From 1727eb621bc23d604109337505738f7f7e0721de Mon Sep 17 00:00:00 2001 From: Mitchell Pomery <bob_george33@hotmail.com> Date: Sun, 9 Feb 2014 13:23:19 +0800 Subject: [PATCH] Start of a web interface Webby --- BlinkenLights.ino | 3 +- web/css/simple-slider-volume.css | 48 ++++ web/css/simple-slider.css | 55 +++++ web/js/simple-slider.coffee | 361 ++++++++++++++++++++++++++++++ web/js/simple-slider.js | 363 +++++++++++++++++++++++++++++++ web/js/simple-slider.min.js | 11 + web/web.php | 91 ++++++++ 7 files changed, 931 insertions(+), 1 deletion(-) create mode 100644 web/css/simple-slider-volume.css create mode 100644 web/css/simple-slider.css create mode 100644 web/js/simple-slider.coffee create mode 100644 web/js/simple-slider.js create mode 100644 web/js/simple-slider.min.js create mode 100644 web/web.php diff --git a/BlinkenLights.ino b/BlinkenLights.ino index 94f2e5b..f326fc0 100644 --- a/BlinkenLights.ino +++ b/BlinkenLights.ino @@ -258,7 +258,8 @@ char *url_tail, bool tail_complete) { char name[NAMELEN]; char value[VALUELEN]; - server.httpSuccess(); + //server.print("Access-Control-Allow-Origin: *"); + server.httpSuccess("application/json", "Access-Control-Allow-Origin: *"); // Kill the connection before doing anything if all they want is head if (type == WebServer::HEAD) { return; diff --git a/web/css/simple-slider-volume.css b/web/css/simple-slider-volume.css new file mode 100644 index 0000000..d8a876b --- /dev/null +++ b/web/css/simple-slider-volume.css @@ -0,0 +1,48 @@ +.slider-volume { + width: 300px; +} + +.slider-volume > .dragger { + width: 16px; + height: 16px; + margin: 0 auto; + border: 1px solid rgba(255,255,255,0.6); + + -moz-box-shadow: 0 0px 2px 1px rgba(0,0,0,0.5), 0 2px 5px 2px rgba(0,0,0,0.2); + -webkit-box-shadow: 0 0px 2px 1px rgba(0,0,0,0.5), 0 2px 5px 2px rgba(0,0,0,0.2); + box-shadow: 0 0px 2px 1px rgba(0,0,0,0.5), 0 2px 5px 2px rgba(0,0,0,0.2); + + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + border-radius: 10px; + + background: #c5c5c5; + background: -moz-linear-gradient(90deg, rgba(180,180,180,1) 20%, rgba(230,230,230,1) 50%, rgba(180,180,180,1) 80%); + background: -webkit-radial-gradient( 50% 0%, 12% 50%, hsla(0,0%,100%,1) 0%, hsla(0,0%,100%,0) 100%), + -webkit-radial-gradient( 50% 100%, 12% 50%, hsla(0,0%,100%,.6) 0%, hsla(0,0%,100%,0) 100%), + -webkit-radial-gradient( 50% 50%, 200% 50%, hsla(0,0%,90%,1) 5%, hsla(0,0%,85%,1) 30%, hsla(0,0%,60%,1) 100%); +} + +.slider-volume > .track, .slider-volume > .highlight-track { + height: 11px; + + background: #787878; + background: -moz-linear-gradient(top, #787878, #a2a2a2); + background: -webkit-linear-gradient(top, #787878, #a2a2a2); + background: linear-gradient(top, #787878, #a2a2a2); + + -moz-box-shadow: inset 0 2px 5px 1px rgba(0,0,0,0.15), 0 1px 0px 0px rgba(230,230,230,0.9), inset 0 0 1px 1px rgba(0,0,0,0.2); + -webkit-box-shadow: inset 0 2px 5px 1px rgba(0,0,0,0.15), 0 1px 0px 0px rgba(230,230,230,0.9), inset 0 0 1px 1px rgba(0,0,0,0.2); + box-shadow: inset 0 2px 5px 1px rgba(0,0,0,0.15), 0 1px 0px 0px rgba(230,230,230,0.9), inset 0 0 1px 1px rgba(0,0,0,0.2); + + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; +} + +.slider-volume > .highlight-track { + background-color: #c5c5c5; + background: -moz-linear-gradient(top, #c5c5c5, #a2a2a2); + background: -webkit-linear-gradient(top, #c5c5c5, #a2a2a2); + background: linear-gradient(top, #c5c5c5, #a2a2a2); +} diff --git a/web/css/simple-slider.css b/web/css/simple-slider.css new file mode 100644 index 0000000..ca9bf6b --- /dev/null +++ b/web/css/simple-slider.css @@ -0,0 +1,55 @@ +.slider { + width: 300px; +} + +.slider > .dragger { + background: #8DCA09; + background: -webkit-linear-gradient(top, #8DCA09, #72A307); + background: -moz-linear-gradient(top, #8DCA09, #72A307); + background: linear-gradient(top, #8DCA09, #72A307); + + -webkit-box-shadow: inset 0 2px 2px rgba(255,255,255,0.5), 0 2px 8px rgba(0,0,0,0.2); + -moz-box-shadow: inset 0 2px 2px rgba(255,255,255,0.5), 0 2px 8px rgba(0,0,0,0.2); + box-shadow: inset 0 2px 2px rgba(255,255,255,0.5), 0 2px 8px rgba(0,0,0,0.2); + + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + border-radius: 10px; + + border: 1px solid #496805; + width: 16px; + height: 16px; +} + +.slider > .dragger:hover { + background: -webkit-linear-gradient(top, #8DCA09, #8DCA09); +} + + +.slider > .track, .slider > .highlight-track { + background: #ccc; + background: -webkit-linear-gradient(top, #bbb, #ddd); + background: -moz-linear-gradient(top, #bbb, #ddd); + background: linear-gradient(top, #bbb, #ddd); + + -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,0.1); + -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,0.1); + box-shadow: inset 0 2px 4px rgba(0,0,0,0.1); + + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + border-radius: 8px; + + border: 1px solid #aaa; + height: 4px; +} + +.slider > .highlight-track { + background-color: #8DCA09; + background: -webkit-linear-gradient(top, #8DCA09, #72A307); + background: -moz-linear-gradient(top, #8DCA09, #72A307); + background: linear-gradient(top, #8DCA09, #72A307); + + border-color: #496805; +} + diff --git a/web/js/simple-slider.coffee b/web/js/simple-slider.coffee new file mode 100644 index 0000000..9c3d40c --- /dev/null +++ b/web/js/simple-slider.coffee @@ -0,0 +1,361 @@ +### + jQuery Simple Slider + + Copyright (c) 2012 James Smith (http://loopj.com) + + Licensed under the MIT license (http://mit-license.org/) +### + +(($, window) -> + + # + # Main slider class + # + + class SimpleSlider + # Build a slider object. + # Exposed via el.numericalSlider(options) + constructor: (@input, options) -> + # Load in the settings + @defaultOptions = + animate: true + snapMid: false + classPrefix: null + classSuffix: null + theme: null + highlight: false + + @settings = $.extend({}, @defaultOptions, options) + @settings.classSuffix = "-#{@settings.theme}" if @settings.theme + + # Hide the original input + @input.hide() + + # Create the slider canvas + @slider = $("<div>") + .addClass("slider"+(@settings.classSuffix || "")) + .css + position: "relative" + userSelect: "none" + boxSizing: "border-box" + .insertBefore @input + @slider.attr("id", @input.attr("id") + "-slider") if @input.attr("id") + + @track = @createDivElement("track") + .css + width: "100%" + + if @settings.highlight + # Create the highlighting track on top of the track + @highlightTrack = @createDivElement("highlight-track") + .css + width: "0" + + # Create the slider drag target + @dragger = @createDivElement("dragger") + + # Adjust dimensions now elements are in the DOM + @slider.css + minHeight: @dragger.outerHeight() + marginLeft: @dragger.outerWidth()/2 + marginRight: @dragger.outerWidth()/2 + + @track.css + marginTop: @track.outerHeight()/-2 + + if @settings.highlight + @highlightTrack.css + marginTop: @track.outerHeight()/-2 + + @dragger.css + marginTop: @dragger.outerWidth()/-2 + marginLeft: @dragger.outerWidth()/-2 + + # Hook up drag/drop mouse events + @track + .mousedown (e) => + @trackEvent(e) + + if @settings.highlight + @highlightTrack + .mousedown (e) => + @trackEvent(e) + + @dragger + .mousedown (e) => + return unless e.which == 1 + + # We've started moving + @dragging = true + @dragger.addClass "dragging" + + # Update the slider position + @domDrag(e.pageX, e.pageY) + + false + + $("body") + .mousemove (e) => + if @dragging + # Update the slider position + @domDrag(e.pageX, e.pageY) + + # Always show a pointer when dragging + $("body").css cursor: "pointer" + + + .mouseup (e) => + if @dragging + # Finished dragging + @dragging = false + @dragger.removeClass "dragging" + + # Revert the cursor + $("body").css cursor: "auto" + + # Set slider initial position + @pagePos = 0 + + # Fill in initial slider value + if @input.val() == "" + @value = @getRange().min + @input.val(@value) + else + @value = @nearestValidValue(@input.val()) + + @setSliderPositionFromValue(@value) + + # We are ready to go + ratio = @valueToRatio(@value) + @input.trigger "slider:ready", + value: @value + ratio: ratio + position: ratio * @slider.outerWidth() + el: @slider + + # Create the basis of the track-div(s) + createDivElement: (classname) -> + item = $("<div>") + .addClass(classname) + .css + position: "absolute" + top: "50%" + userSelect: "none" + cursor: "pointer" + .appendTo @slider + return item + + + # Set the ratio (value between 0 and 1) of the slider. + # Exposed via el.slider("setRatio", ratio) + setRatio: (ratio) -> + # Range-check the ratio + ratio = Math.min(1, ratio) + ratio = Math.max(0, ratio) + + # Work out the value + value = @ratioToValue(ratio) + + # Update the position of the slider on the screen + @setSliderPositionFromValue(value) + + # Trigger value changed events + @valueChanged(value, ratio, "setRatio") + + # Set the value of the slider + # Exposed via el.slider("setValue", value) + setValue: (value) -> + # Snap value to nearest step or allowedValue + value = @nearestValidValue(value) + + # Work out the ratio + ratio = @valueToRatio(value) + + # Update the position of the slider on the screen + @setSliderPositionFromValue(value) + + # Trigger value changed events + @valueChanged(value, ratio, "setValue") + + # Respond to an event on a track + trackEvent: (e) -> + return unless e.which == 1 + + @domDrag(e.pageX, e.pageY, true) + @dragging = true + false + + # Respond to a dom drag event + domDrag: (pageX, pageY, animate=false) -> + # Normalize position within allowed range + pagePos = pageX - @slider.offset().left + pagePos = Math.min(@slider.outerWidth(), pagePos) + pagePos = Math.max(0, pagePos) + + # If the element position has changed, do stuff + if @pagePos != pagePos + @pagePos = pagePos + + # Set the percentage value of the slider + ratio = pagePos / @slider.outerWidth() + + # Trigger value changed events + value = @ratioToValue(ratio) + @valueChanged(value, ratio, "domDrag") + + # Update the position of the slider on the screen + if @settings.snap + @setSliderPositionFromValue(value, animate) + else + @setSliderPosition(pagePos, animate) + + # Set the slider position given a slider canvas position + setSliderPosition: (position, animate=false) -> + if animate and @settings.animate + @dragger.animate left: position, 200 + @highlightTrack.animate width: position, 200 if @settings.highlight + else + @dragger.css left: position + @highlightTrack.css width: position if @settings.highlight + + # Set the slider position given a value + setSliderPositionFromValue: (value, animate=false) -> + # Get the slide ratio from the value + ratio = @valueToRatio(value) + + # Set the slider position + @setSliderPosition(ratio * @slider.outerWidth(), animate) + + # Get the valid range of values + getRange: -> + if @settings.allowedValues + min: Math.min(@settings.allowedValues...) + max: Math.max(@settings.allowedValues...) + else if @settings.range + min: parseFloat(@settings.range[0]) + max: parseFloat(@settings.range[1]) + else + min: 0 + max: 1 + + # Find the nearest valid value, checking allowedValues and step settings + nearestValidValue: (rawValue) -> + range = @getRange() + + # Range-check the value + rawValue = Math.min(range.max, rawValue) + rawValue = Math.max(range.min, rawValue) + + # Apply allowedValues or step settings + if @settings.allowedValues + closest = null + $.each @settings.allowedValues, -> + if closest == null || Math.abs(this - rawValue) < Math.abs(closest - rawValue) + closest = this + + return closest + else if @settings.step + maxSteps = (range.max - range.min) / @settings.step + steps = Math.floor((rawValue - range.min) / @settings.step) + steps += 1 if (rawValue - range.min) % @settings.step > @settings.step / 2 and steps < maxSteps + + return steps * @settings.step + range.min + else + return rawValue + + # Convert a value to a ratio + valueToRatio: (value) -> + if @settings.equalSteps + # Get slider ratio for equal-step + for allowedVal, idx in @settings.allowedValues + if !closest? || Math.abs(allowedVal - value) < Math.abs(closest - value) + closest = allowedVal + closestIdx = idx + + if @settings.snapMid + (closestIdx+0.5)/@settings.allowedValues.length + else + (closestIdx)/(@settings.allowedValues.length - 1) + + else + # Get slider ratio for continuous values + range = @getRange() + (value - range.min) / (range.max - range.min) + + # Convert a ratio to a valid value + ratioToValue: (ratio) -> + if @settings.equalSteps + steps = @settings.allowedValues.length + step = Math.round(ratio * steps - 0.5) + idx = Math.min(step, @settings.allowedValues.length - 1) + + @settings.allowedValues[idx] + else + range = @getRange() + rawValue = ratio * (range.max - range.min) + range.min + + @nearestValidValue(rawValue) + + # Trigger value changed events + valueChanged: (value, ratio, trigger) -> + return if value.toString() == @value.toString() + + # Save the new value + @value = value + + # Construct event data and fire event + eventData = + value: value + ratio: ratio + position: ratio * @slider.outerWidth() + trigger: trigger + el: @slider + + @input + .val(value) + .trigger($.Event("change", eventData)) + .trigger("slider:changed", eventData) + + + # + # Expose as jQuery Plugin + # + + $.extend $.fn, simpleSlider: (settingsOrMethod, params...) -> + publicMethods = ["setRatio", "setValue"] + + $(this).each -> + if settingsOrMethod and settingsOrMethod in publicMethods + obj = $(this).data("slider-object") + + obj[settingsOrMethod].apply(obj, params) + else + settings = settingsOrMethod + $(this).data "slider-object", new SimpleSlider($(this), settings) + + + # + # Attach unobtrusive JS hooks + # + + $ -> + $("[data-slider]").each -> + $el = $(this) + + # Build options object from data attributes + settings = {} + + allowedValues = $el.data "slider-values" + settings.allowedValues = (parseFloat(x) for x in allowedValues.split(",")) if allowedValues + settings.range = $el.data("slider-range").split(",") if $el.data("slider-range") + settings.step = $el.data("slider-step") if $el.data("slider-step") + settings.snap = $el.data("slider-snap") + settings.equalSteps = $el.data("slider-equal-steps") + settings.theme = $el.data("slider-theme") if $el.data("slider-theme") + settings.highlight = $el.data("slider-highlight") if $el.attr("data-slider-highlight") + settings.animate = $el.data("slider-animate") if $el.data("slider-animate")? + + # Activate the plugin + $el.simpleSlider settings + +) @jQuery or @Zepto, this diff --git a/web/js/simple-slider.js b/web/js/simple-slider.js new file mode 100644 index 0000000..1b917f6 --- /dev/null +++ b/web/js/simple-slider.js @@ -0,0 +1,363 @@ +/* + jQuery Simple Slider + + Copyright (c) 2012 James Smith (http://loopj.com) + + Licensed under the MIT license (http://mit-license.org/) +*/ + +var __slice = [].slice, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + +(function($, window) { + var SimpleSlider; + SimpleSlider = (function() { + + function SimpleSlider(input, options) { + var ratio, + _this = this; + this.input = input; + this.defaultOptions = { + animate: true, + snapMid: false, + classPrefix: null, + classSuffix: null, + theme: null, + highlight: false + }; + this.settings = $.extend({}, this.defaultOptions, options); + if (this.settings.theme) { + this.settings.classSuffix = "-" + this.settings.theme; + } + this.input.hide(); + this.slider = $("<div>").addClass("slider" + (this.settings.classSuffix || "")).css({ + position: "relative", + userSelect: "none", + boxSizing: "border-box" + }).insertBefore(this.input); + if (this.input.attr("id")) { + this.slider.attr("id", this.input.attr("id") + "-slider"); + } + this.track = this.createDivElement("track").css({ + width: "100%" + }); + if (this.settings.highlight) { + this.highlightTrack = this.createDivElement("highlight-track").css({ + width: "0" + }); + } + this.dragger = this.createDivElement("dragger"); + this.slider.css({ + minHeight: this.dragger.outerHeight(), + marginLeft: this.dragger.outerWidth() / 2, + marginRight: this.dragger.outerWidth() / 2 + }); + this.track.css({ + marginTop: this.track.outerHeight() / -2 + }); + if (this.settings.highlight) { + this.highlightTrack.css({ + marginTop: this.track.outerHeight() / -2 + }); + } + this.dragger.css({ + marginTop: this.dragger.outerWidth() / -2, + marginLeft: this.dragger.outerWidth() / -2 + }); + this.track.mousedown(function(e) { + return _this.trackEvent(e); + }); + if (this.settings.highlight) { + this.highlightTrack.mousedown(function(e) { + return _this.trackEvent(e); + }); + } + this.dragger.mousedown(function(e) { + if (e.which !== 1) { + return; + } + _this.dragging = true; + _this.dragger.addClass("dragging"); + _this.domDrag(e.pageX, e.pageY); + return false; + }); + $("body").mousemove(function(e) { + if (_this.dragging) { + _this.domDrag(e.pageX, e.pageY); + return $("body").css({ + cursor: "pointer" + }); + } + }).mouseup(function(e) { + if (_this.dragging) { + _this.dragging = false; + _this.dragger.removeClass("dragging"); + return $("body").css({ + cursor: "auto" + }); + } + }); + this.pagePos = 0; + if (this.input.val() === "") { + this.value = this.getRange().min; + this.input.val(this.value); + } else { + this.value = this.nearestValidValue(this.input.val()); + } + this.setSliderPositionFromValue(this.value); + ratio = this.valueToRatio(this.value); + this.input.trigger("slider:ready", { + value: this.value, + ratio: ratio, + position: ratio * this.slider.outerWidth(), + el: this.slider + }); + } + + SimpleSlider.prototype.createDivElement = function(classname) { + var item; + item = $("<div>").addClass(classname).css({ + position: "absolute", + top: "50%", + userSelect: "none", + cursor: "pointer" + }).appendTo(this.slider); + return item; + }; + + SimpleSlider.prototype.setRatio = function(ratio) { + var value; + ratio = Math.min(1, ratio); + ratio = Math.max(0, ratio); + value = this.ratioToValue(ratio); + this.setSliderPositionFromValue(value); + return this.valueChanged(value, ratio, "setRatio"); + }; + + SimpleSlider.prototype.setValue = function(value) { + var ratio; + value = this.nearestValidValue(value); + ratio = this.valueToRatio(value); + this.setSliderPositionFromValue(value); + return this.valueChanged(value, ratio, "setValue"); + }; + + SimpleSlider.prototype.trackEvent = function(e) { + if (e.which !== 1) { + return; + } + this.domDrag(e.pageX, e.pageY, true); + this.dragging = true; + return false; + }; + + SimpleSlider.prototype.domDrag = function(pageX, pageY, animate) { + var pagePos, ratio, value; + if (animate == null) { + animate = false; + } + pagePos = pageX - this.slider.offset().left; + pagePos = Math.min(this.slider.outerWidth(), pagePos); + pagePos = Math.max(0, pagePos); + if (this.pagePos !== pagePos) { + this.pagePos = pagePos; + ratio = pagePos / this.slider.outerWidth(); + value = this.ratioToValue(ratio); + this.valueChanged(value, ratio, "domDrag"); + if (this.settings.snap) { + return this.setSliderPositionFromValue(value, animate); + } else { + return this.setSliderPosition(pagePos, animate); + } + } + }; + + SimpleSlider.prototype.setSliderPosition = function(position, animate) { + if (animate == null) { + animate = false; + } + if (animate && this.settings.animate) { + this.dragger.animate({ + left: position + }, 200); + if (this.settings.highlight) { + return this.highlightTrack.animate({ + width: position + }, 200); + } + } else { + this.dragger.css({ + left: position + }); + if (this.settings.highlight) { + return this.highlightTrack.css({ + width: position + }); + } + } + }; + + SimpleSlider.prototype.setSliderPositionFromValue = function(value, animate) { + var ratio; + if (animate == null) { + animate = false; + } + ratio = this.valueToRatio(value); + return this.setSliderPosition(ratio * this.slider.outerWidth(), animate); + }; + + SimpleSlider.prototype.getRange = function() { + if (this.settings.allowedValues) { + return { + min: Math.min.apply(Math, this.settings.allowedValues), + max: Math.max.apply(Math, this.settings.allowedValues) + }; + } else if (this.settings.range) { + return { + min: parseFloat(this.settings.range[0]), + max: parseFloat(this.settings.range[1]) + }; + } else { + return { + min: 0, + max: 1 + }; + } + }; + + SimpleSlider.prototype.nearestValidValue = function(rawValue) { + var closest, maxSteps, range, steps; + range = this.getRange(); + rawValue = Math.min(range.max, rawValue); + rawValue = Math.max(range.min, rawValue); + if (this.settings.allowedValues) { + closest = null; + $.each(this.settings.allowedValues, function() { + if (closest === null || Math.abs(this - rawValue) < Math.abs(closest - rawValue)) { + return closest = this; + } + }); + return closest; + } else if (this.settings.step) { + maxSteps = (range.max - range.min) / this.settings.step; + steps = Math.floor((rawValue - range.min) / this.settings.step); + if ((rawValue - range.min) % this.settings.step > this.settings.step / 2 && steps < maxSteps) { + steps += 1; + } + return steps * this.settings.step + range.min; + } else { + return rawValue; + } + }; + + SimpleSlider.prototype.valueToRatio = function(value) { + var allowedVal, closest, closestIdx, idx, range, _i, _len, _ref; + if (this.settings.equalSteps) { + _ref = this.settings.allowedValues; + for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) { + allowedVal = _ref[idx]; + if (!(typeof closest !== "undefined" && closest !== null) || Math.abs(allowedVal - value) < Math.abs(closest - value)) { + closest = allowedVal; + closestIdx = idx; + } + } + if (this.settings.snapMid) { + return (closestIdx + 0.5) / this.settings.allowedValues.length; + } else { + return closestIdx / (this.settings.allowedValues.length - 1); + } + } else { + range = this.getRange(); + return (value - range.min) / (range.max - range.min); + } + }; + + SimpleSlider.prototype.ratioToValue = function(ratio) { + var idx, range, rawValue, step, steps; + if (this.settings.equalSteps) { + steps = this.settings.allowedValues.length; + step = Math.round(ratio * steps - 0.5); + idx = Math.min(step, this.settings.allowedValues.length - 1); + return this.settings.allowedValues[idx]; + } else { + range = this.getRange(); + rawValue = ratio * (range.max - range.min) + range.min; + return this.nearestValidValue(rawValue); + } + }; + + SimpleSlider.prototype.valueChanged = function(value, ratio, trigger) { + var eventData; + if (value.toString() === this.value.toString()) { + return; + } + this.value = value; + eventData = { + value: value, + ratio: ratio, + position: ratio * this.slider.outerWidth(), + trigger: trigger, + el: this.slider + }; + return this.input.val(value).trigger($.Event("change", eventData)).trigger("slider:changed", eventData); + }; + + return SimpleSlider; + + })(); + $.extend($.fn, { + simpleSlider: function() { + var params, publicMethods, settingsOrMethod; + settingsOrMethod = arguments[0], params = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + publicMethods = ["setRatio", "setValue"]; + return $(this).each(function() { + var obj, settings; + if (settingsOrMethod && __indexOf.call(publicMethods, settingsOrMethod) >= 0) { + obj = $(this).data("slider-object"); + return obj[settingsOrMethod].apply(obj, params); + } else { + settings = settingsOrMethod; + return $(this).data("slider-object", new SimpleSlider($(this), settings)); + } + }); + } + }); + return $(function() { + return $("[data-slider]").each(function() { + var $el, allowedValues, settings, x; + $el = $(this); + settings = {}; + allowedValues = $el.data("slider-values"); + if (allowedValues) { + settings.allowedValues = (function() { + var _i, _len, _ref, _results; + _ref = allowedValues.split(","); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + x = _ref[_i]; + _results.push(parseFloat(x)); + } + return _results; + })(); + } + if ($el.data("slider-range")) { + settings.range = $el.data("slider-range").split(","); + } + if ($el.data("slider-step")) { + settings.step = $el.data("slider-step"); + } + settings.snap = $el.data("slider-snap"); + settings.equalSteps = $el.data("slider-equal-steps"); + if ($el.data("slider-theme")) { + settings.theme = $el.data("slider-theme"); + } + if ($el.attr("data-slider-highlight")) { + settings.highlight = $el.data("slider-highlight"); + } + if ($el.data("slider-animate") != null) { + settings.animate = $el.data("slider-animate"); + } + return $el.simpleSlider(settings); + }); + }); +})(this.jQuery || this.Zepto, this); diff --git a/web/js/simple-slider.min.js b/web/js/simple-slider.min.js new file mode 100644 index 0000000..b6a7341 --- /dev/null +++ b/web/js/simple-slider.min.js @@ -0,0 +1,11 @@ +/* + * jQuery Simple Slider: Unobtrusive Numerical Slider + * Version 1.0.0 + * + * Copyright (c) 2013 James Smith (http://loopj.com) + * + * Licensed under the MIT license (http://mit-license.org/) + * + */ + +var __slice=[].slice,__indexOf=[].indexOf||function(e){for(var t=0,n=this.length;t<n;t++)if(t in this&&this[t]===e)return t;return-1};(function(e,t){var n;return n=function(){function t(t,n){var r,i=this;this.input=t,this.defaultOptions={animate:!0,snapMid:!1,classPrefix:null,classSuffix:null,theme:null,highlight:!1},this.settings=e.extend({},this.defaultOptions,n),this.settings.theme&&(this.settings.classSuffix="-"+this.settings.theme),this.input.hide(),this.slider=e("<div>").addClass("slider"+(this.settings.classSuffix||"")).css({position:"relative",userSelect:"none",boxSizing:"border-box"}).insertBefore(this.input),this.input.attr("id")&&this.slider.attr("id",this.input.attr("id")+"-slider"),this.track=this.createDivElement("track").css({width:"100%"}),this.settings.highlight&&(this.highlightTrack=this.createDivElement("highlight-track").css({width:"0"})),this.dragger=this.createDivElement("dragger"),this.slider.css({minHeight:this.dragger.outerHeight(),marginLeft:this.dragger.outerWidth()/2,marginRight:this.dragger.outerWidth()/2}),this.track.css({marginTop:this.track.outerHeight()/-2}),this.settings.highlight&&this.highlightTrack.css({marginTop:this.track.outerHeight()/-2}),this.dragger.css({marginTop:this.dragger.outerWidth()/-2,marginLeft:this.dragger.outerWidth()/-2}),this.track.mousedown(function(e){return i.trackEvent(e)}),this.settings.highlight&&this.highlightTrack.mousedown(function(e){return i.trackEvent(e)}),this.dragger.mousedown(function(e){if(e.which!==1)return;return i.dragging=!0,i.dragger.addClass("dragging"),i.domDrag(e.pageX,e.pageY),!1}),e("body").mousemove(function(t){if(i.dragging)return i.domDrag(t.pageX,t.pageY),e("body").css({cursor:"pointer"})}).mouseup(function(t){if(i.dragging)return i.dragging=!1,i.dragger.removeClass("dragging"),e("body").css({cursor:"auto"})}),this.pagePos=0,this.input.val()===""?(this.value=this.getRange().min,this.input.val(this.value)):this.value=this.nearestValidValue(this.input.val()),this.setSliderPositionFromValue(this.value),r=this.valueToRatio(this.value),this.input.trigger("slider:ready",{value:this.value,ratio:r,position:r*this.slider.outerWidth(),el:this.slider})}return t.prototype.createDivElement=function(t){var n;return n=e("<div>").addClass(t).css({position:"absolute",top:"50%",userSelect:"none",cursor:"pointer"}).appendTo(this.slider),n},t.prototype.setRatio=function(e){var t;return e=Math.min(1,e),e=Math.max(0,e),t=this.ratioToValue(e),this.setSliderPositionFromValue(t),this.valueChanged(t,e,"setRatio")},t.prototype.setValue=function(e){var t;return e=this.nearestValidValue(e),t=this.valueToRatio(e),this.setSliderPositionFromValue(e),this.valueChanged(e,t,"setValue")},t.prototype.trackEvent=function(e){if(e.which!==1)return;return this.domDrag(e.pageX,e.pageY,!0),this.dragging=!0,!1},t.prototype.domDrag=function(e,t,n){var r,i,s;n==null&&(n=!1),r=e-this.slider.offset().left,r=Math.min(this.slider.outerWidth(),r),r=Math.max(0,r);if(this.pagePos!==r)return this.pagePos=r,i=r/this.slider.outerWidth(),s=this.ratioToValue(i),this.valueChanged(s,i,"domDrag"),this.settings.snap?this.setSliderPositionFromValue(s,n):this.setSliderPosition(r,n)},t.prototype.setSliderPosition=function(e,t){t==null&&(t=!1);if(t&&this.settings.animate){this.dragger.animate({left:e},200);if(this.settings.highlight)return this.highlightTrack.animate({width:e},200)}else{this.dragger.css({left:e});if(this.settings.highlight)return this.highlightTrack.css({width:e})}},t.prototype.setSliderPositionFromValue=function(e,t){var n;return t==null&&(t=!1),n=this.valueToRatio(e),this.setSliderPosition(n*this.slider.outerWidth(),t)},t.prototype.getRange=function(){return this.settings.allowedValues?{min:Math.min.apply(Math,this.settings.allowedValues),max:Math.max.apply(Math,this.settings.allowedValues)}:this.settings.range?{min:parseFloat(this.settings.range[0]),max:parseFloat(this.settings.range[1])}:{min:0,max:1}},t.prototype.nearestValidValue=function(t){var n,r,i,s;return i=this.getRange(),t=Math.min(i.max,t),t=Math.max(i.min,t),this.settings.allowedValues?(n=null,e.each(this.settings.allowedValues,function(){if(n===null||Math.abs(this-t)<Math.abs(n-t))return n=this}),n):this.settings.step?(r=(i.max-i.min)/this.settings.step,s=Math.floor((t-i.min)/this.settings.step),(t-i.min)%this.settings.step>this.settings.step/2&&s<r&&(s+=1),s*this.settings.step+i.min):t},t.prototype.valueToRatio=function(e){var t,n,r,i,s,o,u,a;if(this.settings.equalSteps){a=this.settings.allowedValues;for(i=o=0,u=a.length;o<u;i=++o){t=a[i];if(typeof n=="undefined"||n===null||Math.abs(t-e)<Math.abs(n-e))n=t,r=i}return this.settings.snapMid?(r+.5)/this.settings.allowedValues.length:r/(this.settings.allowedValues.length-1)}return s=this.getRange(),(e-s.min)/(s.max-s.min)},t.prototype.ratioToValue=function(e){var t,n,r,i,s;return this.settings.equalSteps?(s=this.settings.allowedValues.length,i=Math.round(e*s-.5),t=Math.min(i,this.settings.allowedValues.length-1),this.settings.allowedValues[t]):(n=this.getRange(),r=e*(n.max-n.min)+n.min,this.nearestValidValue(r))},t.prototype.valueChanged=function(t,n,r){var i;if(t.toString()===this.value.toString())return;return this.value=t,i={value:t,ratio:n,position:n*this.slider.outerWidth(),trigger:r,el:this.slider},this.input.val(t).trigger(e.Event("change",i)).trigger("slider:changed",i)},t}(),e.extend(e.fn,{simpleSlider:function(){var t,r,i;return i=arguments[0],t=2<=arguments.length?__slice.call(arguments,1):[],r=["setRatio","setValue"],e(this).each(function(){var s,o;return i&&__indexOf.call(r,i)>=0?(s=e(this).data("slider-object"),s[i].apply(s,t)):(o=i,e(this).data("slider-object",new n(e(this),o)))})}}),e(function(){return e("[data-slider]").each(function(){var t,n,r,i;return t=e(this),r={},n=t.data("slider-values"),n&&(r.allowedValues=function(){var e,t,r,s;r=n.split(","),s=[];for(e=0,t=r.length;e<t;e++)i=r[e],s.push(parseFloat(i));return s}()),t.data("slider-range")&&(r.range=t.data("slider-range").split(",")),t.data("slider-step")&&(r.step=t.data("slider-step")),r.snap=t.data("slider-snap"),r.equalSteps=t.data("slider-equal-steps"),t.data("slider-theme")&&(r.theme=t.data("slider-theme")),t.attr("data-slider-highlight")&&(r.highlight=t.data("slider-highlight")),t.data("slider-animate")!=null&&(r.animate=t.data("slider-animate")),t.simpleSlider(r)})})})(this.jQuery||this.Zepto,this); \ No newline at end of file diff --git a/web/web.php b/web/web.php new file mode 100644 index 0000000..296387c --- /dev/null +++ b/web/web.php @@ -0,0 +1,91 @@ +<?php + /** + * web.php - Simple Web interface for talking to the coke machine lights + * using PHP because screw typing + */ + $cokeaddress = "http://130.95.13.96/"; +?> +<!DOCTYPE html> +<html> +<head> + <title>BlinkenLights</title> + <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> + + <script src="js/simple-slider.js"></script> + <link href="css/simple-slider.css" rel="stylesheet" type="text/css" /> + <link href="css/simple-slider-volume.css" rel="stylesheet" type="text/css" /> + + <script type="text/javascript"> + function setLED(x, y, r, g, b) + { + var led = document.getElementById('led'+x+'x'+y); + console.log('led'+x+'x'+y); + led.style.backgroundColor = "rgb("+r+", "+g+", "+b+")"; + } + </script> + <style type="text/css"> + html { + width: 100%; + min-width: 480px; + background: #DDDDDD; + } + body { + width: 480px; + margin-left: auto; + margin-right: auto; + background: #AAAAAA; + } + .led { + width: 60px; + height: 20px; + margin: 0px; + padding: 0; + background: #000000; + display: inline-block; + } + [class^=slider] { display: inline-block; margin-bottom: 30px; } + </style> +</head> +<body> + <div name="lights"> + <?php + + for ($i = 0; $i < 7; $i++) { + for ($j = 0; $j < 6; $j++) { + echo "<div class='led' id='led".$j."x".$i."'> </div>"; + } + echo "<br />"; + } + ?> + </div> + <div class="brightness"> + Brightness:<br /> + <input type="text" id="bright" data-slider="true" data-slider-theme="volume" data-slider-range="0,255" data-slider-step="1" /> + </div> + <script> + $("[data-slider]") + .each(function () { + var input = $(this); + $("<span>") + .addClass("output") + .insertAfter($(this)); + }) + .bind("slider:ready slider:changed", function (event, data) { + $(this) + .nextAll(".output:first") + .html(data.value.toFixed(0)); + }); + + $(".brightness").change(function() { + console.log('<?=$cokeaddress?>/brightness?bright='+document.getElementById('bright').value); + $.ajax({ + url: '<?=$cokeaddress?>brightness?bright='+document.getElementById('bright').value, + dataType: "jsonp", + crossDomain: true + }); + return false; + }); + + </script> +</body> +</html> \ No newline at end of file -- GitLab