From 0a1c51b7c38ece86c6b4c391f6a577ac2aa43566 Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Tue, 6 Jan 2015 17:52:27 -0700 Subject: [PATCH 01/22] modified: app.js Added SIMULATE support for clicking on macros. Added a post command for the SIMULATE function in irsend.js modified: example_configs/config.json A new example config for simulated buttons -> **this could be automated** modified: static/js/app/core.js added an onclick event for the app.js post simulate function buttons modified: templates/index.swig New Index layout that uses the config.json to create "Areas" for macros. created a 3 column remote page which can be organized by changing the layout of your lircd.conf file. modified: test/fixtures/config.json Added config arrays for simulate functions, Area macro sections, etc. check file for more. modified: test/lirc_web.js added a test --- app.js | 26 +++- example_configs/config.json | 240 +++++++++++++++++++++++++++++++++--- static/js/app/core.js | 10 ++ templates/index.swig | 111 +++++++++++++---- test/fixtures/config.json | 172 ++++++++++++++++++++++++-- test/lirc_web.js | 4 + 6 files changed, 505 insertions(+), 58 deletions(-) diff --git a/app.js b/app.js index 2e809cc..9f37f98 100644 --- a/app.js +++ b/app.js @@ -90,7 +90,6 @@ app.get('/macros/:macro.json', function(req, res) { } }); - // Send :remote/:command one time app.post('/remotes/:remote/:command', function(req, res) { lirc_node.irsend.send_once(req.params.remote, req.params.command, function() {}); @@ -98,6 +97,13 @@ app.post('/remotes/:remote/:command', function(req, res) { res.send(200); }); +// Send the remote command as a SIMULATE action in Lirc +app.post('/remotes/:remote/:command/:code/simulate', function(req, res) { + lirc_node.irsend.simulate(req.params.code + ' 00 ' + req.params.command + ' ' + req.params.remote, function() {}); + res.setHeader('Cache-Control', 'no-cache'); + res.send(200); +}); + // Start sending :remote/:command repeatedly app.post('/remotes/:remote/:command/send_start', function(req, res) { lirc_node.irsend.send_start(req.params.remote, req.params.command, function() {}); @@ -128,11 +134,21 @@ app.post('/macros/:macro', function(req, res) { // increment i = i + 1; - if (command[0] == "delay") { + if (command[0] == "delay") + { setTimeout(nextCommand, command[1]); - } else { - // By default, wait 100msec before calling next command - lirc_node.irsend.send_once(command[0], command[1], function() { setTimeout(nextCommand, 100); }); + } + else if(command[0] == "SIMULATE") + { + var code = config.codes[command[1]][command[2]]; + + var codeString = code + " 00 " + command[2] + " " + command[1]; + + lirc_node.irsend.simulate(codeString, function() { setTimeout(nextCommand, 100); }); + } + else + { + lirc_node.irsend.send_once(command[1], command[2], function() { setTimeout(nextCommand, 100); }); } }; diff --git a/example_configs/config.json b/example_configs/config.json index dd6436e..1074019 100644 --- a/example_configs/config.json +++ b/example_configs/config.json @@ -1,27 +1,233 @@ { +"colors":{ + "colorShow":{ + "0": "#000099", + "1": "#3399FF", + "2": "#CC33FF", + "3": "#FF0000", + "4": "#003300", + "5": "#00CC00", + "6": "#669999", + "7": "#663300", + "8": "#666633" + } + }, + + "simulators":{ + "Outlets":{ + "Upstairs_Outlet_On": true, + "Upstairs_Outlet_Off": true, + "Downstairs_Outlet_On": true, + "Downstairs_Outlet_Off": true + } + }, + + "codes":{ + "Outlets":{ + "Upstairs_Outlet_On": "0000000000000001", + "Upstairs_Outlet_Off": "0000000000000002", + "Downstairs_Outlet_On": "0000000000000003", + "Downstairs_Outlet_Off": "0000000000000004" + } + }, + "repeaters": { - "SonyTV": { - "VolumeUp": true, - "VolumeDown": true + "Receiver": { + "Vol+": true, + "Vol-": true + }, + "Receiver_Zone2": { + "Vol+": true, + "Vol-": true } }, - "macros": { - "Xbox360": [ - { "SonyTV": "Power" }, - { "SonyTV": "Xbox360" }, - { "Yamaha": "Power" }, - { "Yamaha": "Xbox360" }, - { "Xbox360": "Power" } - ] - }, + "macros": { + "Living Room": { + "Turn Off": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOff" ], + [ "SEND_ONCE", "Receiver", "DiscreteOff" ], + [ "delay", "1000", "1000"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_Off"] + ], + "Apple Tv": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "750", "750"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOn" ], + [ "SEND_ONCE", "Receiver", "AppleTv" ], + [ "SEND_ONCE", "SamsungTv", "HDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ] + ], + "Plex": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "750", "750"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOn" ], + [ "SEND_ONCE", "Receiver", "AppleTv" ], + [ "SEND_ONCE", "SamsungTv", "HDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Down" ], + [ "SEND_ONCE", "AppleTv", "Right" ], + [ "SEND_ONCE", "AppleTv", "Select" ] + ], + "Netflix": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "750", "750"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOn" ], + [ "SEND_ONCE", "Receiver", "AppleTv" ], + [ "SEND_ONCE", "SamsungTv", "HDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Down" ], + [ "SEND_ONCE", "AppleTv", "Right" ], + [ "SEND_ONCE", "AppleTv", "Right" ], + [ "SEND_ONCE", "AppleTv", "Select" ] + ], + "Cable": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOff" ], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_Off"], + [ "delay", "750", "750"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_Off"], + [ "SEND_ONCE", "SamsungTv", "Tv" ], + [ "delay", "2000", "2000"], + [ "SEND_ONCE", "SamsungTv", "Tv" ], + [ "delay", "3000", "3000"], + [ "SEND_ONCE", "SamsungTv", "Tv" ], + [ "delay", "4000", "4000"] + ], + "Radio": [ + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "500", "500"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOn" ], + [ "SEND_ONCE", "Receiver", "Tuner" ] + ] + }, + "Downstairs": { + "Cable": [ + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "500", "500"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "4500", "4500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteHDMI2" ] + ], + "Apple Tv": [ + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "500", "500"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "4500", "4500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteHDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ] + ], + "Turn Off": [ + [ "SEND_ONCE", "Basement", "LGDiscreteOff" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOff" ], + [ "delay", "5000", "5000"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_Off"], + [ "delay", "1000", "1000"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_Off"] + ], + "Mute All": [ + [ "SEND_ONCE", "Receiver", "Mute" ], + [ "SEND_ONCE", "Receiver_Zone2", "Mute" ], + [ "SEND_ONCE", "Cable", "Mute" ] + ] + }, + "Fish Tank": { + "Skimmer": [ + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On1"], + [ "delay", "500", "500"] + ], + "Return Pump": [ + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "500", "500"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "4500", "4500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteHDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ] + ], + "Power Heads": [ + [ "SEND_ONCE", "Basement", "LGDiscreteOff" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOff" ], + [ "delay", "5000", "5000"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_Off"], + [ "delay", "1000", "1000"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_Off"] + ], + "Sump Light": [ + [ "SEND_ONCE", "Receiver", "Mute" ], + [ "SEND_ONCE", "Receiver_Zone2", "Mute" ], + [ "SEND_ONCE", "Cable", "Mute" ] + ] + } +}, + "commandLabels": { - "Yamaha": { - "Xbox360": "Xbox 360", - "VolumeUp": "Volume Up", - "VolumeDown": "Volume Down" + "LircNamespace": { + "KEY_POWER": "Power", + "KEY_VOLUMEUP": "Vol+", + "KEY_VOLUMEDOWN": "Vol-", + "KEY_CHANNELUP": "Channel Up", + "KEY_CHANNELDOWN": "Channel Down" } }, "remoteLabels": { - "Xbox360": "Xbox 360" + "LircNamespace": "LIRC namespace" } } diff --git a/static/js/app/core.js b/static/js/app/core.js index f899419..8ceda51 100644 --- a/static/js/app/core.js +++ b/static/js/app/core.js @@ -27,6 +27,16 @@ $(function() { error: function(xhr, type) {} }); }); + + //command-simulator buttons send a command as a SIMULATE Lirc event + $('.command-simulator').on('click', function(evt) { + $.ajax({ + type: "POST", + url: $(this).attr('href')+'/simulate', + success: function(data) {}, + error: function(xhr, type) {} + }); + }); // command-repeater buttons repeatedly send the command while being clicked // (uses send_start and send_stop behind the scenes) diff --git a/templates/index.swig b/templates/index.swig index 134bd6d..840c1b4 100644 --- a/templates/index.swig +++ b/templates/index.swig @@ -1,6 +1,64 @@ + @@ -19,43 +77,50 @@ Universal Remote - -
+{% for macro in macros %} + {% set area = loop.key %} + +
+

{{area}}

+ {% for aMacroCommand in macro %} + {% set macroName = loop.key %} + + {% endfor %} +
+{% endfor %} - + - - + - + + + +
Status on and ready...
+ + diff --git a/test/fixtures/config.json b/test/fixtures/config.json index 1a3e2b4..63fafea 100644 --- a/test/fixtures/config.json +++ b/test/fixtures/config.json @@ -1,21 +1,167 @@ { + "simulators":{ + "Outlets":{ + "Upstairs_Outlet_On": true, + "Upstairs_Outlet_Off": true, + "Downstairs_Outlet_On": true, + "Downstairs_Outlet_Off": true + } + }, + + "codes":{ + "Outlets":{ + "Upstairs_Outlet_On": "0000000000000001", + "Upstairs_Outlet_Off": "0000000000000002", + "Downstairs_Outlet_On": "0000000000000003", + "Downstairs_Outlet_Off": "0000000000000004" + } + }, + "repeaters": { - "SonyTV": { - "VolumeUp": true, - "VolumeDown": true + "Receiver": { + "Vol+": true, + "Vol-": true + }, + "Receiver_Zone2": { + "Vol+": true, + "Vol-": true } }, "macros": { - "Play Xbox 360": [ - [ "SonyTV", "Power" ], - [ "SonyTV", "Xbox360" ], - [ "Yamaha", "Power" ], - [ "Yamaha", "Xbox360" ], - [ "Xbox360", "Power" ] - ], - "Listen to Music": [ - [ "Yamaha", "Power" ], - [ "Yamaha", "AirPlay" ] + "Turn Off": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOff" ], + [ "SEND_ONCE", "Receiver", "DiscreteOff" ], + [ "delay", "1000", "1000"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_Off"] + ], + "Apple Tv": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "750", "750"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOn" ], + [ "SEND_ONCE", "Receiver", "AppleTv" ], + [ "SEND_ONCE", "SamsungTv", "HDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ] + ], + "Plex": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "750", "750"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOn" ], + [ "SEND_ONCE", "Receiver", "AppleTv" ], + [ "SEND_ONCE", "SamsungTv", "HDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Down" ], + [ "SEND_ONCE", "AppleTv", "Right" ], + [ "SEND_ONCE", "AppleTv", "Select" ] + ], +"Netflix": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "750", "750"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOn" ], + [ "SEND_ONCE", "Receiver", "AppleTv" ], + [ "SEND_ONCE", "SamsungTv", "HDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Down" ], + [ "SEND_ONCE", "AppleTv", "Right" ], + [ "SEND_ONCE", "AppleTv", "Right" ], + [ "SEND_ONCE", "AppleTv", "Select" ] + ], + "Cable": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOff" ], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_Off"], + [ "delay", "750", "750"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_Off"], + [ "SEND_ONCE", "SamsungTv", "Tv" ], + [ "delay", "2000", "2000"], + [ "SEND_ONCE", "SamsungTv", "Tv" ], + [ "delay", "3000", "3000"], + [ "SEND_ONCE", "SamsungTv", "Tv" ], + [ "delay", "4000", "4000"] + ], +"Radio": [ + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "500", "500"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOn" ], + [ "SEND_ONCE", "Receiver", "Tuner" ] + ] +}, + +"downstairsmacros": { +"Cable": [ + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "500", "500"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "4500", "4500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteHDMI2" ] + ], + "Apple Tv": [ + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "500", "500"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "4500", "4500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteHDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ] + ], + "Turn Off": [ + [ "SEND_ONCE", "Basement", "LGDiscreteOff" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOff" ], + [ "delay", "5000", "5000"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_Off"], + [ "delay", "1000", "1000"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_Off"] + ], + "Mute All": [ + [ "SEND_ONCE", "Receiver", "Mute" ], + [ "SEND_ONCE", "Receiver_Zone2", "Mute" ], + [ "SEND_ONCE", "Cable", "Mute" ] ] }, "commandLabels": { diff --git a/test/lirc_web.js b/test/lirc_web.js index ec4360e..95bfef7 100644 --- a/test/lirc_web.js +++ b/test/lirc_web.js @@ -45,6 +45,10 @@ describe('lirc_web', function() { it('should have POST route to start repeatedly sending a command', function(done) { assert(request(app).post('/remotes/tv/volumeup/send_start').expect(200, done)); }); + + it('should have POST route to send a simulate command', function(done) { + assert(request(app).post('/remotes/:remote/:command/:code/simulate').expect(200, done)); + }); it('should have POST route to stop repeatedly sending a command', function(done) { assert(request(app).post('/remotes/tv/volumeup/send_stop').expect(200, done)); From 8e7469502b4280bf92f23405965fad959f115feb Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Tue, 6 Jan 2015 18:12:22 -0700 Subject: [PATCH 02/22] Update index.swig Added a button press notification window that notifies users of buttons that macros are pressing. Fades away after 5 seconds. New layout for macros. You can now create "Areas" for sets of macros. --- templates/index.swig | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/templates/index.swig b/templates/index.swig index 840c1b4..69042a2 100644 --- a/templates/index.swig +++ b/templates/index.swig @@ -10,7 +10,6 @@ window.onscroll = function() { var v = document.getElementById("statusText"); - v.style.position = "fixed"; v.style.bottom = "0px"; } @@ -34,9 +33,7 @@ function removeExtraText() { clearInterval(counter); - counter = setInterval('decreaseOpacity(.05)', 100); - //document.getElementById("statusText").innerHTML = ""; } function decreaseOpacity(val) @@ -78,26 +75,26 @@ Universal Remote -{% for macro in macros %} - {% set area = loop.key %} - -
-

{{area}}

- {% for aMacroCommand in macro %} - {% set macroName = loop.key %} - - {% endfor %} -
-{% endfor %} + {% for macro in macros %} + {% set area = loop.key %} + +
+

{{area}}

+ {% for aMacroCommand in macro %} + {% set macroName = loop.key %} + + {% endfor %} +
+ {% endfor %}
- {% for remote in remotes %} - {% set remoteName = loop.key %} - {{ labelForRemote(remoteName) }} - {% endfor %} -
+ {% for remote in remotes %} + {% set remoteName = loop.key %} + {{ labelForRemote(remoteName) }} + {% endfor %} + @@ -114,9 +111,6 @@ {% endfor %} - - -
Status on and ready...
From 1cc85c273879d988fb03cfa0529e16edee9faab8 Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Tue, 6 Jan 2015 18:18:58 -0700 Subject: [PATCH 03/22] Update app.js Had to repair the macro function so that it would support the use of simulated buttons. Added post command for simulate --- app.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/app.js b/app.js index 9f37f98..ac9089f 100644 --- a/app.js +++ b/app.js @@ -134,20 +134,20 @@ app.post('/macros/:macro', function(req, res) { // increment i = i + 1; - if (command[0] == "delay") - { - setTimeout(nextCommand, command[1]); - } - else if(command[0] == "SIMULATE") - { - var code = config.codes[command[1]][command[2]]; - - var codeString = code + " 00 " + command[2] + " " + command[1]; - - lirc_node.irsend.simulate(codeString, function() { setTimeout(nextCommand, 100); }); - } - else - { + if (command[0] == "delay") + { + setTimeout(nextCommand, command[1]); + } + else if(command[0] == "SIMULATE") + { + var code = config.codes[command[1]][command[2]]; + + var codeString = code + " 00 " + command[2] + " " + command[1]; + + lirc_node.irsend.simulate(codeString, function() { setTimeout(nextCommand, 100); }); + } + else + { lirc_node.irsend.send_once(command[1], command[2], function() { setTimeout(nextCommand, 100); }); } }; From e4005520d2ff2171748af05567ec2a3c9e26edc3 Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Wed, 7 Jan 2015 19:36:57 -0700 Subject: [PATCH 04/22] Update config.json --- example_configs/config.json | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/example_configs/config.json b/example_configs/config.json index 1074019..afd401e 100644 --- a/example_configs/config.json +++ b/example_configs/config.json @@ -1,18 +1,4 @@ { -"colors":{ - "colorShow":{ - "0": "#000099", - "1": "#3399FF", - "2": "#CC33FF", - "3": "#FF0000", - "4": "#003300", - "5": "#00CC00", - "6": "#669999", - "7": "#663300", - "8": "#666633" - } - }, - "simulators":{ "Outlets":{ "Upstairs_Outlet_On": true, From fa00e74c119b242f4d9744ac063479af3f7be534 Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Fri, 9 Jan 2015 23:55:51 -0700 Subject: [PATCH 05/22] Added Moment nodejs Auto timers have been added and the app now uses moment.js to manage dates and times. --- app.js | 109 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 18 deletions(-) diff --git a/app.js b/app.js index 9f37f98..9890014 100644 --- a/app.js +++ b/app.js @@ -8,10 +8,12 @@ var express = require('express'), path = require('path'), swig = require('swig'), labels = require('./lib/labels'); - +var moment = require('moment-timezone'); // Precompile templates var JST = { - index: swig.compileFile(__dirname + '/templates/index.swig') + index: swig.compileFile(__dirname + '/templates/index.swig'), + schedule: swig.compileFile(__dirname + '/templates/schedule.swig') + }; // Create app @@ -46,6 +48,77 @@ if (process.env.NODE_ENV == 'test' || process.env.NODE_ENV == 'development') { } } +createTimers(); + +function createTimers() +{ + var daysOfWeek = ["SUN", "MON", "TUE", "WED", "THUR", "FRI", "SAT"]; + + for(var i = 0; i < config.schedule["items"].length; i++) + { + var currDate = moment().tz("" + config.schedule["timezone"][0]); + var daysIndex; + for(var j = 0; j < daysOfWeek.length; j++) + { + if(config.schedule["items"][i][3] == daysOfWeek[j]) + daysIndex = j; + } + + var daysFromNow; + + if(currDate.day() == daysIndex) + { + //if the current hour is greater than the desired hour + if(currDate.hour() > config.schedule["items"][i][4]) + { + daysFromNow = 7; + } + else if(currDate.hour() == config.schedule["items"][i][4]) + { + if(currDate.minute() >= config.schedule["items"][i][5]) + daysFromNow = 7; + else + daysFromNow = 0; + } + else + { + daysFromNow = 0; + } + } + else if(currDate.day() < daysIndex) + { + daysFromNow = daysIndex - currDate.day(); + } + else + { + daysFromNow = (6 - currDate.day()) + daysIndex+1; + } + + var dater = currDate.year() + "-0" + (currDate.month()+1) + "-0" + currDate.date() + " 00:00"; + + var tempDay = moment.tz(dater, ""+config.schedule["timezone"][0]); + tempDay.add(daysFromNow, 'days'); + tempDay.hour(config.schedule["items"][i][4]); + tempDay.minute(config.schedule["items"][i][5]); + + if(config.schedule["items"][i][0] == "SEND_ONCE") + { + setTimeout(sendOnce, tempDay.diff(currDate), config.schedule["items"][i][1], config.schedule["items"][i][2]); + } + else if(config.schedule["items"][i][0] == "SIMULATE") + { + lirc_node.irsend.simulate(req.params.code + ' 00 ' + req.params.command + ' ' + req.params.remote, function() {}); + + } + } + +} + +function sendOnce(command1, command2) +{ + lirc_node.irsend.send_once(command1, command2, function() { }); + console.log("Schedule Triggered. Remote " + command1+ " and Command: " + command2); +} // Routes @@ -57,8 +130,11 @@ app.get('/', function(req, res) { remotes: lirc_node.remotes, macros: config.macros, repeaters: config.repeaters, + simulators: config.simulators, + codes: config.codes, labelForRemote: labelFor.remote, - labelForCommand: labelFor.command + labelForCommand: labelFor.command, + items: config.schedule["items"] })); }); @@ -119,35 +195,32 @@ app.post('/remotes/:remote/:command/send_stop', function(req, res) { }); // Execute a macro (a collection of commands to one or more remotes) -app.post('/macros/:macro', function(req, res) { +app.post('/macros/:area/:macro', function(req, res) { // If the macro exists, execute each command in the macro with 100msec // delay between each command. - if (config.macros && config.macros[req.params.macro]) { + if (config.macros && config.macros[req.params.area]) { var i = 0; var nextCommand = function() { - var command = config.macros[req.params.macro][i]; + var command = config.macros[req.params.area][req.params.macro][i]; if (!command) { return true; } // increment i = i + 1; - if (command[0] == "delay") - { + if (command[0] == "delay") { setTimeout(nextCommand, command[1]); - } - else if(command[0] == "SIMULATE") - { - var code = config.codes[command[1]][command[2]]; + } else if(command[0] == "SIMULATE"){ + + var code = config.codes[command[1]][command[2]]; + + var codeString = code + " 00 " + command[2] + " " + command[1]; - var codeString = code + " 00 " + command[2] + " " + command[1]; - - lirc_node.irsend.simulate(codeString, function() { setTimeout(nextCommand, 100); }); - } - else - { + lirc_node.irsend.simulate(codeString, function() { setTimeout(nextCommand, 100); }); + } else { + // By default, wait 100msec before calling next command lirc_node.irsend.send_once(command[1], command[2], function() { setTimeout(nextCommand, 100); }); } }; From a6154d8c0e21468bb2b19d5e24a4d41666e379eb Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Fri, 9 Jan 2015 23:56:20 -0700 Subject: [PATCH 06/22] Examples for Schedules added --- example_configs/config.json | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/example_configs/config.json b/example_configs/config.json index 1074019..424cd2b 100644 --- a/example_configs/config.json +++ b/example_configs/config.json @@ -1,17 +1,18 @@ { -"colors":{ - "colorShow":{ - "0": "#000099", - "1": "#3399FF", - "2": "#CC33FF", - "3": "#FF0000", - "4": "#003300", - "5": "#00CC00", - "6": "#669999", - "7": "#663300", - "8": "#666633" - } - }, +"schedule": { + "items": [ + [ "SEND_ONCE", "Receiver_Zone2", "Power", "MON", 1, 1 ], + [ "SEND_ONCE", "Receiver_Zone2", "VolUp2", "TUE", 19, 0 ], + [ "SEND_ONCE", "Receiver_Zone2", "VolUp3", "WED", 23, 50 ], + [ "SEND_ONCE", "Receiver_Zone2", "Power4", "THUR", 2, 50 ], + [ "SEND_ONCE", "Receiver_Zone2", "VolUp5", "FRI", 6, 0 ], + [ "SEND_ONCE", "Receiver_Zone2", "VolUp6", "SAT", 23,58 ], + [ "SEND_ONCE", "Receiver_Zone2", "Power7", "SUN", 6,0 ] + ], + "timezone": [ + [ "America/Denver" ] + ] +}, "simulators":{ "Outlets":{ From d4ee9cc6710db7f039e4fd4b62d91d5666c52875 Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Fri, 9 Jan 2015 23:57:17 -0700 Subject: [PATCH 07/22] Dependencies added The moment.js files are also needed on the client side to display when items are scheduled to go off. --- Gruntfile.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gruntfile.js b/Gruntfile.js index f4c12d6..7a0e180 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -15,6 +15,8 @@ module.exports = function(grunt) { src: ['static/js/vendor/zepto.min.js', 'static/js/vendor/zepto.touch.js', 'static/js/vendor/fastclick.js', + 'static/js/vendor/moment.min.js', + 'static/js/vendor/moment-timezone.js', 'static/js/app/*.js'], dest: 'static/js/compiled/app.js' } From 635473a73b37ab5eb9e070a4fc2973e05e86a953 Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Fri, 9 Jan 2015 23:58:00 -0700 Subject: [PATCH 08/22] Nodejs Dependencies added Moment dependencies for the nodejs server have been updated. --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 9a2871f..ec8a3d1 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "express": "3.0.6", "lirc_node": "*", "swig": "0.13.5", - "consolidate": "*" + "consolidate": "*", + "moment": "2.9.0", + "moment-timezone": "0.2.5" }, "devDependencies": { "mocha": "*", From 77e0c5bca7ddf382ea68ce372efe03efe28ee261 Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Fri, 9 Jan 2015 23:59:34 -0700 Subject: [PATCH 09/22] Modified the display of some items Added a margin to the bottom for the status indicator. Added styling for the "View Schedule" button. --- static/css/app.less | 86 +++++++++++++++++++------------------ static/css/compiled/app.css | 44 +++++++++++++++++-- 2 files changed, 85 insertions(+), 45 deletions(-) diff --git a/static/css/app.less b/static/css/app.less index 7a0ee4e..8c374c7 100644 --- a/static/css/app.less +++ b/static/css/app.less @@ -1,112 +1,110 @@ -// Colors -@colorWetAsphalt: #34495E; -@colorConcrete: #95A5A6; -@colorSilver: #BDC3C7; -@colorClouds: #ECF0F1; -@colorPeterRiver: #3498DB; -@colorGreenSea: #16A085; -@colorTurqoise: #1ABC9C; - html { height: 100%; } - body { height: 100%; } - body { + margin: 0 0 50px 0; + padding: 70px 0 150px 0; + -webkit-touch-callout: none; + -webkit-text-size-adjust: none; + -webkit-user-select: none; + -webkit-highlight: none; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +.colorSync body { + background-color: #000; margin: 0; padding: 70px 0 0 0; - -webkit-touch-callout: none; -webkit-text-size-adjust: none; -webkit-user-select: none; -webkit-highlight: none; - -webkit-tap-highlight-color: rgba(0,0,0,0); + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } - ul { list-style-type: none; margin: 0; padding: 0; } - .commands li { margin: 20px 0; padding: 0; } - h1 { - background: @colorWetAsphalt; + background: #34495e; color: #fff; margin: 0 0 30px; padding: 10px 0; text-align: center; z-index: 5; - left: 0; position: fixed; top: 0; width: 100%; - - &.is-remote { - background: @colorPeterRiver; - } } - +h1.is-remote { + background: #3498db; +} .command { margin: 20px 0; } - .command:nth-child(even) .btn-primary { - background: @colorGreenSea; + background: #16a085; } - .no-touch .command-link:hover { background: #2fe2bf; } - .no-touch .command-link:active { background: #16a085; } - .command-link.active { background: #2fe2bf !important; } - .remote-link.active { background: #5dade2 !important; } - .btn-wide { padding-left: 0; padding-right: 0; width: 100%; } - .remote { margin: 0; padding: 0; position: relative; } - -.remotes-nav, -.macros-nav { +.remotes-nav { + text-align: center; } - -.remotes-nav li, -.macros-nav li { - margin: 20px 0; +.remotes-nav a { + margin-left: auto; + margin-right: auto; + width: 33%; + height: 25px; + margin: 0px 0px 5px 5px; } +.scheduleBtn { + text-align: center; +} +.scheduleBtn a { + margin-left: auto; + margin-right: auto; + width: 50%; + height: 25px; + margin: 0px 0px 5px 5px; +} +.macros-nav button { + margin: 0px 0px 5px 5px; +} .back { position: absolute; top: 7px; left: 8px; cursor: pointer; } - a, a:hover, a:active, @@ -119,19 +117,23 @@ a:active, transition: 0s !important; -webkit-backface-visibility: hidden !important; } - #container { margin: 0 40px; } - .remote { display: none; } - .remote.active { display: block; } +.scheduledItems { + display: none; +} +.scheduledItems.active { + display: block; +} + .hidden { display: none !important; } diff --git a/static/css/compiled/app.css b/static/css/compiled/app.css index 7d85f34..8c374c7 100644 --- a/static/css/compiled/app.css +++ b/static/css/compiled/app.css @@ -5,6 +5,16 @@ body { height: 100%; } body { + margin: 0 0 50px 0; + padding: 70px 0 150px 0; + -webkit-touch-callout: none; + -webkit-text-size-adjust: none; + -webkit-user-select: none; + -webkit-highlight: none; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +.colorSync body { + background-color: #000; margin: 0; padding: 70px 0 0 0; -webkit-touch-callout: none; @@ -65,9 +75,29 @@ h1.is-remote { padding: 0; position: relative; } -.remotes-nav li, -.macros-nav li { - margin: 20px 0; +.remotes-nav { + text-align: center; +} +.remotes-nav a { + margin-left: auto; + margin-right: auto; + width: 33%; + height: 25px; + margin: 0px 0px 5px 5px; +} + +.scheduleBtn { + text-align: center; +} +.scheduleBtn a { + margin-left: auto; + margin-right: auto; + width: 50%; + height: 25px; + margin: 0px 0px 5px 5px; +} +.macros-nav button { + margin: 0px 0px 5px 5px; } .back { position: absolute; @@ -96,6 +126,14 @@ a:active, .remote.active { display: block; } + +.scheduledItems { + display: none; +} +.scheduledItems.active { + display: block; +} + .hidden { display: none !important; } From 58d775270d26fe7b7d5e0e7c3ca73a7628eb8f43 Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Sat, 10 Jan 2015 00:00:51 -0700 Subject: [PATCH 10/22] Added proper classes to jquery button presses Added proper 'hidden' classes and other for switching to the view schedule 'page'. --- static/js/app/core.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/static/js/app/core.js b/static/js/app/core.js index 8ceda51..626cad0 100644 --- a/static/js/app/core.js +++ b/static/js/app/core.js @@ -27,8 +27,8 @@ $(function() { error: function(xhr, type) {} }); }); - - //command-simulator buttons send a command as a SIMULATE Lirc event + + // command-simulator buttons send a single command acting as an LIRC simulator when clicked $('.command-simulator').on('click', function(evt) { $.ajax({ type: "POST", @@ -100,6 +100,8 @@ $(function() { // Back button shown on remote pages $('.back').on('click', function(evt) { $('.remote.active').removeClass('active'); + $('.scheduledItems.active').removeClass('active'); + $('.scheduleBtn').removeClass('hidden'); $('.remotes-nav').removeClass('hidden'); $('.macros-nav').removeClass('hidden'); $('.back').addClass('hidden'); @@ -113,6 +115,19 @@ $(function() { var href = $(this).attr('href'); $('.remotes-nav').addClass('hidden'); $('.macros-nav').addClass('hidden'); + $('.scheduleBtn').addClass('hidden'); + $(href).addClass('active'); + $('.back').removeClass('hidden'); + $('#title').html($(this).html()); + $('#titlebar').addClass('is-remote'); + }); + +$('.scheduleBtn a').on('click', function(evt) { + evt.preventDefault(); + var href = $(this).attr('href'); + $('.remotes-nav').addClass('hidden'); + $('.macros-nav').addClass('hidden'); + $('.scheduleBtn').addClass('hidden'); $(href).addClass('active'); $('.back').removeClass('hidden'); $('#title').html($(this).html()); @@ -122,5 +137,4 @@ $(function() { // Remove 300ms delay after tapping OSUR.fastClick = new FastClick(document.body); -}); - +}); \ No newline at end of file From 17f15f56aabfa63a2a958e6bcd1613fb804daa88 Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Sat, 10 Jan 2015 00:01:10 -0700 Subject: [PATCH 11/22] For grunt to uglify --- static/js/vendor/moment-timezone.js | 401 ++++++++++++++++++++++++++++ static/js/vendor/moment.min.js | 7 + 2 files changed, 408 insertions(+) create mode 100644 static/js/vendor/moment-timezone.js create mode 100644 static/js/vendor/moment.min.js diff --git a/static/js/vendor/moment-timezone.js b/static/js/vendor/moment-timezone.js new file mode 100644 index 0000000..870e1eb --- /dev/null +++ b/static/js/vendor/moment-timezone.js @@ -0,0 +1,401 @@ +//! moment-timezone.js +//! version : 0.2.5 +//! author : Tim Wood +//! license : MIT +//! github.com/moment/moment-timezone + +(function (root, factory) { + "use strict"; + + /*global define*/ + if (typeof define === 'function' && define.amd) { + define(['moment'], factory); // AMD + } else if (typeof exports === 'object') { + module.exports = factory(require('moment')); // Node + } else { + factory(root.moment); // Browser + } +}(this, function (moment) { + "use strict"; + + // Do not load moment-timezone a second time. + if (moment.tz !== undefined) { return moment; } + + var VERSION = "0.2.5", + zones = {}, + links = {}, + + momentVersion = moment.version.split('.'), + major = +momentVersion[0], + minor = +momentVersion[1]; + + // Moment.js version check + if (major < 2 || (major === 2 && minor < 6)) { + logError('Moment Timezone requires Moment.js >= 2.6.0. You are using Moment.js ' + moment.version + '. See momentjs.com'); + } + + /************************************ + Unpacking + ************************************/ + + function charCodeToInt(charCode) { + if (charCode > 96) { + return charCode - 87; + } else if (charCode > 64) { + return charCode - 29; + } + return charCode - 48; + } + + function unpackBase60(string) { + var i = 0, + parts = string.split('.'), + whole = parts[0], + fractional = parts[1] || '', + multiplier = 1, + num, + out = 0, + sign = 1; + + // handle negative numbers + if (string.charCodeAt(0) === 45) { + i = 1; + sign = -1; + } + + // handle digits before the decimal + for (i; i < whole.length; i++) { + num = charCodeToInt(whole.charCodeAt(i)); + out = 60 * out + num; + } + + // handle digits after the decimal + for (i = 0; i < fractional.length; i++) { + multiplier = multiplier / 60; + num = charCodeToInt(fractional.charCodeAt(i)); + out += num * multiplier; + } + + return out * sign; + } + + function arrayToInt (array) { + for (var i = 0; i < array.length; i++) { + array[i] = unpackBase60(array[i]); + } + } + + function intToUntil (array, length) { + for (var i = 0; i < length; i++) { + array[i] = Math.round((array[i - 1] || 0) + (array[i] * 60000)); // minutes to milliseconds + } + + array[length - 1] = Infinity; + } + + function mapIndices (source, indices) { + var out = [], i; + + for (i = 0; i < indices.length; i++) { + out[i] = source[indices[i]]; + } + + return out; + } + + function unpack (string) { + var data = string.split('|'), + offsets = data[2].split(' '), + indices = data[3].split(''), + untils = data[4].split(' '); + + arrayToInt(offsets); + arrayToInt(indices); + arrayToInt(untils); + + intToUntil(untils, indices.length); + + return { + name : data[0], + abbrs : mapIndices(data[1].split(' '), indices), + offsets : mapIndices(offsets, indices), + untils : untils + }; + } + + /************************************ + Zone object + ************************************/ + + function Zone (packedString) { + if (packedString) { + this._set(unpack(packedString)); + } + } + + Zone.prototype = { + _set : function (unpacked) { + this.name = unpacked.name; + this.abbrs = unpacked.abbrs; + this.untils = unpacked.untils; + this.offsets = unpacked.offsets; + }, + + _index : function (timestamp) { + var target = +timestamp, + untils = this.untils, + i; + + for (i = 0; i < untils.length; i++) { + if (target < untils[i]) { + return i; + } + } + }, + + parse : function (timestamp) { + var target = +timestamp, + offsets = this.offsets, + untils = this.untils, + max = untils.length - 1, + offset, offsetNext, offsetPrev, i; + + for (i = 0; i < max; i++) { + offset = offsets[i]; + offsetNext = offsets[i + 1]; + offsetPrev = offsets[i ? i - 1 : i]; + + if (offset < offsetNext && tz.moveAmbiguousForward) { + offset = offsetNext; + } else if (offset > offsetPrev && tz.moveInvalidForward) { + offset = offsetPrev; + } + + if (target < untils[i] - (offset * 60000)) { + return offsets[i]; + } + } + + return offsets[max]; + }, + + abbr : function (mom) { + return this.abbrs[this._index(mom)]; + }, + + offset : function (mom) { + return this.offsets[this._index(mom)]; + } + }; + + /************************************ + Global Methods + ************************************/ + + function normalizeName (name) { + return (name || '').toLowerCase().replace(/\//g, '_'); + } + + function addZone (packed) { + var i, zone, zoneName; + + if (typeof packed === "string") { + packed = [packed]; + } + + for (i = 0; i < packed.length; i++) { + zone = new Zone(packed[i]); + zoneName = normalizeName(zone.name); + zones[zoneName] = zone; + upgradeLinksToZones(zoneName); + } + } + + function getZone (name) { + return zones[normalizeName(name)] || null; + } + + function getNames () { + var i, out = []; + + for (i in zones) { + if (zones.hasOwnProperty(i) && zones[i]) { + out.push(zones[i].name); + } + } + + return out.sort(); + } + + function addLink (aliases) { + var i, alias; + + if (typeof aliases === "string") { + aliases = [aliases]; + } + + for (i = 0; i < aliases.length; i++) { + alias = aliases[i].split('|'); + pushLink(alias[0], alias[1]); + pushLink(alias[1], alias[0]); + } + } + + function upgradeLinksToZones (zoneName) { + if (!links[zoneName]) { + return; + } + + var i, + zone = zones[zoneName], + linkNames = links[zoneName]; + + for (i = 0; i < linkNames.length; i++) { + copyZoneWithName(zone, linkNames[i]); + } + + links[zoneName] = null; + } + + function copyZoneWithName (zone, name) { + var linkZone = zones[normalizeName(name)] = new Zone(); + linkZone._set(zone); + linkZone.name = name; + } + + function pushLink (zoneName, linkName) { + zoneName = normalizeName(zoneName); + + if (zones[zoneName]) { + copyZoneWithName(zones[zoneName], linkName); + } else { + links[zoneName] = links[zoneName] || []; + links[zoneName].push(linkName); + } + } + + function loadData (data) { + addZone(data.zones); + addLink(data.links); + tz.dataVersion = data.version; + } + + function zoneExists (name) { + if (!zoneExists.didShowError) { + zoneExists.didShowError = true; + logError("moment.tz.zoneExists('" + name + "') has been deprecated in favor of !moment.tz.zone('" + name + "')"); + } + return !!getZone(name); + } + + function needsOffset (m) { + return !!(m._a && (m._tzm === undefined)); + } + + function logError (message) { + if (typeof console !== 'undefined' && typeof console.error === 'function') { + console.error(message); + } + } + + /************************************ + moment.tz namespace + ************************************/ + + function tz () { + var args = Array.prototype.slice.call(arguments, 0, -1), + name = arguments[arguments.length - 1], + zone = getZone(name), + out = moment.utc.apply(null, args); + + if (zone && needsOffset(out)) { + out.add(zone.parse(out), 'minutes'); + } + + out.tz(name); + + return out; + } + + tz.version = VERSION; + tz.dataVersion = ''; + tz._zones = zones; + tz._links = links; + tz.add = addZone; + tz.link = addLink; + tz.load = loadData; + tz.zone = getZone; + tz.zoneExists = zoneExists; // deprecated in 0.1.0 + tz.names = getNames; + tz.Zone = Zone; + tz.unpack = unpack; + tz.unpackBase60 = unpackBase60; + tz.needsOffset = needsOffset; + tz.moveInvalidForward = true; + tz.moveAmbiguousForward = false; + + /************************************ + Interface with Moment.js + ************************************/ + + var fn = moment.fn; + + moment.tz = tz; + + moment.updateOffset = function (mom, keepTime) { + var offset; + if (mom._z) { + offset = mom._z.offset(mom); + if (Math.abs(offset) < 16) { + offset = offset / 60; + } + mom.zone(offset, keepTime); + } + }; + + fn.tz = function (name) { + if (name) { + this._z = getZone(name); + if (this._z) { + moment.updateOffset(this); + } else { + logError("Moment Timezone has no data for " + name + ". See http://momentjs.com/timezone/docs/#/data-loading/."); + } + return this; + } + if (this._z) { return this._z.name; } + }; + + function abbrWrap (old) { + return function () { + if (this._z) { return this._z.abbr(this); } + return old.call(this); + }; + } + + function resetZoneWrap (old) { + return function () { + this._z = null; + return old.apply(this, arguments); + }; + } + + fn.zoneName = abbrWrap(fn.zoneName); + fn.zoneAbbr = abbrWrap(fn.zoneAbbr); + fn.utc = resetZoneWrap(fn.utc); + + // Cloning a moment should include the _z property. + var momentProperties = moment.momentProperties; + if (Object.prototype.toString.call(momentProperties) === '[object Array]') { + // moment 2.8.1+ + momentProperties.push('_z'); + momentProperties.push('_a'); + } else if (momentProperties) { + // moment 2.7.0 + momentProperties._z = null; + } + + // INJECT DATA + + return moment; +})); diff --git a/static/js/vendor/moment.min.js b/static/js/vendor/moment.min.js new file mode 100644 index 0000000..024d488 --- /dev/null +++ b/static/js/vendor/moment.min.js @@ -0,0 +1,7 @@ +//! moment.js +//! version : 2.9.0 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com +(function(a){function b(a,b,c){switch(arguments.length){case 2:return null!=a?a:b;case 3:return null!=a?a:null!=b?b:c;default:throw new Error("Implement me")}}function c(a,b){return Bb.call(a,b)}function d(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function e(a){vb.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+a)}function f(a,b){var c=!0;return o(function(){return c&&(e(a),c=!1),b.apply(this,arguments)},b)}function g(a,b){sc[a]||(e(b),sc[a]=!0)}function h(a,b){return function(c){return r(a.call(this,c),b)}}function i(a,b){return function(c){return this.localeData().ordinal(a.call(this,c),b)}}function j(a,b){var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),f=a.clone().add(e,"months");return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function k(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function l(){}function m(a,b){b!==!1&&H(a),p(this,a),this._d=new Date(+a._d),uc===!1&&(uc=!0,vb.updateOffset(this),uc=!1)}function n(a){var b=A(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._milliseconds=+k+1e3*j+6e4*i+36e5*h,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=vb.localeData(),this._bubble()}function o(a,b){for(var d in b)c(b,d)&&(a[d]=b[d]);return c(b,"toString")&&(a.toString=b.toString),c(b,"valueOf")&&(a.valueOf=b.valueOf),a}function p(a,b){var c,d,e;if("undefined"!=typeof b._isAMomentObject&&(a._isAMomentObject=b._isAMomentObject),"undefined"!=typeof b._i&&(a._i=b._i),"undefined"!=typeof b._f&&(a._f=b._f),"undefined"!=typeof b._l&&(a._l=b._l),"undefined"!=typeof b._strict&&(a._strict=b._strict),"undefined"!=typeof b._tzm&&(a._tzm=b._tzm),"undefined"!=typeof b._isUTC&&(a._isUTC=b._isUTC),"undefined"!=typeof b._offset&&(a._offset=b._offset),"undefined"!=typeof b._pf&&(a._pf=b._pf),"undefined"!=typeof b._locale&&(a._locale=b._locale),Kb.length>0)for(c in Kb)d=Kb[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function q(a){return 0>a?Math.ceil(a):Math.floor(a)}function r(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.lengthd;d++)(c&&a[d]!==b[d]||!c&&C(a[d])!==C(b[d]))&&g++;return g+f}function z(a){if(a){var b=a.toLowerCase().replace(/(.)s$/,"$1");a=lc[a]||mc[b]||b}return a}function A(a){var b,d,e={};for(d in a)c(a,d)&&(b=z(d),b&&(e[b]=a[d]));return e}function B(b){var c,d;if(0===b.indexOf("week"))c=7,d="day";else{if(0!==b.indexOf("month"))return;c=12,d="month"}vb[b]=function(e,f){var g,h,i=vb._locale[b],j=[];if("number"==typeof e&&(f=e,e=a),h=function(a){var b=vb().utc().set(d,a);return i.call(vb._locale,b,e||"")},null!=f)return h(f);for(g=0;c>g;g++)j.push(h(g));return j}}function C(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function D(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function E(a,b,c){return jb(vb([a,11,31+b-c]),b,c).week}function F(a){return G(a)?366:365}function G(a){return a%4===0&&a%100!==0||a%400===0}function H(a){var b;a._a&&-2===a._pf.overflow&&(b=a._a[Db]<0||a._a[Db]>11?Db:a._a[Eb]<1||a._a[Eb]>D(a._a[Cb],a._a[Db])?Eb:a._a[Fb]<0||a._a[Fb]>24||24===a._a[Fb]&&(0!==a._a[Gb]||0!==a._a[Hb]||0!==a._a[Ib])?Fb:a._a[Gb]<0||a._a[Gb]>59?Gb:a._a[Hb]<0||a._a[Hb]>59?Hb:a._a[Ib]<0||a._a[Ib]>999?Ib:-1,a._pf._overflowDayOfYear&&(Cb>b||b>Eb)&&(b=Eb),a._pf.overflow=b)}function I(b){return null==b._isValid&&(b._isValid=!isNaN(b._d.getTime())&&b._pf.overflow<0&&!b._pf.empty&&!b._pf.invalidMonth&&!b._pf.nullInput&&!b._pf.invalidFormat&&!b._pf.userInvalidated,b._strict&&(b._isValid=b._isValid&&0===b._pf.charsLeftOver&&0===b._pf.unusedTokens.length&&b._pf.bigHour===a)),b._isValid}function J(a){return a?a.toLowerCase().replace("_","-"):a}function K(a){for(var b,c,d,e,f=0;f0;){if(d=L(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&y(e,c,!0)>=b-1)break;b--}f++}return null}function L(a){var b=null;if(!Jb[a]&&Lb)try{b=vb.locale(),require("./locale/"+a),vb.locale(b)}catch(c){}return Jb[a]}function M(a,b){var c,d;return b._isUTC?(c=b.clone(),d=(vb.isMoment(a)||x(a)?+a:+vb(a))-+c,c._d.setTime(+c._d+d),vb.updateOffset(c,!1),c):vb(a).local()}function N(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function O(a){var b,c,d=a.match(Pb);for(b=0,c=d.length;c>b;b++)d[b]=rc[d[b]]?rc[d[b]]:N(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function P(a,b){return a.isValid()?(b=Q(b,a.localeData()),nc[b]||(nc[b]=O(b)),nc[b](a)):a.localeData().invalidDate()}function Q(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Qb.lastIndex=0;d>=0&&Qb.test(a);)a=a.replace(Qb,c),Qb.lastIndex=0,d-=1;return a}function R(a,b){var c,d=b._strict;switch(a){case"Q":return _b;case"DDDD":return bc;case"YYYY":case"GGGG":case"gggg":return d?cc:Tb;case"Y":case"G":case"g":return ec;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return d?dc:Ub;case"S":if(d)return _b;case"SS":if(d)return ac;case"SSS":if(d)return bc;case"DDD":return Sb;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Wb;case"a":case"A":return b._locale._meridiemParse;case"x":return Zb;case"X":return $b;case"Z":case"ZZ":return Xb;case"T":return Yb;case"SSSS":return Vb;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return d?ac:Rb;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return Rb;case"Do":return d?b._locale._ordinalParse:b._locale._ordinalParseLenient;default:return c=new RegExp($(Z(a.replace("\\","")),"i"))}}function S(a){a=a||"";var b=a.match(Xb)||[],c=b[b.length-1]||[],d=(c+"").match(jc)||["-",0,0],e=+(60*d[1])+C(d[2]);return"+"===d[0]?e:-e}function T(a,b,c){var d,e=c._a;switch(a){case"Q":null!=b&&(e[Db]=3*(C(b)-1));break;case"M":case"MM":null!=b&&(e[Db]=C(b)-1);break;case"MMM":case"MMMM":d=c._locale.monthsParse(b,a,c._strict),null!=d?e[Db]=d:c._pf.invalidMonth=b;break;case"D":case"DD":null!=b&&(e[Eb]=C(b));break;case"Do":null!=b&&(e[Eb]=C(parseInt(b.match(/\d{1,2}/)[0],10)));break;case"DDD":case"DDDD":null!=b&&(c._dayOfYear=C(b));break;case"YY":e[Cb]=vb.parseTwoDigitYear(b);break;case"YYYY":case"YYYYY":case"YYYYYY":e[Cb]=C(b);break;case"a":case"A":c._meridiem=b;break;case"h":case"hh":c._pf.bigHour=!0;case"H":case"HH":e[Fb]=C(b);break;case"m":case"mm":e[Gb]=C(b);break;case"s":case"ss":e[Hb]=C(b);break;case"S":case"SS":case"SSS":case"SSSS":e[Ib]=C(1e3*("0."+b));break;case"x":c._d=new Date(C(b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=S(b);break;case"dd":case"ddd":case"dddd":d=c._locale.weekdaysParse(b),null!=d?(c._w=c._w||{},c._w.d=d):c._pf.invalidWeekday=b;break;case"w":case"ww":case"W":case"WW":case"d":case"e":case"E":a=a.substr(0,1);case"gggg":case"GGGG":case"GGGGG":a=a.substr(0,2),b&&(c._w=c._w||{},c._w[a]=C(b));break;case"gg":case"GG":c._w=c._w||{},c._w[a]=vb.parseTwoDigitYear(b)}}function U(a){var c,d,e,f,g,h,i;c=a._w,null!=c.GG||null!=c.W||null!=c.E?(g=1,h=4,d=b(c.GG,a._a[Cb],jb(vb(),1,4).year),e=b(c.W,1),f=b(c.E,1)):(g=a._locale._week.dow,h=a._locale._week.doy,d=b(c.gg,a._a[Cb],jb(vb(),g,h).year),e=b(c.w,1),null!=c.d?(f=c.d,g>f&&++e):f=null!=c.e?c.e+g:g),i=kb(d,e,f,h,g),a._a[Cb]=i.year,a._dayOfYear=i.dayOfYear}function V(a){var c,d,e,f,g=[];if(!a._d){for(e=X(a),a._w&&null==a._a[Eb]&&null==a._a[Db]&&U(a),a._dayOfYear&&(f=b(a._a[Cb],e[Cb]),a._dayOfYear>F(f)&&(a._pf._overflowDayOfYear=!0),d=fb(f,0,a._dayOfYear),a._a[Db]=d.getUTCMonth(),a._a[Eb]=d.getUTCDate()),c=0;3>c&&null==a._a[c];++c)a._a[c]=g[c]=e[c];for(;7>c;c++)a._a[c]=g[c]=null==a._a[c]?2===c?1:0:a._a[c];24===a._a[Fb]&&0===a._a[Gb]&&0===a._a[Hb]&&0===a._a[Ib]&&(a._nextDay=!0,a._a[Fb]=0),a._d=(a._useUTC?fb:eb).apply(null,g),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[Fb]=24)}}function W(a){var b;a._d||(b=A(a._i),a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],V(a))}function X(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function Y(b){if(b._f===vb.ISO_8601)return void ab(b);b._a=[],b._pf.empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=Q(b._f,b._locale).match(Pb)||[],c=0;c0&&b._pf.unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),rc[f]?(d?b._pf.empty=!1:b._pf.unusedTokens.push(f),T(f,d,b)):b._strict&&!d&&b._pf.unusedTokens.push(f);b._pf.charsLeftOver=i-j,h.length>0&&b._pf.unusedInput.push(h),b._pf.bigHour===!0&&b._a[Fb]<=12&&(b._pf.bigHour=a),b._a[Fb]=k(b._locale,b._a[Fb],b._meridiem),V(b),H(b)}function Z(a){return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e})}function $(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function _(a){var b,c,e,f,g;if(0===a._f.length)return a._pf.invalidFormat=!0,void(a._d=new Date(0/0));for(f=0;fg)&&(e=g,c=b));o(a,c||b)}function ab(a){var b,c,d=a._i,e=fc.exec(d);if(e){for(a._pf.iso=!0,b=0,c=hc.length;c>b;b++)if(hc[b][1].exec(d)){a._f=hc[b][0]+(e[6]||" ");break}for(b=0,c=ic.length;c>b;b++)if(ic[b][1].exec(d)){a._f+=ic[b][0];break}d.match(Xb)&&(a._f+="Z"),Y(a)}else a._isValid=!1}function bb(a){ab(a),a._isValid===!1&&(delete a._isValid,vb.createFromInputFallback(a))}function cb(a,b){var c,d=[];for(c=0;ca&&h.setFullYear(a),h}function fb(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function gb(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function hb(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function ib(a,b,c){var d=vb.duration(a).abs(),e=Ab(d.as("s")),f=Ab(d.as("m")),g=Ab(d.as("h")),h=Ab(d.as("d")),i=Ab(d.as("M")),j=Ab(d.as("y")),k=e0,k[4]=c,hb.apply({},k)}function jb(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=vb(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function kb(a,b,c,d,e){var f,g,h=fb(a,0,1).getUTCDay();return h=0===h?7:h,c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:F(a-1)+g}}function lb(b){var c,d=b._i,e=b._f;return b._locale=b._locale||vb.localeData(b._l),null===d||e===a&&""===d?vb.invalid({nullInput:!0}):("string"==typeof d&&(b._i=d=b._locale.preparse(d)),vb.isMoment(d)?new m(d,!0):(e?w(e)?_(b):Y(b):db(b),c=new m(b),c._nextDay&&(c.add(1,"d"),c._nextDay=a),c))}function mb(a,b){var c,d;if(1===b.length&&w(b[0])&&(b=b[0]),!b.length)return vb();for(c=b[0],d=1;d=0?"+":"-";return b+r(Math.abs(a),6)},gg:function(){return r(this.weekYear()%100,2)},gggg:function(){return r(this.weekYear(),4)},ggggg:function(){return r(this.weekYear(),5)},GG:function(){return r(this.isoWeekYear()%100,2)},GGGG:function(){return r(this.isoWeekYear(),4)},GGGGG:function(){return r(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return C(this.milliseconds()/100)},SS:function(){return r(C(this.milliseconds()/10),2)},SSS:function(){return r(this.milliseconds(),3)},SSSS:function(){return r(this.milliseconds(),3)},Z:function(){var a=this.utcOffset(),b="+";return 0>a&&(a=-a,b="-"),b+r(C(a/60),2)+":"+r(C(a)%60,2)},ZZ:function(){var a=this.utcOffset(),b="+";return 0>a&&(a=-a,b="-"),b+r(C(a/60),2)+r(C(a)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},x:function(){return this.valueOf()},X:function(){return this.unix()},Q:function(){return this.quarter()}},sc={},tc=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"],uc=!1;pc.length;)xb=pc.pop(),rc[xb+"o"]=i(rc[xb],xb);for(;qc.length;)xb=qc.pop(),rc[xb+xb]=h(rc[xb],2);rc.DDDD=h(rc.DDD,3),o(l.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a,b,c){var d,e,f;for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){if(e=vb.utc([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=vb([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM D, YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.apply(b,[c]):d},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",_ordinalParse:/\d{1,2}/,preparse:function(a){return a},postformat:function(a){return a},week:function(a){return jb(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},firstDayOfWeek:function(){return this._week.dow},firstDayOfYear:function(){return this._week.doy},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),vb=function(b,c,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._i=b,g._f=c,g._l=e,g._strict=f,g._isUTC=!1,g._pf=d(),lb(g)},vb.suppressDeprecationWarnings=!1,vb.createFromInputFallback=f("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),vb.min=function(){var a=[].slice.call(arguments,0);return mb("isBefore",a)},vb.max=function(){var a=[].slice.call(arguments,0);return mb("isAfter",a)},vb.utc=function(b,c,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._useUTC=!0,g._isUTC=!0,g._l=e,g._i=b,g._f=c,g._strict=f,g._pf=d(),lb(g).utc()},vb.unix=function(a){return vb(1e3*a)},vb.duration=function(a,b){var d,e,f,g,h=a,i=null;return vb.isDuration(a)?h={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(h={},b?h[b]=a:h.milliseconds=a):(i=Nb.exec(a))?(d="-"===i[1]?-1:1,h={y:0,d:C(i[Eb])*d,h:C(i[Fb])*d,m:C(i[Gb])*d,s:C(i[Hb])*d,ms:C(i[Ib])*d}):(i=Ob.exec(a))?(d="-"===i[1]?-1:1,f=function(a){var b=a&&parseFloat(a.replace(",","."));return(isNaN(b)?0:b)*d},h={y:f(i[2]),M:f(i[3]),d:f(i[4]),h:f(i[5]),m:f(i[6]),s:f(i[7]),w:f(i[8])}):null==h?h={}:"object"==typeof h&&("from"in h||"to"in h)&&(g=t(vb(h.from),vb(h.to)),h={},h.ms=g.milliseconds,h.M=g.months),e=new n(h),vb.isDuration(a)&&c(a,"_locale")&&(e._locale=a._locale),e},vb.version=yb,vb.defaultFormat=gc,vb.ISO_8601=function(){},vb.momentProperties=Kb,vb.updateOffset=function(){},vb.relativeTimeThreshold=function(b,c){return oc[b]===a?!1:c===a?oc[b]:(oc[b]=c,!0)},vb.lang=f("moment.lang is deprecated. Use moment.locale instead.",function(a,b){return vb.locale(a,b)}),vb.locale=function(a,b){var c;return a&&(c="undefined"!=typeof b?vb.defineLocale(a,b):vb.localeData(a),c&&(vb.duration._locale=vb._locale=c)),vb._locale._abbr},vb.defineLocale=function(a,b){return null!==b?(b.abbr=a,Jb[a]||(Jb[a]=new l),Jb[a].set(b),vb.locale(a),Jb[a]):(delete Jb[a],null)},vb.langData=f("moment.langData is deprecated. Use moment.localeData instead.",function(a){return vb.localeData(a)}),vb.localeData=function(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return vb._locale;if(!w(a)){if(b=L(a))return b;a=[a]}return K(a)},vb.isMoment=function(a){return a instanceof m||null!=a&&c(a,"_isAMomentObject")},vb.isDuration=function(a){return a instanceof n};for(xb=tc.length-1;xb>=0;--xb)B(tc[xb]);vb.normalizeUnits=function(a){return z(a)},vb.invalid=function(a){var b=vb.utc(0/0);return null!=a?o(b._pf,a):b._pf.userInvalidated=!0,b},vb.parseZone=function(){return vb.apply(null,arguments).parseZone()},vb.parseTwoDigitYear=function(a){return C(a)+(C(a)>68?1900:2e3)},vb.isDate=x,o(vb.fn=m.prototype,{clone:function(){return vb(this)},valueOf:function(){return+this._d-6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var a=vb(this).utc();return 00:!1},parsingFlags:function(){return o({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(a){return this.utcOffset(0,a)},local:function(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(this._dateUtcOffset(),"m")),this},format:function(a){var b=P(this,a||vb.defaultFormat);return this.localeData().postformat(b)},add:u(1,"add"),subtract:u(-1,"subtract"),diff:function(a,b,c){var d,e,f=M(a,this),g=6e4*(f.utcOffset()-this.utcOffset());return b=z(b),"year"===b||"month"===b||"quarter"===b?(e=j(this,f),"quarter"===b?e/=3:"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:q(e)},from:function(a,b){return vb.duration({to:this,from:a}).locale(this.locale()).humanize(!b)},fromNow:function(a){return this.from(vb(),a)},calendar:function(a){var b=a||vb(),c=M(b,this).startOf("day"),d=this.diff(c,"days",!0),e=-6>d?"sameElse":-1>d?"lastWeek":0>d?"lastDay":1>d?"sameDay":2>d?"nextDay":7>d?"nextWeek":"sameElse";return this.format(this.localeData().calendar(e,this,vb(b)))},isLeapYear:function(){return G(this.year())},isDST:function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},day:function(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=gb(a,this.localeData()),this.add(a-b,"d")):b},month:qb("Month",!0),startOf:function(a){switch(a=z(a)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a?this.weekday(0):"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this},endOf:function(b){return b=z(b),b===a||"millisecond"===b?this:this.startOf(b).add(1,"isoWeek"===b?"week":b).subtract(1,"ms")},isAfter:function(a,b){var c;return b=z("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=vb.isMoment(a)?a:vb(a),+this>+a):(c=vb.isMoment(a)?+a:+vb(a),c<+this.clone().startOf(b))},isBefore:function(a,b){var c;return b=z("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=vb.isMoment(a)?a:vb(a),+a>+this):(c=vb.isMoment(a)?+a:+vb(a),+this.clone().endOf(b)a?this:a}),max:f("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(a){return a=vb.apply(null,arguments),a>this?this:a}),zone:f("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",function(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}),utcOffset:function(a,b){var c,d=this._offset||0;return null!=a?("string"==typeof a&&(a=S(a)),Math.abs(a)<16&&(a=60*a),!this._isUTC&&b&&(c=this._dateUtcOffset()),this._offset=a,this._isUTC=!0,null!=c&&this.add(c,"m"),d!==a&&(!b||this._changeInProgress?v(this,vb.duration(a-d,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,vb.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?d:this._dateUtcOffset()},isLocal:function(){return!this._isUTC},isUtcOffset:function(){return this._isUTC},isUtc:function(){return this._isUTC&&0===this._offset},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(S(this._i)),this},hasAlignedHourOffset:function(a){return a=a?vb(a).utcOffset():0,(this.utcOffset()-a)%60===0},daysInMonth:function(){return D(this.year(),this.month())},dayOfYear:function(a){var b=Ab((vb(this).startOf("day")-vb(this).startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")},quarter:function(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)},weekYear:function(a){var b=jb(this,this.localeData()._week.dow,this.localeData()._week.doy).year;return null==a?b:this.add(a-b,"y")},isoWeekYear:function(a){var b=jb(this,1,4).year;return null==a?b:this.add(a-b,"y")},week:function(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")},isoWeek:function(a){var b=jb(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")},weekday:function(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},isoWeeksInYear:function(){return E(this.year(),1,4)},weeksInYear:function(){var a=this.localeData()._week;return E(this.year(),a.dow,a.doy)},get:function(a){return a=z(a),this[a]()},set:function(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else a=z(a),"function"==typeof this[a]&&this[a](b);return this},locale:function(b){var c;return b===a?this._locale._abbr:(c=vb.localeData(b),null!=c&&(this._locale=c),this)},lang:f("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(b){return b===a?this.localeData():this.locale(b)}),localeData:function(){return this._locale},_dateUtcOffset:function(){return 15*-Math.round(this._d.getTimezoneOffset()/15)}}),vb.fn.millisecond=vb.fn.milliseconds=qb("Milliseconds",!1),vb.fn.second=vb.fn.seconds=qb("Seconds",!1),vb.fn.minute=vb.fn.minutes=qb("Minutes",!1),vb.fn.hour=vb.fn.hours=qb("Hours",!0),vb.fn.date=qb("Date",!0),vb.fn.dates=f("dates accessor is deprecated. Use date instead.",qb("Date",!0)),vb.fn.year=qb("FullYear",!0),vb.fn.years=f("years accessor is deprecated. Use year instead.",qb("FullYear",!0)),vb.fn.days=vb.fn.day,vb.fn.months=vb.fn.month,vb.fn.weeks=vb.fn.week,vb.fn.isoWeeks=vb.fn.isoWeek,vb.fn.quarters=vb.fn.quarter,vb.fn.toJSON=vb.fn.toISOString,vb.fn.isUTC=vb.fn.isUtc,o(vb.duration.fn=n.prototype,{_bubble:function(){var a,b,c,d=this._milliseconds,e=this._days,f=this._months,g=this._data,h=0;g.milliseconds=d%1e3,a=q(d/1e3),g.seconds=a%60,b=q(a/60),g.minutes=b%60,c=q(b/60),g.hours=c%24,e+=q(c/24),h=q(rb(e)),e-=q(sb(h)),f+=q(e/30),e%=30,h+=q(f/12),f%=12,g.days=e,g.months=f,g.years=h},abs:function(){return this._milliseconds=Math.abs(this._milliseconds),this._days=Math.abs(this._days),this._months=Math.abs(this._months),this._data.milliseconds=Math.abs(this._data.milliseconds),this._data.seconds=Math.abs(this._data.seconds),this._data.minutes=Math.abs(this._data.minutes),this._data.hours=Math.abs(this._data.hours),this._data.months=Math.abs(this._data.months),this._data.years=Math.abs(this._data.years),this},weeks:function(){return q(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*C(this._months/12) +},humanize:function(a){var b=ib(this,!a,this.localeData());return a&&(b=this.localeData().pastFuture(+this,b)),this.localeData().postformat(b)},add:function(a,b){var c=vb.duration(a,b);return this._milliseconds+=c._milliseconds,this._days+=c._days,this._months+=c._months,this._bubble(),this},subtract:function(a,b){var c=vb.duration(a,b);return this._milliseconds-=c._milliseconds,this._days-=c._days,this._months-=c._months,this._bubble(),this},get:function(a){return a=z(a),this[a.toLowerCase()+"s"]()},as:function(a){var b,c;if(a=z(a),"month"===a||"year"===a)return b=this._days+this._milliseconds/864e5,c=this._months+12*rb(b),"month"===a?c:c/12;switch(b=this._days+Math.round(sb(this._months/12)),a){case"week":return b/7+this._milliseconds/6048e5;case"day":return b+this._milliseconds/864e5;case"hour":return 24*b+this._milliseconds/36e5;case"minute":return 24*b*60+this._milliseconds/6e4;case"second":return 24*b*60*60+this._milliseconds/1e3;case"millisecond":return Math.floor(24*b*60*60*1e3)+this._milliseconds;default:throw new Error("Unknown unit "+a)}},lang:vb.fn.lang,locale:vb.fn.locale,toIsoString:f("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",function(){return this.toISOString()}),toISOString:function(){var a=Math.abs(this.years()),b=Math.abs(this.months()),c=Math.abs(this.days()),d=Math.abs(this.hours()),e=Math.abs(this.minutes()),f=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"},localeData:function(){return this._locale},toJSON:function(){return this.toISOString()}}),vb.duration.fn.toString=vb.duration.fn.toISOString;for(xb in kc)c(kc,xb)&&tb(xb.toLowerCase());vb.duration.fn.asMilliseconds=function(){return this.as("ms")},vb.duration.fn.asSeconds=function(){return this.as("s")},vb.duration.fn.asMinutes=function(){return this.as("m")},vb.duration.fn.asHours=function(){return this.as("h")},vb.duration.fn.asDays=function(){return this.as("d")},vb.duration.fn.asWeeks=function(){return this.as("weeks")},vb.duration.fn.asMonths=function(){return this.as("M")},vb.duration.fn.asYears=function(){return this.as("y")},vb.locale("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===C(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),Lb?module.exports=vb:"function"==typeof define&&define.amd?(define(function(a,b,c){return c.config&&c.config()&&c.config().noGlobal===!0&&(zb.moment=wb),vb}),ub(!0)):ub()}).call(this); \ No newline at end of file From 5e637ea16e58789e677a1b152b504384d82a9ea3 Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Sat, 10 Jan 2015 00:03:24 -0700 Subject: [PATCH 12/22] Added a table for listing schedules swig doesnt have a very good for loop syntax so i vouched for creating a table out using javascript. now the user can see how much time there is until one of their remotes will be triggered. --- templates/index.swig | 187 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 181 insertions(+), 6 deletions(-) diff --git a/templates/index.swig b/templates/index.swig index 840c1b4..9a1dbb4 100644 --- a/templates/index.swig +++ b/templates/index.swig @@ -5,8 +5,12 @@ window.onload = function() { window.onscroll(); + startCountDowns(); }; + var daysOfWeek = ["SUN", "MON", "TUE", "WED", "THUR", "FRI", "SAT"]; + var items = []; + window.onscroll = function() { var v = document.getElementById("statusText"); @@ -58,7 +62,171 @@ } } - + function startCountDowns(command) + { + items = []; + var oldTable = document.getElementById("ScheduleTable"); + if(oldTable) + oldTable.parentNode.removeChild(oldTable); + + {% for item in items%} + {% set colorName = loop.key%} + {% set colorIndex = loop.index0%} + var array = []; + {% for eachItem in item%} + array.push("{{eachItem}}"); + {% endfor %} + + items.push(array); + {% endfor %} + + var newTable = document.createElement("table"); + newTable.style.width = "100%"; + newTable.id = "ScheduleTable"; + var newRow = document.createElement("tr"); + var newHeader1 = document.createElement("th"); + var header1Text = "Remote"; + var header1Node = document.createTextNode(header1Text); + newHeader1.appendChild(header1Node); + newRow.appendChild(newHeader1); + var newHeader2 = document.createElement("th"); + var header2Text = "Command"; + var header2Node = document.createTextNode(header2Text); + newHeader2.appendChild(header2Node); + newRow.appendChild(newHeader2); + var newHeader3 = document.createElement("th"); + var header3Text = "Triggered In"; + var header3Node = document.createTextNode(header3Text); + newHeader3.appendChild(header3Node); + newRow.appendChild(newHeader3); + newTable.appendChild(newRow); + + for(var i = 0; i < items.length; i++) + { + var currDate = moment(); + console.log("Current Time!!!: " + currDate.format()); + var daysIndex; + for(var j = 0; j < daysOfWeek.length; j++) + { + if(items[i][3] == daysOfWeek[j]) + daysIndex = j; + } + + var daysFromNow; + + if(currDate.day() == daysIndex) + { + //if the current hour is greater than the desired hour + if(currDate.hour() > items[i][4]) + { + daysFromNow = 7; + } + else if(currDate.hour() == items[i][4]) + { + if(currDate.minute() >= items[i][5]) + daysFromNow = 7; + else + daysFromNow = 0; + } + else + { + daysFromNow = 0; + } + } + else if(currDate.day() < daysIndex) + { + daysFromNow = daysIndex - currDate.day(); + } + else + { + daysFromNow = (6 - currDate.day()) + daysIndex+1; + } + + //console.log("Days From Now: " + daysFromNow); + var dater = currDate.year() + "-0" + (currDate.month()+1) + "-0" + currDate.date() + " 00:00"; + + var tempDay = moment(dater); + tempDay.add(daysFromNow, 'days'); + tempDay.hour(items[i][4]); + tempDay.minute(items[i][5]); + + //console.log(tempDay.format()); + //console.log("From Now: " + tempDay.diff(currDate)); + //console.log(currDate.format()); + + var timeText = secondsToString(tempDay.diff(currDate)*0.001); + + var newRow = document.createElement("tr"); + var newColumn = document.createElement("td"); + newColumn.align = "center"; + var remoteText = items[i][1]; + var remoteTextNode = document.createTextNode(remoteText ); + newColumn.appendChild(remoteTextNode ); + newRow.appendChild(newColumn); + + var newColumn1 = document.createElement("td"); + newColumn1.align = "center"; + var commandText = items[i][2]; + var commandTextNode = document.createTextNode(commandText ); + newColumn1.appendChild(commandTextNode ); + newRow.appendChild(newColumn1); + + var newColumn2 = document.createElement("td"); + newColumn2.align = "center"; + newColumn2.id = i + items[i][1]; + var triggerText = timeText; + var triggerTextNode = document.createTextNode(triggerText ); + newColumn2.appendChild(triggerTextNode ); + newRow.appendChild(newColumn2); + + newTable.appendChild(newRow); + + setTimeout(updateTimer, 1000, i, tempDay.diff(currDate), items[i][1], items[i][2]); + } + + var tableSpace = document.getElementById("scheduledItems"); + tableSpace.insertBefore(newTable, tableSpace .childNodes[0]); + } + + function updateTimer(element, time, remote, command) + { + var timeText = secondsToString((time - 1000)*0.001); + //console.log(timeText); + var newElement = document.getElementById(element + remote); + newElement .innerHTML = timeText; + if(time <= 0) + { + startCountDowns(); + } + else + { + setTimeout(updateTimer, 1000, element, time-1000, remote, command); + } + } + + function secondsToString(seconds) + { + var numyears = Math.floor(seconds / 31536000); + var numdays = Math.floor((seconds % 31536000) / 86400); + var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600); + var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60); + var numseconds = Math.round((((seconds % 31536000) % 86400) % 3600) % 60); + + var output = ""; + if(numyears > 0) + output += numyears + " years "; + if(numdays > 0) + output += numdays + " days "; + if(numhours > 0) + output += numhours + " hours "; + if(numminutes > 0) + output += numminutes + " minutes "; + if(numseconds) + output += numseconds + " seconds"; + return output; + } + + @@ -90,15 +258,18 @@ {% endfor %} -
-
+
{% for remote in remotes %} {% set remoteName = loop.key %} - {{ labelForRemote(remoteName) }} + {{ labelForRemote(remoteName) }} {% endfor %} +
+ @@ -114,12 +285,16 @@ {% endfor %} - - +
+ +

+ +
Status on and ready...
+ From b06bbe012c4aa86c0d9d084bc1244fed8d689dac Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Sat, 10 Jan 2015 00:27:54 -0700 Subject: [PATCH 13/22] Fixed screwed up merge Has all changed that previous version had. --- app.js | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/app.js b/app.js index 4605100..f2c8c98 100644 --- a/app.js +++ b/app.js @@ -12,8 +12,6 @@ var moment = require('moment-timezone'); // Precompile templates var JST = { index: swig.compileFile(__dirname + '/templates/index.swig'), - schedule: swig.compileFile(__dirname + '/templates/schedule.swig') - }; // Create app @@ -54,6 +52,7 @@ function createTimers() { var daysOfWeek = ["SUN", "MON", "TUE", "WED", "THUR", "FRI", "SAT"]; + for(var i = 0; i < config.schedule["items"].length; i++) { var currDate = moment().tz("" + config.schedule["timezone"][0]); @@ -210,7 +209,6 @@ app.post('/macros/:area/:macro', function(req, res) { // increment i = i + 1; -<<<<<<< HEAD if (command[0] == "delay") { setTimeout(nextCommand, command[1]); } else if(command[0] == "SIMULATE"){ @@ -222,22 +220,6 @@ app.post('/macros/:area/:macro', function(req, res) { lirc_node.irsend.simulate(codeString, function() { setTimeout(nextCommand, 100); }); } else { // By default, wait 100msec before calling next command -======= - if (command[0] == "delay") - { - setTimeout(nextCommand, command[1]); - } - else if(command[0] == "SIMULATE") - { - var code = config.codes[command[1]][command[2]]; - - var codeString = code + " 00 " + command[2] + " " + command[1]; - - lirc_node.irsend.simulate(codeString, function() { setTimeout(nextCommand, 100); }); - } - else - { ->>>>>>> origin/master lirc_node.irsend.send_once(command[1], command[2], function() { setTimeout(nextCommand, 100); }); } }; From b7639a02f6a89164fcfe1c3f17a3e97aafa1a499 Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Sat, 10 Jan 2015 00:28:12 -0700 Subject: [PATCH 14/22] Fixed bad merge Has all changed that previous version had. --- example_configs/config.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/example_configs/config.json b/example_configs/config.json index d56ff0a..424cd2b 100644 --- a/example_configs/config.json +++ b/example_configs/config.json @@ -1,5 +1,4 @@ { -<<<<<<< HEAD "schedule": { "items": [ [ "SEND_ONCE", "Receiver_Zone2", "Power", "MON", 1, 1 ], @@ -15,8 +14,6 @@ ] }, -======= ->>>>>>> origin/master "simulators":{ "Outlets":{ "Upstairs_Outlet_On": true, From 231d0826cf0050a8b38183cc7e39bcede54f0f3d Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Sat, 10 Jan 2015 00:28:21 -0700 Subject: [PATCH 15/22] Fixed bad merge Has all changed that previous version had. --- templates/index.swig | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/templates/index.swig b/templates/index.swig index 34684b5..b7ce4c3 100644 --- a/templates/index.swig +++ b/templates/index.swig @@ -14,6 +14,7 @@ window.onscroll = function() { var v = document.getElementById("statusText"); + v.style.position = "fixed"; v.style.bottom = "0px"; } @@ -37,7 +38,9 @@ function removeExtraText() { clearInterval(counter); + counter = setInterval('decreaseOpacity(.05)', 100); + //document.getElementById("statusText").innerHTML = ""; } function decreaseOpacity(val) @@ -243,20 +246,21 @@ Universal Remote - {% for macro in macros %} - {% set area = loop.key %} +{% for macro in macros %} + {% set area = loop.key %} + +
+

{{area}}

+ {% for aMacroCommand in macro %} + {% set macroName = loop.key %} + + {% endfor %} +
+{% endfor %} + -
-

{{area}}

- {% for aMacroCommand in macro %} - {% set macroName = loop.key %} - - {% endfor %} -
- {% endfor %}
-<<<<<<< HEAD
{% for remote in remotes %} {% set remoteName = loop.key %} @@ -264,13 +268,6 @@ {% endfor %}
-======= - {% for remote in remotes %} - {% set remoteName = loop.key %} - {{ labelForRemote(remoteName) }} - {% endfor %} - ->>>>>>> origin/master
View Schedule @@ -290,19 +287,19 @@ {% endfor %}
-<<<<<<< HEAD

-======= ->>>>>>> origin/master + + + +
Status on and ready...
- From 338b93fca7b98cf5849eb7f745357f6d159c56a5 Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Sat, 10 Jan 2015 01:03:44 -0700 Subject: [PATCH 16/22] Fix for creating dates appending a zero to the beginning of a day or month that is less than 10. --- templates/index.swig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/templates/index.swig b/templates/index.swig index b7ce4c3..9fde415 100644 --- a/templates/index.swig +++ b/templates/index.swig @@ -143,6 +143,17 @@ } //console.log("Days From Now: " + daysFromNow); + var currMonth; + var currDay; + if(currDate.month()+1 < 10) + currMonth = "0" + (currDate.month()+1); + else + currMonth = "" + (currDate.month()+1); + if(currDate.date() < 10) + currDay= "0" + currDate.date(); + else + currDay= "" + currDate.date(); + var dater = currDate.year() + "-0" + (currDate.month()+1) + "-0" + currDate.date() + " 00:00"; var tempDay = moment(dater); From cc871a9cc53f1cc9a80b5a7d0f52d347a97b92bf Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Sat, 10 Jan 2015 01:24:02 -0700 Subject: [PATCH 17/22] Visual Fixes Table now uses bootstrap for nice styling and hover states --- templates/index.swig | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/templates/index.swig b/templates/index.swig index 9fde415..c2fcc00 100644 --- a/templates/index.swig +++ b/templates/index.swig @@ -82,6 +82,7 @@ var newTable = document.createElement("table"); newTable.style.width = "100%"; + newTable.className = "table table-striped table-hover"; newTable.id = "ScheduleTable"; var newRow = document.createElement("tr"); var newHeader1 = document.createElement("th"); @@ -100,6 +101,9 @@ newHeader3.appendChild(header3Node); newRow.appendChild(newHeader3); newTable.appendChild(newRow); + var tableBody = document.createElement("tbody"); + newTable.appendChild(tableBody); + for(var i = 0; i < items.length; i++) { @@ -142,7 +146,7 @@ daysFromNow = (6 - currDate.day()) + daysIndex+1; } - //console.log("Days From Now: " + daysFromNow); + //console.log("Days From Now: " + daysFromNow); var currMonth; var currDay; if(currDate.month()+1 < 10) @@ -154,7 +158,7 @@ else currDay= "" + currDate.date(); - var dater = currDate.year() + "-0" + (currDate.month()+1) + "-0" + currDate.date() + " 00:00"; + var dater = currDate.year() + "-" + currMonth + "-" + currDay + " 00:00"; var tempDay = moment(dater); tempDay.add(daysFromNow, 'days'); @@ -166,7 +170,6 @@ //console.log(currDate.format()); var timeText = secondsToString(tempDay.diff(currDate)*0.001); - var newRow = document.createElement("tr"); var newColumn = document.createElement("td"); newColumn.align = "center"; @@ -190,7 +193,7 @@ newColumn2.appendChild(triggerTextNode ); newRow.appendChild(newColumn2); - newTable.appendChild(newRow); + tableBody.appendChild(newRow); setTimeout(updateTimer, 1000, i, tempDay.diff(currDate), items[i][1], items[i][2]); } @@ -202,7 +205,7 @@ function updateTimer(element, time, remote, command) { var timeText = secondsToString((time - 1000)*0.001); - //console.log(timeText); + console.log("Time Text: " + timeText); var newElement = document.getElementById(element + remote); newElement .innerHTML = timeText; if(time <= 0) @@ -227,13 +230,13 @@ if(numyears > 0) output += numyears + " years "; if(numdays > 0) - output += numdays + " days "; + output += numdays + " d "; if(numhours > 0) - output += numhours + " hours "; + output += numhours + " h "; if(numminutes > 0) - output += numminutes + " minutes "; + output += numminutes + " m "; if(numseconds) - output += numseconds + " seconds"; + output += numseconds + " s"; return output; } From 4d55b1d127fcabe7e4ffab30939845b9dbf4cbb5 Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Sat, 10 Jan 2015 01:30:09 -0700 Subject: [PATCH 18/22] Fixed the same bug that was in the index --- app.js | 9 +++++++++ templates/index.swig | 3 --- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index f2c8c98..215dd43 100644 --- a/app.js +++ b/app.js @@ -93,6 +93,15 @@ function createTimers() daysFromNow = (6 - currDate.day()) + daysIndex+1; } + if(currDate.month()+1 < 10) + currMonth = "0" + (currDate.month()+1); + else + currMonth = "" + (currDate.month()+1); + if(currDate.date() < 10) + currDay= "0" + currDate.date(); + else + currDay= "" + currDate.date(); + var dater = currDate.year() + "-0" + (currDate.month()+1) + "-0" + currDate.date() + " 00:00"; var tempDay = moment.tz(dater, ""+config.schedule["timezone"][0]); diff --git a/templates/index.swig b/templates/index.swig index c2fcc00..f8fd12c 100644 --- a/templates/index.swig +++ b/templates/index.swig @@ -38,9 +38,7 @@ function removeExtraText() { clearInterval(counter); - counter = setInterval('decreaseOpacity(.05)', 100); - //document.getElementById("statusText").innerHTML = ""; } function decreaseOpacity(val) @@ -146,7 +144,6 @@ daysFromNow = (6 - currDate.day()) + daysIndex+1; } - //console.log("Days From Now: " + daysFromNow); var currMonth; var currDay; if(currDate.month()+1 < 10) From bff4f5123ffa3383ed8a44846ab5f0542bdfc5fd Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Sun, 11 Jan 2015 15:50:35 -0700 Subject: [PATCH 19/22] Added proper test and config files for the test Config file has been updated for the tests, and the proper command is now in the test for the simulate function --- test/fixtures/config.json | 338 ++++++++++++++++++++++---------------- test/lirc_web.js | 2 +- 2 files changed, 200 insertions(+), 140 deletions(-) diff --git a/test/fixtures/config.json b/test/fixtures/config.json index 63fafea..b9f8054 100644 --- a/test/fixtures/config.json +++ b/test/fixtures/config.json @@ -1,4 +1,19 @@ { +"schedule": { + "items": [ + [ "SEND_ONCE", "Receiver_Zone2", "Power", "FRI", 1, 1 ], + [ "SEND_ONCE", "Receiver_Zone2", "Power", "SAT", 1, 30 ], + [ "SEND_ONCE", "Receiver_Zone2", "VolUp3", "THUR", 23, 50 ], + [ "SEND_ONCE", "Receiver_Zone2", "Power4", "THUR", 2, 50 ], + [ "SEND_ONCE", "Receiver_Zone2", "VolUp5", "THUR", 6, 0 ], + [ "SEND_ONCE", "Receiver_Zone2", "VolUp6", "THUR", 23,58 ], + [ "SEND_ONCE", "Receiver_Zone2", "Power7", "THUR", 6,0 ] + ], + "timezone": [ + [ "America/Denver" ] + ] +}, + "simulators":{ "Outlets":{ "Upstairs_Outlet_On": true, @@ -19,151 +34,196 @@ "repeaters": { "Receiver": { - "Vol+": true, - "Vol-": true + "VolUp": true, + "VolDown": true }, "Receiver_Zone2": { - "Vol+": true, - "Vol-": true + "VolUp": true, + "VolDown": true + }, + "Cable": { + "VolUp": true, + "VolDown": true } }, - "macros": { - "Turn Off": [ - [ "SEND_ONCE", "SamsungTv", "DiscreteOff" ], - [ "SEND_ONCE", "Receiver", "DiscreteOff" ], - [ "delay", "1000", "1000"], - [ "SIMULATE", "Outlets", "Upstairs_Outlet_Off"] - ], - "Apple Tv": [ - [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], - [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], - [ "delay", "750", "750"], - [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], - [ "delay", "1000", "1000"], - [ "SEND_ONCE", "Receiver", "DiscreteOn" ], - [ "SEND_ONCE", "Receiver", "AppleTv" ], - [ "SEND_ONCE", "SamsungTv", "HDMI1" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ] - ], - "Plex": [ - [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], - [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], - [ "delay", "750", "750"], - [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], - [ "delay", "1000", "1000"], - [ "SEND_ONCE", "Receiver", "DiscreteOn" ], - [ "SEND_ONCE", "Receiver", "AppleTv" ], - [ "SEND_ONCE", "SamsungTv", "HDMI1" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Down" ], - [ "SEND_ONCE", "AppleTv", "Right" ], - [ "SEND_ONCE", "AppleTv", "Select" ] - ], -"Netflix": [ - [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], - [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], - [ "delay", "750", "750"], - [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], - [ "delay", "1000", "1000"], - [ "SEND_ONCE", "Receiver", "DiscreteOn" ], - [ "SEND_ONCE", "Receiver", "AppleTv" ], - [ "SEND_ONCE", "SamsungTv", "HDMI1" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Down" ], - [ "SEND_ONCE", "AppleTv", "Right" ], - [ "SEND_ONCE", "AppleTv", "Right" ], - [ "SEND_ONCE", "AppleTv", "Select" ] - ], - "Cable": [ - [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], - [ "delay", "1000", "1000"], - [ "SEND_ONCE", "Receiver", "DiscreteOff" ], - [ "SIMULATE", "Outlets", "Upstairs_Outlet_Off"], - [ "delay", "750", "750"], - [ "SIMULATE", "Outlets", "Upstairs_Outlet_Off"], - [ "SEND_ONCE", "SamsungTv", "Tv" ], - [ "delay", "2000", "2000"], - [ "SEND_ONCE", "SamsungTv", "Tv" ], - [ "delay", "3000", "3000"], - [ "SEND_ONCE", "SamsungTv", "Tv" ], - [ "delay", "4000", "4000"] - ], -"Radio": [ - [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], - [ "delay", "500", "500"], - [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], - [ "delay", "1000", "1000"], - [ "SEND_ONCE", "Receiver", "DiscreteOn" ], - [ "SEND_ONCE", "Receiver", "Tuner" ] - ] + "macros": { + "Living Room": { + "Turn Off": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOff" ], + [ "SEND_ONCE", "Receiver", "DiscreteOff" ], + [ "delay", "1000", "1000"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_Off"] + ], + "Apple Tv": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "750", "750"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOn" ], + [ "SEND_ONCE", "Receiver", "AppleTv" ], + [ "SEND_ONCE", "SamsungTv", "HDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ] + ], + "Plex": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "750", "750"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOn" ], + [ "SEND_ONCE", "Receiver", "AppleTv" ], + [ "SEND_ONCE", "SamsungTv", "HDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Down" ], + [ "SEND_ONCE", "AppleTv", "Right" ], + [ "SEND_ONCE", "AppleTv", "Select" ] + ], + "Netflix": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "750", "750"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOn" ], + [ "SEND_ONCE", "Receiver", "AppleTv" ], + [ "SEND_ONCE", "SamsungTv", "HDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Down" ], + [ "SEND_ONCE", "AppleTv", "Right" ], + [ "SEND_ONCE", "AppleTv", "Right" ], + [ "SEND_ONCE", "AppleTv", "Select" ] + ], + "Cable": [ + [ "SEND_ONCE", "SamsungTv", "DiscreteOn" ], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOff" ], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_Off"], + [ "delay", "750", "750"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_Off"], + [ "SEND_ONCE", "SamsungTv", "Tv" ], + [ "delay", "2000", "2000"], + [ "SEND_ONCE", "SamsungTv", "Tv" ], + [ "delay", "3000", "3000"], + [ "SEND_ONCE", "SamsungTv", "Tv" ], + [ "delay", "4000", "4000"] + ], + "Radio": [ + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "500", "500"], + [ "SIMULATE", "Outlets", "Upstairs_Outlet_On"], + [ "delay", "1000", "1000"], + [ "SEND_ONCE", "Receiver", "DiscreteOn" ], + [ "SEND_ONCE", "Receiver", "Tuner" ] + ] + }, + "Downstairs": { + "Cable": [ + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "500", "500"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "7000", "7000"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteHDMI2" ] + ], + "Apple Tv": [ + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "500", "500"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "7000", "7000"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteHDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ] + ], + "Turn Off": [ + [ "SEND_ONCE", "Basement", "LGDiscreteOff" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOff" ], + [ "delay", "5000", "5000"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_Off"], + [ "delay", "1000", "1000"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_Off"] + ], + "Mute All": [ + [ "SEND_ONCE", "Receiver", "Mute" ], + [ "SEND_ONCE", "Receiver_Zone2", "Mute" ], + [ "SEND_ONCE", "Cable", "Mute" ] + ] + }, + "Fish Tank": { + "Skimmer": [ + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On1"], + [ "delay", "500", "500"] + ], + "Return Pump": [ + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "500", "500"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], + [ "delay", "4500", "4500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteHDMI1" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ], + [ "SEND_ONCE", "AppleTv", "Menu" ] + ], + "Power Heads": [ + [ "SEND_ONCE", "Basement", "LGDiscreteOff" ], + [ "delay", "500", "500"], + [ "SEND_ONCE", "Basement", "LGDiscreteOff" ], + [ "delay", "5000", "5000"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_Off"], + [ "delay", "1000", "1000"], + [ "SIMULATE", "Outlets", "Downstairs_Outlet_Off"] + ], + "Sump Light": [ + [ "SEND_ONCE", "Receiver", "Mute" ], + [ "SEND_ONCE", "Receiver_Zone2", "Mute" ], + [ "SEND_ONCE", "Cable", "Mute" ] + ] + } + }, -"downstairsmacros": { -"Cable": [ - [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], - [ "delay", "500", "500"], - [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], - [ "delay", "4500", "4500"], - [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], - [ "delay", "500", "500"], - [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], - [ "delay", "500", "500"], - [ "SEND_ONCE", "Basement", "LGDiscreteHDMI2" ] - ], - "Apple Tv": [ - [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], - [ "delay", "500", "500"], - [ "SIMULATE", "Outlets", "Downstairs_Outlet_On"], - [ "delay", "4500", "4500"], - [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], - [ "delay", "500", "500"], - [ "SEND_ONCE", "Basement", "LGDiscreteOn" ], - [ "delay", "500", "500"], - [ "SEND_ONCE", "Basement", "LGDiscreteHDMI1" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ], - [ "SEND_ONCE", "AppleTv", "Menu" ] - ], - "Turn Off": [ - [ "SEND_ONCE", "Basement", "LGDiscreteOff" ], - [ "delay", "500", "500"], - [ "SEND_ONCE", "Basement", "LGDiscreteOff" ], - [ "delay", "5000", "5000"], - [ "SIMULATE", "Outlets", "Downstairs_Outlet_Off"], - [ "delay", "1000", "1000"], - [ "SIMULATE", "Outlets", "Downstairs_Outlet_Off"] - ], - "Mute All": [ - [ "SEND_ONCE", "Receiver", "Mute" ], - [ "SEND_ONCE", "Receiver_Zone2", "Mute" ], - [ "SEND_ONCE", "Cable", "Mute" ] - ] - }, "commandLabels": { "LircNamespace": { "KEY_POWER": "Power", diff --git a/test/lirc_web.js b/test/lirc_web.js index 95bfef7..1f59ed2 100644 --- a/test/lirc_web.js +++ b/test/lirc_web.js @@ -47,7 +47,7 @@ describe('lirc_web', function() { }); it('should have POST route to send a simulate command', function(done) { - assert(request(app).post('/remotes/:remote/:command/:code/simulate').expect(200, done)); + assert(request(app).post('/remotes/Outlets/Upstairs_Outlet_On/0000000000000001/simulate').expect(200, done)); }); it('should have POST route to stop repeatedly sending a command', function(done) { From 44e1ac65a769ed6fef4f95cf7bd4558a6f06f60d Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Sun, 11 Jan 2015 21:46:53 -0700 Subject: [PATCH 20/22] Added snapping to selected location The app will now snap to the top of the screen if you have enough remotes to make you need to scroll --- static/js/app/core.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/static/js/app/core.js b/static/js/app/core.js index 626cad0..0d85b75 100644 --- a/static/js/app/core.js +++ b/static/js/app/core.js @@ -100,8 +100,8 @@ $(function() { // Back button shown on remote pages $('.back').on('click', function(evt) { $('.remote.active').removeClass('active'); - $('.scheduledItems.active').removeClass('active'); - $('.scheduleBtn').removeClass('hidden'); + $('.scheduledItems.active').removeClass('active'); + $('.scheduleBtn').removeClass('hidden'); $('.remotes-nav').removeClass('hidden'); $('.macros-nav').removeClass('hidden'); $('.back').addClass('hidden'); @@ -112,10 +112,12 @@ $(function() { // Navigate to remote pages $('.remotes-nav a').on('click', function(evt) { evt.preventDefault(); + var new_position = $('body').offset(); + window.scrollTo(new_position.left,new_position.top); var href = $(this).attr('href'); $('.remotes-nav').addClass('hidden'); $('.macros-nav').addClass('hidden'); - $('.scheduleBtn').addClass('hidden'); + $('.scheduleBtn').addClass('hidden'); $(href).addClass('active'); $('.back').removeClass('hidden'); $('#title').html($(this).html()); @@ -124,10 +126,12 @@ $(function() { $('.scheduleBtn a').on('click', function(evt) { evt.preventDefault(); + var new_position = $('body').offset(); + window.scrollTo(new_position.left,new_position.top); var href = $(this).attr('href'); $('.remotes-nav').addClass('hidden'); $('.macros-nav').addClass('hidden'); - $('.scheduleBtn').addClass('hidden'); + $('.scheduleBtn').addClass('hidden'); $(href).addClass('active'); $('.back').removeClass('hidden'); $('#title').html($(this).html()); From 511d41f218cb3062e20c2b13db60698bfe1b180b Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Sun, 11 Jan 2015 22:08:05 -0700 Subject: [PATCH 21/22] Helps fix a test condition --- templates/index.swig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/index.swig b/templates/index.swig index f8fd12c..1535048 100644 --- a/templates/index.swig +++ b/templates/index.swig @@ -291,7 +291,7 @@ {% set remoteName = loop.key %}
{% for command in remote %} - {% endfor %}
From 9d9110164276224a5afd89643b8ee344a446356c Mon Sep 17 00:00:00 2001 From: JimJamUrCode Date: Mon, 12 Jan 2015 09:59:35 -0700 Subject: [PATCH 22/22] Fixed some moment.js deprecation warnings using utcOffset to set the user timezone now. --- app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 215dd43..54c05dc 100644 --- a/app.js +++ b/app.js @@ -55,7 +55,7 @@ function createTimers() for(var i = 0; i < config.schedule["items"].length; i++) { - var currDate = moment().tz("" + config.schedule["timezone"][0]); + var currDate = moment().utcOffset("" + config.schedule["timezone"][0]); var daysIndex; for(var j = 0; j < daysOfWeek.length; j++) { @@ -104,7 +104,7 @@ function createTimers() var dater = currDate.year() + "-0" + (currDate.month()+1) + "-0" + currDate.date() + " 00:00"; - var tempDay = moment.tz(dater, ""+config.schedule["timezone"][0]); + var tempDay = moment().utcOffset(dater, ""+config.schedule["timezone"][0]); tempDay.add(daysFromNow, 'days'); tempDay.hour(config.schedule["items"][i][4]); tempDay.minute(config.schedule["items"][i][5]);