issue46, added a javascript-based slider to modify slide-interval
[phpfspot.git] / slider / js / slider.js
diff --git a/slider/js/slider.js b/slider/js/slider.js
new file mode 100644 (file)
index 0000000..865a625
--- /dev/null
@@ -0,0 +1,489 @@
+/*----------------------------------------------------------------------------\\r
+|                                Slider 1.02                                  |\r
+|-----------------------------------------------------------------------------|\r
+|                         Created by Erik Arvidsson                           |\r
+|                  (http://webfx.eae.net/contact.html#erik)                   |\r
+|                      For WebFX (http://webfx.eae.net/)                      |\r
+|-----------------------------------------------------------------------------|\r
+| A  slider  control that  degrades  to an  input control  for non  supported |\r
+| browsers.                                                                   |\r
+|-----------------------------------------------------------------------------|\r
+|                Copyright (c) 2002, 2003, 2006 Erik Arvidsson                |\r
+|-----------------------------------------------------------------------------|\r
+| Licensed under the Apache License, Version 2.0 (the "License"); you may not |\r
+| use this file except in compliance with the License.  You may obtain a copy |\r
+| of the License at http://www.apache.org/licenses/LICENSE-2.0                |\r
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |\r
+| Unless  required  by  applicable law or  agreed  to  in  writing,  software |\r
+| distributed under the License is distributed on an  "AS IS" BASIS,  WITHOUT |\r
+| WARRANTIES OR  CONDITIONS OF ANY KIND,  either express or implied.  See the |\r
+| License  for the  specific language  governing permissions  and limitations |\r
+| under the License.                                                          |\r
+|-----------------------------------------------------------------------------|\r
+| Dependencies: timer.js - an OO abstraction of timers                        |\r
+|               range.js - provides the data model for the slider             |\r
+|               winclassic.css or any other css file describing the look      |\r
+|-----------------------------------------------------------------------------|\r
+| 2002-10-14 | Original version released                                      |\r
+| 2003-03-27 | Added a test in the constructor for missing oElement arg       |\r
+| 2003-11-27 | Only use mousewheel when focused                               |\r
+| 2006-05-28 | Changed license to Apache Software License 2.0.                |\r
+|-----------------------------------------------------------------------------|\r
+| Created 2002-10-14 | All changes are in the log above. | Updated 2006-05-28 |\r
+\----------------------------------------------------------------------------*/\r
+\r
+Slider.isSupported = typeof document.createElement != "undefined" &&\r
+       typeof document.documentElement != "undefined" &&\r
+       typeof document.documentElement.offsetWidth == "number";\r
+\r
+\r
+function Slider(oElement, oInput, sOrientation) {\r
+       if (!oElement) return;\r
+       this._orientation = sOrientation || "horizontal";\r
+       this._range = new Range();\r
+       this._range.setExtent(0);\r
+       this._blockIncrement = 10;\r
+       this._unitIncrement = 1;\r
+       this._timer = new Timer(100);\r
+\r
+\r
+       if (Slider.isSupported && oElement) {\r
+\r
+               this.document = oElement.ownerDocument || oElement.document;\r
+\r
+               this.element = oElement;\r
+               this.element.slider = this;\r
+               this.element.unselectable = "on";\r
+\r
+               // add class name tag to class name\r
+               this.element.className = this._orientation + " " + this.classNameTag + " " + this.element.className;\r
+\r
+               // create line\r
+               this.line = this.document.createElement("DIV");\r
+               this.line.className = "line";\r
+               this.line.unselectable = "on";\r
+               this.line.appendChild(this.document.createElement("DIV"));\r
+               this.element.appendChild(this.line);\r
+\r
+               // create handle\r
+               this.handle = this.document.createElement("DIV");\r
+               this.handle.className = "handle";\r
+               this.handle.unselectable = "on";\r
+               this.handle.appendChild(this.document.createElement("DIV"));\r
+               this.handle.firstChild.appendChild(\r
+                       this.document.createTextNode(String.fromCharCode(160)));\r
+               this.element.appendChild(this.handle);\r
+       }\r
+\r
+       this.input = oInput;\r
+\r
+       // events\r
+       var oThis = this;\r
+       this._range.onchange = function () {\r
+               oThis.recalculate();\r
+               if (typeof oThis.onchange == "function")\r
+                       oThis.onchange();\r
+       };\r
+\r
+       if (Slider.isSupported && oElement) {\r
+               this.element.onfocus            = Slider.eventHandlers.onfocus;\r
+               this.element.onblur                     = Slider.eventHandlers.onblur;\r
+               this.element.onmousedown        = Slider.eventHandlers.onmousedown;\r
+               this.element.onmouseover        = Slider.eventHandlers.onmouseover;\r
+               this.element.onmouseout         = Slider.eventHandlers.onmouseout;\r
+               this.element.onkeydown          = Slider.eventHandlers.onkeydown;\r
+               this.element.onkeypress         = Slider.eventHandlers.onkeypress;\r
+               this.element.onmousewheel       = Slider.eventHandlers.onmousewheel;\r
+               this.handle.onselectstart       =\r
+               this.element.onselectstart      = function () { return false; };\r
+\r
+               this._timer.ontimer = function () {\r
+                       oThis.ontimer();\r
+               };\r
+\r
+               // extra recalculate for ie\r
+               window.setTimeout(function() {\r
+                       oThis.recalculate();\r
+               }, 1);\r
+       }\r
+       else {\r
+               this.input.onchange = function (e) {\r
+                       oThis.setValue(oThis.input.value);\r
+               };\r
+       }\r
+}\r
+\r
+Slider.eventHandlers = {\r
+\r
+       // helpers to make events a bit easier\r
+       getEvent:       function (e, el) {\r
+               if (!e) {\r
+                       if (el)\r
+                               e = el.document.parentWindow.event;\r
+                       else\r
+                               e = window.event;\r
+               }\r
+               if (!e.srcElement) {\r
+                       var el = e.target;\r
+                       while (el != null && el.nodeType != 1)\r
+                               el = el.parentNode;\r
+                       e.srcElement = el;\r
+               }\r
+               if (typeof e.offsetX == "undefined") {\r
+                       e.offsetX = e.layerX;\r
+                       e.offsetY = e.layerY;\r
+               }\r
+\r
+               return e;\r
+       },\r
+\r
+       getDocument:    function (e) {\r
+               if (e.target)\r
+                       return e.target.ownerDocument;\r
+               return e.srcElement.document;\r
+       },\r
+\r
+       getSlider:      function (e) {\r
+               var el = e.target || e.srcElement;\r
+               while (el != null && el.slider == null) {\r
+                       el = el.parentNode;\r
+               }\r
+               if (el)\r
+                       return el.slider;\r
+               return null;\r
+       },\r
+\r
+       getLine:        function (e) {\r
+               var el = e.target || e.srcElement;\r
+               while (el != null && el.className != "line")    {\r
+                       el = el.parentNode;\r
+               }\r
+               return el;\r
+       },\r
+\r
+       getHandle:      function (e) {\r
+               var el = e.target || e.srcElement;\r
+               var re = /handle/;\r
+               while (el != null && !re.test(el.className))    {\r
+                       el = el.parentNode;\r
+               }\r
+               return el;\r
+       },\r
+       // end helpers\r
+\r
+       onfocus:        function (e) {\r
+               var s = this.slider;\r
+               s._focused = true;\r
+               s.handle.className = "handle hover";\r
+       },\r
+\r
+       onblur: function (e) {\r
+               var s = this.slider\r
+               s._focused = false;\r
+               s.handle.className = "handle";\r
+       },\r
+\r
+       onmouseover:    function (e) {\r
+               e = Slider.eventHandlers.getEvent(e, this);\r
+               var s = this.slider;\r
+               if (e.srcElement == s.handle)\r
+                       s.handle.className = "handle hover";\r
+       },\r
+\r
+       onmouseout:     function (e) {\r
+               e = Slider.eventHandlers.getEvent(e, this);\r
+               var s = this.slider;\r
+               if (e.srcElement == s.handle && !s._focused)\r
+                       s.handle.className = "handle";\r
+       },\r
+\r
+       onmousedown:    function (e) {\r
+               e = Slider.eventHandlers.getEvent(e, this);\r
+               var s = this.slider;\r
+               if (s.element.focus)\r
+                       s.element.focus();\r
+\r
+               Slider._currentInstance = s;\r
+               var doc = s.document;\r
+\r
+               if (doc.addEventListener) {\r
+                       doc.addEventListener("mousemove", Slider.eventHandlers.onmousemove, true);\r
+                       doc.addEventListener("mouseup", Slider.eventHandlers.onmouseup, true);\r
+               }\r
+               else if (doc.attachEvent) {\r
+                       doc.attachEvent("onmousemove", Slider.eventHandlers.onmousemove);\r
+                       doc.attachEvent("onmouseup", Slider.eventHandlers.onmouseup);\r
+                       doc.attachEvent("onlosecapture", Slider.eventHandlers.onmouseup);\r
+                       s.element.setCapture();\r
+               }\r
+\r
+               if (Slider.eventHandlers.getHandle(e)) {        // start drag\r
+                       Slider._sliderDragData = {\r
+                               screenX:        e.screenX,\r
+                               screenY:        e.screenY,\r
+                               dx:                     e.screenX - s.handle.offsetLeft,\r
+                               dy:                     e.screenY - s.handle.offsetTop,\r
+                               startValue:     s.getValue(),\r
+                               slider:         s\r
+                       };\r
+               }\r
+               else {\r
+                       var lineEl = Slider.eventHandlers.getLine(e);\r
+                       s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0);\r
+                       s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0);\r
+                       s._increasing = null;\r
+                       s.ontimer();\r
+               }\r
+       },\r
+\r
+       onmousemove:    function (e) {\r
+               e = Slider.eventHandlers.getEvent(e, this);\r
+\r
+               if (Slider._sliderDragData) {   // drag\r
+                       var s = Slider._sliderDragData.slider;\r
+\r
+                       var boundSize = s.getMaximum() - s.getMinimum();\r
+                       var size, pos, reset;\r
+\r
+                       if (s._orientation == "horizontal") {\r
+                               size = s.element.offsetWidth - s.handle.offsetWidth;\r
+                               pos = e.screenX - Slider._sliderDragData.dx;\r
+                               reset = Math.abs(e.screenY - Slider._sliderDragData.screenY) > 100;\r
+                       }\r
+                       else {\r
+                               size = s.element.offsetHeight - s.handle.offsetHeight;\r
+                               pos = s.element.offsetHeight - s.handle.offsetHeight -\r
+                                       (e.screenY - Slider._sliderDragData.dy);\r
+                               reset = Math.abs(e.screenX - Slider._sliderDragData.screenX) > 100;\r
+                       }\r
+                       s.setValue(reset ? Slider._sliderDragData.startValue :\r
+                                               s.getMinimum() + boundSize * pos / size);\r
+                       return false;\r
+               }\r
+               else {\r
+                       var s = Slider._currentInstance;\r
+                       if (s != null) {\r
+                               var lineEl = Slider.eventHandlers.getLine(e);\r
+                               s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0);\r
+                               s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0);\r
+                       }\r
+               }\r
+\r
+       },\r
+\r
+       onmouseup:      function (e) {\r
+               e = Slider.eventHandlers.getEvent(e, this);\r
+               var s = Slider._currentInstance;\r
+               var doc = s.document;\r
+               if (doc.removeEventListener) {\r
+                       doc.removeEventListener("mousemove", Slider.eventHandlers.onmousemove, true);\r
+                       doc.removeEventListener("mouseup", Slider.eventHandlers.onmouseup, true);\r
+               }\r
+               else if (doc.detachEvent) {\r
+                       doc.detachEvent("onmousemove", Slider.eventHandlers.onmousemove);\r
+                       doc.detachEvent("onmouseup", Slider.eventHandlers.onmouseup);\r
+                       doc.detachEvent("onlosecapture", Slider.eventHandlers.onmouseup);\r
+                       s.element.releaseCapture();\r
+               }\r
+\r
+               if (Slider._sliderDragData) {   // end drag\r
+                       Slider._sliderDragData = null;\r
+               }\r
+               else {\r
+                       s._timer.stop();\r
+                       s._increasing = null;\r
+               }\r
+               Slider._currentInstance = null;\r
+       },\r
+\r
+       onkeydown:      function (e) {\r
+               e = Slider.eventHandlers.getEvent(e, this);\r
+               //var s = Slider.eventHandlers.getSlider(e);\r
+               var s = this.slider;\r
+               var kc = e.keyCode;\r
+               switch (kc) {\r
+                       case 33:        // page up\r
+                               s.setValue(s.getValue() + s.getBlockIncrement());\r
+                               break;\r
+                       case 34:        // page down\r
+                               s.setValue(s.getValue() - s.getBlockIncrement());\r
+                               break;\r
+                       case 35:        // end\r
+                               s.setValue(s.getOrientation() == "horizontal" ?\r
+                                       s.getMaximum() :\r
+                                       s.getMinimum());\r
+                               break;\r
+                       case 36:        // home\r
+                               s.setValue(s.getOrientation() == "horizontal" ?\r
+                                       s.getMinimum() :\r
+                                       s.getMaximum());\r
+                               break;\r
+                       case 38:        // up\r
+                       case 39:        // right\r
+                               s.setValue(s.getValue() + s.getUnitIncrement());\r
+                               break;\r
+\r
+                       case 37:        // left\r
+                       case 40:        // down\r
+                               s.setValue(s.getValue() - s.getUnitIncrement());\r
+                               break;\r
+               }\r
+\r
+               if (kc >= 33 && kc <= 40) {\r
+                       return false;\r
+               }\r
+       },\r
+\r
+       onkeypress:     function (e) {\r
+               e = Slider.eventHandlers.getEvent(e, this);\r
+               var kc = e.keyCode;\r
+               if (kc >= 33 && kc <= 40) {\r
+                       return false;\r
+               }\r
+       },\r
+\r
+       onmousewheel:   function (e) {\r
+               e = Slider.eventHandlers.getEvent(e, this);\r
+               var s = this.slider;\r
+               if (s._focused) {\r
+                       s.setValue(s.getValue() + e.wheelDelta / 120 * s.getUnitIncrement());\r
+                       // windows inverts this on horizontal sliders. That does not\r
+                       // make sense to me\r
+                       return false;\r
+               }\r
+       }\r
+};\r
+\r
+\r
+\r
+Slider.prototype.classNameTag = "dynamic-slider-control",\r
+\r
+Slider.prototype.setValue = function (v) {\r
+       this._range.setValue(v);\r
+       this.input.value = this.getValue();\r
+};\r
+\r
+Slider.prototype.getValue = function () {\r
+       return this._range.getValue();\r
+};\r
+\r
+Slider.prototype.setMinimum = function (v) {\r
+       this._range.setMinimum(v);\r
+       this.input.value = this.getValue();\r
+};\r
+\r
+Slider.prototype.getMinimum = function () {\r
+       return this._range.getMinimum();\r
+};\r
+\r
+Slider.prototype.setMaximum = function (v) {\r
+       this._range.setMaximum(v);\r
+       this.input.value = this.getValue();\r
+};\r
+\r
+Slider.prototype.getMaximum = function () {\r
+       return this._range.getMaximum();\r
+};\r
+\r
+Slider.prototype.setUnitIncrement = function (v) {\r
+       this._unitIncrement = v;\r
+};\r
+\r
+Slider.prototype.getUnitIncrement = function () {\r
+       return this._unitIncrement;\r
+};\r
+\r
+Slider.prototype.setBlockIncrement = function (v) {\r
+       this._blockIncrement = v;\r
+};\r
+\r
+Slider.prototype.getBlockIncrement = function () {\r
+       return this._blockIncrement;\r
+};\r
+\r
+Slider.prototype.getOrientation = function () {\r
+       return this._orientation;\r
+};\r
+\r
+Slider.prototype.setOrientation = function (sOrientation) {\r
+       if (sOrientation != this._orientation) {\r
+               if (Slider.isSupported && this.element) {\r
+                       // add class name tag to class name\r
+                       this.element.className = this.element.className.replace(this._orientation,\r
+                                                                       sOrientation);\r
+               }\r
+               this._orientation = sOrientation;\r
+               this.recalculate();\r
+\r
+       }\r
+};\r
+\r
+Slider.prototype.recalculate = function() {\r
+       if (!Slider.isSupported || !this.element) return;\r
+\r
+       var w = this.element.offsetWidth;\r
+       var h = this.element.offsetHeight;\r
+       var hw = this.handle.offsetWidth;\r
+       var hh = this.handle.offsetHeight;\r
+       var lw = this.line.offsetWidth;\r
+       var lh = this.line.offsetHeight;\r
+\r
+       // this assumes a border-box layout\r
+\r
+       if (this._orientation == "horizontal") {\r
+               this.handle.style.left = (w - hw) * (this.getValue() - this.getMinimum()) /\r
+                       (this.getMaximum() - this.getMinimum()) + "px";\r
+               this.handle.style.top = (h - hh) / 2 + "px";\r
+\r
+               this.line.style.top = (h - lh) / 2 + "px";\r
+               this.line.style.left = hw / 2 + "px";\r
+               //this.line.style.right = hw / 2 + "px";\r
+               this.line.style.width = Math.max(0, w - hw - 2)+ "px";\r
+               this.line.firstChild.style.width = Math.max(0, w - hw - 4)+ "px";\r
+       }\r
+       else {\r
+               this.handle.style.left = (w - hw) / 2 + "px";\r
+               this.handle.style.top = h - hh - (h - hh) * (this.getValue() - this.getMinimum()) /\r
+                       (this.getMaximum() - this.getMinimum()) + "px";\r
+\r
+               this.line.style.left = (w - lw) / 2 + "px";\r
+               this.line.style.top = hh / 2 + "px";\r
+               this.line.style.height = Math.max(0, h - hh - 2) + "px";        //hard coded border width\r
+               //this.line.style.bottom = hh / 2 + "px";\r
+               this.line.firstChild.style.height = Math.max(0, h - hh - 4) + "px";     //hard coded border width\r
+       }\r
+};\r
+\r
+Slider.prototype.ontimer = function () {\r
+       var hw = this.handle.offsetWidth;\r
+       var hh = this.handle.offsetHeight;\r
+       var hl = this.handle.offsetLeft;\r
+       var ht = this.handle.offsetTop;\r
+\r
+       if (this._orientation == "horizontal") {\r
+               if (this._mouseX > hl + hw &&\r
+                       (this._increasing == null || this._increasing)) {\r
+                       this.setValue(this.getValue() + this.getBlockIncrement());\r
+                       this._increasing = true;\r
+               }\r
+               else if (this._mouseX < hl &&\r
+                       (this._increasing == null || !this._increasing)) {\r
+                       this.setValue(this.getValue() - this.getBlockIncrement());\r
+                       this._increasing = false;\r
+               }\r
+       }\r
+       else {\r
+               if (this._mouseY > ht + hh &&\r
+                       (this._increasing == null || !this._increasing)) {\r
+                       this.setValue(this.getValue() - this.getBlockIncrement());\r
+                       this._increasing = false;\r
+               }\r
+               else if (this._mouseY < ht &&\r
+                       (this._increasing == null || this._increasing)) {\r
+                       this.setValue(this.getValue() + this.getBlockIncrement());\r
+                       this._increasing = true;\r
+               }\r
+       }\r
+\r
+       this._timer.start();\r
+};
\ No newline at end of file