From b6bbab40259417677b797138a82a95d56e223234 Mon Sep 17 00:00:00 2001 From: Chris Maloney Date: Wed, 18 Jul 2012 16:57:59 -0400 Subject: [PATCH 01/10] Changes to get rangeinput to work on Android devices --- src/rangeinput/rangeinput.js | 62 +++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 12 deletions(-) mode change 100644 => 100755 src/rangeinput/rangeinput.js diff --git a/src/rangeinput/rangeinput.js b/src/rangeinput/rangeinput.js old mode 100644 new mode 100755 index 43ec9ab..212365f --- a/src/rangeinput/rangeinput.js +++ b/src/rangeinput/rangeinput.js @@ -66,22 +66,59 @@ conf = $.extend({x: true, y: true, drag: true}, conf); - doc = doc || $(document).bind("mousedown mouseup touchstart touchend", function(e) { - + var eventlist = + typeof Modernizer == "undefined" + ? "touchstart touchend mousedown mouseup" + : Modernizr.touch ? "touchstart touchend" : "mousedown mouseup"; + doc = doc || $(document).bind(eventlist, function(e) { + //dcon.head(e.type); var el = $(e.target); - // start - if ((e.type == "mousedown" || e.type == "touchstart") && el.data("drag")) { + // Only consider events of the right type, and, in the case of touch events, + // only those when the user has just one finger touching the device. + if ( ( e.type == "mousedown" || + e.type == "touchstart" && e.originalEvent.touches.length == 1 ) && + el.data("drag") ) + { // touchstart/touchmove use e.orginalEvent.pageX/Y instead of e.pageX/Y - var offset = el.position(), - x0 = (e.pageX || e.originalEvent.pageX) - offset.left, - y0 = (e.pageY || e.originalEvent.pageY) - offset.top, - start = true; + var offset = el.position(); + //dcon.info("offset.left = " + offset.left + ", offset.top = " + offset.top); + var x0, y0; + if (e.type == "mousedown") { + //dcon.info("e.pageX = " + e.pageX + ", e.originalEvent.pageX = " + e.pageX); + x0 = (e.pageX || e.originalEvent.pageX) - offset.left, + y0 = (e.pageY || e.originalEvent.pageY) - offset.top; + } + else { // touchstart + //dcon.info("..screenX = " + e.originalEvent.touches[0].screenX); + x0 = e.originalEvent.touches[0].screenX - offset.left; + y0 = e.originalEvent.touches[0].screenY - offset.top; + } + //dcon.info("x0 = " + x0 + ", y0 = " + y0); + + var start = true; - doc.bind("mousemove.drag touchmove.drag", function(e) { - var x = (e.pageX || e.originalEvent.pageX) -x0, - y = (e.pageY || e.originalEvent.pageY) -y0, - props = {}; + var eventlist = + typeof Modernizer == "undefined" + ? "touchmove.drag mousemove.drag" + : Modernizr.touch ? "touchmove.drag" : "mousemove.drag"; + doc.bind(eventlist, function(e) { + //dcon.head(e.type); + + var x, y; + if (e.type == "mousemove") { + //dcon.info("e.pageX = " + e.pageX + ", e.originalEvent.pageX = " + e.pageX); + x = (e.pageX || e.originalEvent.pageX) - x0, + y = (e.pageY || e.originalEvent.pageY) - y0; + } + else { // touchstart + //dcon.info("..screenX = " + e.originalEvent.touches[0].screenX); + x = e.originalEvent.touches[0].screenX - x0; + y = e.originalEvent.touches[0].screenY - y0; + } + //dcon.info("x = " + x + ", y = " + y); + + var props = {}; if (conf.x) { props.left = x; } if (conf.y) { props.top = y; } @@ -95,6 +132,7 @@ draggable = el; }); + //dcon.info("Setting preventDefault()"); e.preventDefault(); } else { From 4ad0c36f6c9da0e671e6253bd8db4c9d7a147992 Mon Sep 17 00:00:00 2001 From: Chris Maloney Date: Thu, 19 Jul 2012 09:54:39 -0400 Subject: [PATCH 02/10] Remove animation, set css property directly --- src/rangeinput/rangeinput.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/rangeinput/rangeinput.js b/src/rangeinput/rangeinput.js index 212365f..3da8001 100755 --- a/src/rangeinput/rangeinput.js +++ b/src/rangeinput/rangeinput.js @@ -301,7 +301,12 @@ } } else { - handle.animate({left: x}, speed, callback); + // Android is very sluggish. We don't want or need animation here, + // so just set the css property directly. Unfortunately, it's still + // sluggish. Might need to play with the CSS3 transform property, which is + // supposed to be very fast. + //handle.animate({left: x}, speed, callback); + handle.css('left', x); if (conf.progress) { progress.animate({width: x + handle.width() / 2}, speed); } From 36061cec72cd0f57625bb6296f4b9c02654b9724 Mon Sep 17 00:00:00 2001 From: Chris Maloney Date: Thu, 19 Jul 2012 09:58:08 -0400 Subject: [PATCH 03/10] Add provenance comment --- src/rangeinput/rangeinput.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/rangeinput/rangeinput.js b/src/rangeinput/rangeinput.js index 3da8001..5570dd9 100755 --- a/src/rangeinput/rangeinput.js +++ b/src/rangeinput/rangeinput.js @@ -1,4 +1,10 @@ /** + * jquerytools rangeinput widget. + * + * This version of this file is from https://github.com/Klortho/jquerytools, forked from + * https://github.com/Patrick64/jquerytools, which was forked from + * https://github.com/jquerytools/jquerytools. + * * @license * jQuery Tools @VERSION Rangeinput - HTML5 for humans * From e87f161bf958347de19465043183e99d7afcf636 Mon Sep 17 00:00:00 2001 From: Chris Maloney Date: Fri, 20 Jul 2012 13:26:36 -0400 Subject: [PATCH 04/10] Fix godforsaken whitespace in rangeinput.js --- src/rangeinput/rangeinput.js | 932 +++++++++++++++++------------------ 1 file changed, 466 insertions(+), 466 deletions(-) diff --git a/src/rangeinput/rangeinput.js b/src/rangeinput/rangeinput.js index 5570dd9..9661e38 100755 --- a/src/rangeinput/rangeinput.js +++ b/src/rangeinput/rangeinput.js @@ -2,98 +2,98 @@ * jquerytools rangeinput widget. * * This version of this file is from https://github.com/Klortho/jquerytools, forked from - * https://github.com/Patrick64/jquerytools, which was forked from + * https://github.com/Patrick64/jquerytools, which was forked from * https://github.com/jquerytools/jquerytools. * - * @license + * @license * jQuery Tools @VERSION Rangeinput - HTML5 for humans - * + * * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE. - * + * * http://flowplayer.org/tools/rangeinput/ * * Since: Mar 2010 - * Date: @DATE + * Date: @DATE */ (function($) { - - $.tools = $.tools || {version: '@VERSION'}; - - var tool; - - tool = $.tools.rangeinput = { - - conf: { - min: 0, - max: 100, // as defined in the standard - step: 'any', // granularity of the value. a non-zero float or int (or "any") - steps: 0, - value: 0, - precision: undefined, - vertical: 0, - keyboard: true, - progress: false, - speed: 100, - - // set to null if not needed - css: { - input: 'range', - slider: 'slider', - progress: 'progress', - handle: 'handle' - } - - } - }; - + + $.tools = $.tools || {version: '@VERSION'}; + + var tool; + + tool = $.tools.rangeinput = { + + conf: { + min: 0, + max: 100, // as defined in the standard + step: 'any', // granularity of the value. a non-zero float or int (or "any") + steps: 0, + value: 0, + precision: undefined, + vertical: 0, + keyboard: true, + progress: false, + speed: 100, + + // set to null if not needed + css: { + input: 'range', + slider: 'slider', + progress: 'progress', + handle: 'handle' + } + + } + }; + //{{{ fn.drag - - /* - FULL featured drag and drop. 0.7 kb minified, 0.3 gzipped. done. - Who told d'n'd is rocket science? Usage: - - $(".myelement").drag({y: false}).bind("drag", function(event, x, y) { - // do your custom thing - }); - - Configuration: - x: true, // enable horizontal drag - y: true, // enable vertical drag - drag: true // true = perform drag, false = only fire events - - Events: dragStart, drag, dragEnd. - */ - var doc, draggable; - - $.fn.drag = function(conf) { - - // disable IE specialities - document.ondragstart = function () { return false; }; - - conf = $.extend({x: true, y: true, drag: true}, conf); - - var eventlist = + + /* + FULL featured drag and drop. 0.7 kb minified, 0.3 gzipped. done. + Who told d'n'd is rocket science? Usage: + + $(".myelement").drag({y: false}).bind("drag", function(event, x, y) { + // do your custom thing + }); + + Configuration: + x: true, // enable horizontal drag + y: true, // enable vertical drag + drag: true // true = perform drag, false = only fire events + + Events: dragStart, drag, dragEnd. + */ + var doc, draggable; + + $.fn.drag = function(conf) { + + // disable IE specialities + document.ondragstart = function () { return false; }; + + conf = $.extend({x: true, y: true, drag: true}, conf); + + var eventlist = typeof Modernizer == "undefined" - ? "touchstart touchend mousedown mouseup" + ? "touchstart touchend mousedown mouseup" : Modernizr.touch ? "touchstart touchend" : "mousedown mouseup"; - doc = doc || $(document).bind(eventlist, function(e) { + doc = doc || $(document).bind(eventlist, function(e) { //dcon.head(e.type); - var el = $(e.target); - - // Only consider events of the right type, and, in the case of touch events, + var el = $(e.target); + + // Only consider events of the right type, and, in the case of touch events, // only those when the user has just one finger touching the device. - if ( ( e.type == "mousedown" || - e.type == "touchstart" && e.originalEvent.touches.length == 1 ) && - el.data("drag") ) + if ( ( e.type == "mousedown" || + e.type == "touchstart" && e.originalEvent.touches.length == 1 ) && + el.data("drag") ) { - // touchstart/touchmove use e.orginalEvent.pageX/Y instead of e.pageX/Y - var offset = el.position(); + // touchstart/touchmove use e.orginalEvent.pageX/Y instead of e.pageX/Y + var offset = el.position(); //dcon.info("offset.left = " + offset.left + ", offset.top = " + offset.top); var x0, y0; if (e.type == "mousedown") { //dcon.info("e.pageX = " + e.pageX + ", e.originalEvent.pageX = " + e.pageX); - x0 = (e.pageX || e.originalEvent.pageX) - offset.left, - y0 = (e.pageY || e.originalEvent.pageY) - offset.top; + x0 = (e.pageX || e.originalEvent.pageX) - offset.left, + y0 = (e.pageY || e.originalEvent.pageY) - offset.top; } else { // touchstart //dcon.info("..screenX = " + e.originalEvent.touches[0].screenX); @@ -102,20 +102,20 @@ } //dcon.info("x0 = " + x0 + ", y0 = " + y0); - var start = true; + var start = true; - var eventlist = + var eventlist = typeof Modernizer == "undefined" - ? "touchmove.drag mousemove.drag" + ? "touchmove.drag mousemove.drag" : Modernizr.touch ? "touchmove.drag" : "mousemove.drag"; - doc.bind(eventlist, function(e) { + doc.bind(eventlist, function(e) { //dcon.head(e.type); - + var x, y; if (e.type == "mousemove") { //dcon.info("e.pageX = " + e.pageX + ", e.originalEvent.pageX = " + e.pageX); - x = (e.pageX || e.originalEvent.pageX) - x0, - y = (e.pageY || e.originalEvent.pageY) - y0; + x = (e.pageX || e.originalEvent.pageX) - x0, + y = (e.pageY || e.originalEvent.pageY) - y0; } else { // touchstart //dcon.info("..screenX = " + e.originalEvent.touches[0].screenX); @@ -123,398 +123,398 @@ y = e.originalEvent.touches[0].screenY - y0; } //dcon.info("x = " + x + ", y = " + y); - + var props = {}; - - if (conf.x) { props.left = x; } - if (conf.y) { props.top = y; } - - if (start) { - el.trigger("dragStart"); - start = false; - } - if (conf.drag) { el.css(props); } - el.trigger("drag", [y, x]); - draggable = el; - }); - - //dcon.info("Setting preventDefault()"); - e.preventDefault(); - - } else { - - try { - if (draggable) { - draggable.trigger("dragEnd"); - } - } finally { - doc.unbind("mousemove.drag touchmove.drag"); - draggable = null; - } - } - - }); - - return this.data("drag", true); - }; + + if (conf.x) { props.left = x; } + if (conf.y) { props.top = y; } + + if (start) { + el.trigger("dragStart"); + start = false; + } + if (conf.drag) { el.css(props); } + el.trigger("drag", [y, x]); + draggable = el; + }); + + //dcon.info("Setting preventDefault()"); + e.preventDefault(); + + } else { + + try { + if (draggable) { + draggable.trigger("dragEnd"); + } + } finally { + doc.unbind("mousemove.drag touchmove.drag"); + draggable = null; + } + } + + }); + + return this.data("drag", true); + }; //}}} - - - - function round(value, precision) { - var n = Math.pow(10, precision); - return Math.round(value * n) / n; - } - - // get hidden element's width or height even though it's hidden - function dim(el, key) { - var v = parseInt(el.css(key), 10); - if (v) { return v; } - var s = el[0].currentStyle; - return s && s.width && parseInt(s.width, 10); - } - - function hasEvent(el) { - var e = el.data("events"); - return e && e.onSlide; - } - - function RangeInput(input, conf) { - - // private variables - var self = this, - css = conf.css, - root = $("
").data("rangeinput", self), - vertical, - value, // current value - origo, // handle's start point - len, // length of the range - pos; // current position of the handle - - // create range - input.before(root); - - var handle = root.addClass(css.slider).find("a").addClass(css.handle), - progress = root.find("div").addClass(css.progress); - - // get (HTML5) attributes into configuration - $.each("min,max,step,value".split(","), function(i, key) { - var val = input.attr(key); - if (parseFloat(val)) { - conf[key] = parseFloat(val, 10); - } - }); - - var range = conf.max - conf.min, - step = conf.step == 'any' ? 0 : conf.step, - precision = conf.precision; - - if (precision === undefined) { - try { - precision = step.toString().split(".")[1].length; - } catch (err) { - precision = 0; - } - } - - // Replace built-in range input (type attribute cannot be changed) - if (input.attr("type") == 'range') { - var def = input.clone().wrap("
").parent().html(), - clone = $(def.replace(/type/i, "type=text data-orig-type")); - - clone.val(conf.value); - input.replaceWith(clone); - input = clone; - } - - input.addClass(css.input); - - var fire = $(self).add(input), fireOnSlide = true; - - - /** - The flesh and bone of this tool. All sliding is routed trough this. - - @param evt types include: click, keydown, blur and api (setValue call) - @param isSetValue when called trough setValue() call (keydown, blur, api) - - vertical configuration gives additional complexity. - */ - function slide(evt, x, val, isSetValue) { - - // calculate value based on slide position - if (val === undefined) { - val = x / len * range; - - // x is calculated based on val. we need to strip off min during calculation - } else if (isSetValue) { - val -= conf.min; - } - - // increment in steps - if (step) { - val = Math.round(val / step) * step; - } - - // count x based on value or tweak x if stepping is done - if (x === undefined || step) { - x = val * len / range; - } - - // crazy value? - if (isNaN(val)) { return self; } - - // stay within range - x = Math.max(0, Math.min(x, len)); - val = x / len * range; - - if (isSetValue || !vertical) { - val += conf.min; - } - - // in vertical ranges value rises upwards - if (vertical) { - if (isSetValue) { - x = len -x; - } else { - val = conf.max - val; - } - } - - // precision - val = round(val, precision); - - // onSlide - var isClick = evt.type == "click"; - if (fireOnSlide && value !== undefined && !isClick) { - evt.type = "onSlide"; - fire.trigger(evt, [val, x]); - if (evt.isDefaultPrevented()) { return self; } - } - - // speed & callback - var speed = isClick ? conf.speed : 0, - callback = isClick ? function() { - evt.type = "change"; - fire.trigger(evt, [val]); - } : null; - - if (vertical) { - handle.animate({top: x}, speed, callback); - if (conf.progress) { - progress.animate({height: len - x + handle.height() / 2}, speed); - } - - } else { + + + + function round(value, precision) { + var n = Math.pow(10, precision); + return Math.round(value * n) / n; + } + + // get hidden element's width or height even though it's hidden + function dim(el, key) { + var v = parseInt(el.css(key), 10); + if (v) { return v; } + var s = el[0].currentStyle; + return s && s.width && parseInt(s.width, 10); + } + + function hasEvent(el) { + var e = el.data("events"); + return e && e.onSlide; + } + + function RangeInput(input, conf) { + + // private variables + var self = this, + css = conf.css, + root = $("
").data("rangeinput", self), + vertical, + value, // current value + origo, // handle's start point + len, // length of the range + pos; // current position of the handle + + // create range + input.before(root); + + var handle = root.addClass(css.slider).find("a").addClass(css.handle), + progress = root.find("div").addClass(css.progress); + + // get (HTML5) attributes into configuration + $.each("min,max,step,value".split(","), function(i, key) { + var val = input.attr(key); + if (parseFloat(val)) { + conf[key] = parseFloat(val, 10); + } + }); + + var range = conf.max - conf.min, + step = conf.step == 'any' ? 0 : conf.step, + precision = conf.precision; + + if (precision === undefined) { + try { + precision = step.toString().split(".")[1].length; + } catch (err) { + precision = 0; + } + } + + // Replace built-in range input (type attribute cannot be changed) + if (input.attr("type") == 'range') { + var def = input.clone().wrap("
").parent().html(), + clone = $(def.replace(/type/i, "type=text data-orig-type")); + + clone.val(conf.value); + input.replaceWith(clone); + input = clone; + } + + input.addClass(css.input); + + var fire = $(self).add(input), fireOnSlide = true; + + + /** + The flesh and bone of this tool. All sliding is routed trough this. + + @param evt types include: click, keydown, blur and api (setValue call) + @param isSetValue when called trough setValue() call (keydown, blur, api) + + vertical configuration gives additional complexity. + */ + function slide(evt, x, val, isSetValue) { + + // calculate value based on slide position + if (val === undefined) { + val = x / len * range; + + // x is calculated based on val. we need to strip off min during calculation + } else if (isSetValue) { + val -= conf.min; + } + + // increment in steps + if (step) { + val = Math.round(val / step) * step; + } + + // count x based on value or tweak x if stepping is done + if (x === undefined || step) { + x = val * len / range; + } + + // crazy value? + if (isNaN(val)) { return self; } + + // stay within range + x = Math.max(0, Math.min(x, len)); + val = x / len * range; + + if (isSetValue || !vertical) { + val += conf.min; + } + + // in vertical ranges value rises upwards + if (vertical) { + if (isSetValue) { + x = len -x; + } else { + val = conf.max - val; + } + } + + // precision + val = round(val, precision); + + // onSlide + var isClick = evt.type == "click"; + if (fireOnSlide && value !== undefined && !isClick) { + evt.type = "onSlide"; + fire.trigger(evt, [val, x]); + if (evt.isDefaultPrevented()) { return self; } + } + + // speed & callback + var speed = isClick ? conf.speed : 0, + callback = isClick ? function() { + evt.type = "change"; + fire.trigger(evt, [val]); + } : null; + + if (vertical) { + handle.animate({top: x}, speed, callback); + if (conf.progress) { + progress.animate({height: len - x + handle.height() / 2}, speed); + } + + } else { // Android is very sluggish. We don't want or need animation here, - // so just set the css property directly. Unfortunately, it's still + // so just set the css property directly. Unfortunately, it's still // sluggish. Might need to play with the CSS3 transform property, which is // supposed to be very fast. - //handle.animate({left: x}, speed, callback); + //handle.animate({left: x}, speed, callback); handle.css('left', x); - if (conf.progress) { - progress.animate({width: x + handle.width() / 2}, speed); - } - } - - // store current value - value = val; - pos = x; - - // se input field's value - input.val(val); - - return self; - } - - - $.extend(self, { - - getValue: function() { - return value; - }, - - setValue: function(val, e) { - init(); - return slide(e || $.Event("api"), undefined, val, true); - }, - - getConf: function() { - return conf; - }, - - getProgress: function() { - return progress; - }, - - getHandle: function() { - return handle; - }, - - getInput: function() { - return input; - }, - - step: function(am, e) { - e = e || $.Event(); - var step = conf.step == 'any' ? 1 : conf.step; - self.setValue(value + step * (am || 1), e); - }, - - // HTML5 compatible name - stepUp: function(am) { - return self.step(am || 1); - }, - - // HTML5 compatible name - stepDown: function(am) { - return self.step(-am || -1); - } - - }); - - // callbacks - $.each("onSlide,change".split(","), function(i, name) { - - // from configuration - if ($.isFunction(conf[name])) { - $(self).bind(name, conf[name]); - } - - // API methods - self[name] = function(fn) { - if (fn) { $(self).bind(name, fn); } - return self; - }; - }); - - - // dragging - handle.drag({drag: false}).bind("dragStart", function() { - - /* do some pre- calculations for seek() function. improves performance */ - init(); - - // avoid redundant event triggering (= heavy stuff) - fireOnSlide = hasEvent($(self)) || hasEvent(input); - - - }).bind("drag", function(e, y, x) { - - if (input.is(":disabled")) { return false; } - slide(e, vertical ? y : x); - - }).bind("dragEnd", function(e) { - if (!e.isDefaultPrevented()) { - e.type = "change"; - fire.trigger(e, [value]); - } - - }).click(function(e) { - return e.preventDefault(); - }); - - // clicking - root.click(function(e) { - if (input.is(":disabled") || e.target == handle[0]) { - return e.preventDefault(); - } - init(); - var fix = vertical ? handle.height() / 2 : handle.width() / 2; - slide(e, vertical ? len-origo-fix + e.pageY : e.pageX -origo -fix); - }); - - if (conf.keyboard) { - - input.keydown(function(e) { - - if (input.attr("readonly")) { return; } - - var key = e.keyCode, - up = $([75, 76, 38, 33, 39]).index(key) != -1, - down = $([74, 72, 40, 34, 37]).index(key) != -1; - - if ((up || down) && !(e.shiftKey || e.altKey || e.ctrlKey)) { - - // UP: k=75, l=76, up=38, pageup=33, right=39 - if (up) { - self.step(key == 33 ? 10 : 1, e); - - // DOWN: j=74, h=72, down=40, pagedown=34, left=37 - } else if (down) { - self.step(key == 34 ? -10 : -1, e); - } - return e.preventDefault(); - } - }); - } - - - input.blur(function(e) { - var val = $(this).val(); - if (val !== value) { - self.setValue(val, e); - } - }); - - - // HTML5 DOM methods - $.extend(input[0], { stepUp: self.stepUp, stepDown: self.stepDown}); - - - // calculate all dimension related stuff - function init() { - vertical = conf.vertical || dim(root, "height") > dim(root, "width"); - - if (vertical) { - len = dim(root, "height") - dim(handle, "height"); - origo = root.offset().top + len; - - } else { - len = dim(root, "width") - dim(handle, "width"); - origo = root.offset().left; - } - } - - function begin() { - init(); - self.setValue(conf.value !== undefined ? conf.value : conf.min); - } - begin(); - - // some browsers cannot get dimensions upon initialization - if (!len) { - $(window).load(begin); - } - } - - $.expr[':'].range = function(el) { - var type = el.getAttribute("type"); - return type && type == 'range' || !!$(el).filter("input").data("rangeinput"); - }; - - - // jQuery plugin implementation - $.fn.rangeinput = function(conf) { - - // already installed - if (this.data("rangeinput")) { return this; } - - // extend configuration with globals - conf = $.extend(true, {}, tool.conf, conf); - - var els; - - this.each(function() { - var el = new RangeInput($(this), $.extend(true, {}, conf)); - var input = el.getInput().data("rangeinput", el); - els = els ? els.add(input) : input; - }); - - return els ? els : this; - }; - - + if (conf.progress) { + progress.animate({width: x + handle.width() / 2}, speed); + } + } + + // store current value + value = val; + pos = x; + + // se input field's value + input.val(val); + + return self; + } + + + $.extend(self, { + + getValue: function() { + return value; + }, + + setValue: function(val, e) { + init(); + return slide(e || $.Event("api"), undefined, val, true); + }, + + getConf: function() { + return conf; + }, + + getProgress: function() { + return progress; + }, + + getHandle: function() { + return handle; + }, + + getInput: function() { + return input; + }, + + step: function(am, e) { + e = e || $.Event(); + var step = conf.step == 'any' ? 1 : conf.step; + self.setValue(value + step * (am || 1), e); + }, + + // HTML5 compatible name + stepUp: function(am) { + return self.step(am || 1); + }, + + // HTML5 compatible name + stepDown: function(am) { + return self.step(-am || -1); + } + + }); + + // callbacks + $.each("onSlide,change".split(","), function(i, name) { + + // from configuration + if ($.isFunction(conf[name])) { + $(self).bind(name, conf[name]); + } + + // API methods + self[name] = function(fn) { + if (fn) { $(self).bind(name, fn); } + return self; + }; + }); + + + // dragging + handle.drag({drag: false}).bind("dragStart", function() { + + /* do some pre- calculations for seek() function. improves performance */ + init(); + + // avoid redundant event triggering (= heavy stuff) + fireOnSlide = hasEvent($(self)) || hasEvent(input); + + + }).bind("drag", function(e, y, x) { + + if (input.is(":disabled")) { return false; } + slide(e, vertical ? y : x); + + }).bind("dragEnd", function(e) { + if (!e.isDefaultPrevented()) { + e.type = "change"; + fire.trigger(e, [value]); + } + + }).click(function(e) { + return e.preventDefault(); + }); + + // clicking + root.click(function(e) { + if (input.is(":disabled") || e.target == handle[0]) { + return e.preventDefault(); + } + init(); + var fix = vertical ? handle.height() / 2 : handle.width() / 2; + slide(e, vertical ? len-origo-fix + e.pageY : e.pageX -origo -fix); + }); + + if (conf.keyboard) { + + input.keydown(function(e) { + + if (input.attr("readonly")) { return; } + + var key = e.keyCode, + up = $([75, 76, 38, 33, 39]).index(key) != -1, + down = $([74, 72, 40, 34, 37]).index(key) != -1; + + if ((up || down) && !(e.shiftKey || e.altKey || e.ctrlKey)) { + + // UP: k=75, l=76, up=38, pageup=33, right=39 + if (up) { + self.step(key == 33 ? 10 : 1, e); + + // DOWN: j=74, h=72, down=40, pagedown=34, left=37 + } else if (down) { + self.step(key == 34 ? -10 : -1, e); + } + return e.preventDefault(); + } + }); + } + + + input.blur(function(e) { + var val = $(this).val(); + if (val !== value) { + self.setValue(val, e); + } + }); + + + // HTML5 DOM methods + $.extend(input[0], { stepUp: self.stepUp, stepDown: self.stepDown}); + + + // calculate all dimension related stuff + function init() { + vertical = conf.vertical || dim(root, "height") > dim(root, "width"); + + if (vertical) { + len = dim(root, "height") - dim(handle, "height"); + origo = root.offset().top + len; + + } else { + len = dim(root, "width") - dim(handle, "width"); + origo = root.offset().left; + } + } + + function begin() { + init(); + self.setValue(conf.value !== undefined ? conf.value : conf.min); + } + begin(); + + // some browsers cannot get dimensions upon initialization + if (!len) { + $(window).load(begin); + } + } + + $.expr[':'].range = function(el) { + var type = el.getAttribute("type"); + return type && type == 'range' || !!$(el).filter("input").data("rangeinput"); + }; + + + // jQuery plugin implementation + $.fn.rangeinput = function(conf) { + + // already installed + if (this.data("rangeinput")) { return this; } + + // extend configuration with globals + conf = $.extend(true, {}, tool.conf, conf); + + var els; + + this.each(function() { + var el = new RangeInput($(this), $.extend(true, {}, conf)); + var input = el.getInput().data("rangeinput", el); + els = els ? els.add(input) : input; + }); + + return els ? els : this; + }; + + }) (jQuery); From d45d24b8415d7f868de69a922948218a42c4cb21 Mon Sep 17 00:00:00 2001 From: Chris Maloney Date: Fri, 20 Jul 2012 13:27:52 -0400 Subject: [PATCH 05/10] Add setMax and setRange methods to the rangeinput API --- src/rangeinput/rangeinput.js | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/rangeinput/rangeinput.js b/src/rangeinput/rangeinput.js index 9661e38..b07a410 100755 --- a/src/rangeinput/rangeinput.js +++ b/src/rangeinput/rangeinput.js @@ -21,6 +21,7 @@ var tool; + // The default configuration for new rangeinputs tool = $.tools.rangeinput = { conf: { @@ -37,12 +38,11 @@ // set to null if not needed css: { - input: 'range', - slider: 'slider', - progress: 'progress', - handle: 'handle' + input: 'range', + slider: 'slider', + progress: 'progress', + handle: 'handle' } - } }; @@ -340,6 +340,20 @@ return slide(e || $.Event("api"), undefined, val, true); }, + setMax: function(val) { + //console.info("Setting max to " + val); + conf.max = val; + range = conf.max - conf.min; + return self.setValue(value); + }, + + setRange: function(min, max, val) { + if (typeof min !== "undefined") { conf.min = min; } + if (typeof max !== "undefined") { conf.max = max; } + range = conf.max - conf.min; + return self.setValue(typeof val !== "undefined" ? val : value); + }, + getConf: function() { return conf; }, From aed4b30cd071216566678f8fcd851e2b479e6a7b Mon Sep 17 00:00:00 2001 From: Chris Maloney Date: Fri, 20 Jul 2012 15:47:14 -0400 Subject: [PATCH 06/10] Document my changes in the README file --- README.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 2309a5c..72904f3 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,11 @@ -[jQuery Tools](http://flowplayer.org/tools/) - The Missing UI library for the Web +Klortho fork of [jQuery Tools](http://flowplayer.org/tools/) - The Missing UI library for the Web ================================ -jQuery Tools is a collection of the most important user-interface components for modern websites. Used by large sites all over the world. - -##Contributing - -Please issue pull requests to the [dev branch](https://github.com/jquerytools/jquerytools/tree/dev). - -This is where active development takes place, we then merge changes into master for releases. That will become v1.2.6. -Most of the development goes to 2.0 which is currently a private repository. +This repo is forked form [Patrick64/jquerytools](https://github.com/Patrick64/jquerytools), +who forked from [jquerytools/jquerytools](https://github.com/jquerytools/jquerytools). +Patrick64 added support for touch devices to the rangeinput component. I tweaked +that to make it work better on the Android browser, and also added two new API methods: +* setMax(max) - set a new maximum value, dynamically updating the handle position +* setRange(min, max, val) - change any combination of min, max, or value. If any + of these arguments is *undefined*, then that value will not be changed. From 9a0e53330a6da6127b86b7b2be59c7955d608b00 Mon Sep 17 00:00:00 2001 From: Chris Maloney Date: Mon, 23 Jul 2012 13:01:53 -0400 Subject: [PATCH 07/10] put animate/callback back in (I broke it) --- src/rangeinput/rangeinput.js | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/rangeinput/rangeinput.js b/src/rangeinput/rangeinput.js index b07a410..ff460cf 100755 --- a/src/rangeinput/rangeinput.js +++ b/src/rangeinput/rangeinput.js @@ -230,7 +230,8 @@ input.addClass(css.input); - var fire = $(self).add(input), fireOnSlide = true; + var fire = $(self).add(input); + var fireOnSlide = true; /** @@ -284,6 +285,7 @@ // precision val = round(val, precision); + if (val == value) { return self; } // onSlide var isClick = evt.type == "click"; @@ -293,12 +295,16 @@ if (evt.isDefaultPrevented()) { return self; } } - // speed & callback - var speed = isClick ? conf.speed : 0, - callback = isClick ? function() { - evt.type = "change"; - fire.trigger(evt, [val]); - } : null; + // Speed of animation (really duration): if it was a click, use the configured value; + // if it's a drag, then use zero (instant). + var speed = isClick ? conf.speed : 0; + + // Function called at the end of the animation will fire a change event. + var callback = function() { + console.info("rangeinput: firing a rangeinput change event."); + evt.type = "change"; + fire.trigger(evt, [val]); + }; if (vertical) { handle.animate({top: x}, speed, callback); @@ -307,12 +313,14 @@ } } else { - // Android is very sluggish. We don't want or need animation here, - // so just set the css property directly. Unfortunately, it's still - // sluggish. Might need to play with the CSS3 transform property, which is - // supposed to be very fast. - //handle.animate({left: x}, speed, callback); - handle.css('left', x); + // Android is very sluggish. We don't want or need animation here when we + // are dragging the handle, but since the duration is set to zero when we're + // dragging, I don't think it makes any difference. Note that it might be + // improved now that we only get to this point when the value has changed by + // a discrete step (used to be called with every touchmove event, even when the + // value didn't change.) + handle.animate({left: x}, speed, callback); + //handle.css('left', x); if (conf.progress) { progress.animate({width: x + handle.width() / 2}, speed); } From b53bac6fdf147e5d68ec29a9ab73fc290760b6e3 Mon Sep 17 00:00:00 2001 From: Chris Maloney Date: Thu, 26 Jul 2012 12:18:57 -0400 Subject: [PATCH 08/10] Added debug 'console', currently commented out, for testing --- src/rangeinput/rangeinput.js | 39 +++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/rangeinput/rangeinput.js b/src/rangeinput/rangeinput.js index ff460cf..57ec681 100755 --- a/src/rangeinput/rangeinput.js +++ b/src/rangeinput/rangeinput.js @@ -17,6 +17,31 @@ */ (function($) { + /* Test console. This waits ten seconds, and then pops up an alert box. + + dcon = (function() { + var starttime = (new Date()).getTime(); + var text = "Console, start: " + starttime + ".\n"; + + var info = function(msg) { + var t = (new Date()).getTime() - starttime; + text += t + ": " + msg + "\n"; + }; + var display = function() { + alert(text); + }; + + window.setTimeout(display, 10000); + + return { + starttime: starttime, + info: info, + display: display + }; + })(); + */ + + $.tools = $.tools || {version: '@VERSION'}; var tool; @@ -76,6 +101,7 @@ typeof Modernizer == "undefined" ? "touchstart touchend mousedown mouseup" : Modernizr.touch ? "touchstart touchend" : "mousedown mouseup"; + //dcon.info("Binding to events " + eventlist); doc = doc || $(document).bind(eventlist, function(e) { //dcon.head(e.type); var el = $(e.target); @@ -100,7 +126,7 @@ x0 = e.originalEvent.touches[0].screenX - offset.left; y0 = e.originalEvent.touches[0].screenY - offset.top; } - //dcon.info("x0 = " + x0 + ", y0 = " + y0); + //dcon.info("event " + e.type + ", x0 = " + x0); var start = true; @@ -108,6 +134,7 @@ typeof Modernizer == "undefined" ? "touchmove.drag mousemove.drag" : Modernizr.touch ? "touchmove.drag" : "mousemove.drag"; + //dcon.info("Binding to events " + eventlist); doc.bind(eventlist, function(e) { //dcon.head(e.type); @@ -122,7 +149,7 @@ x = e.originalEvent.touches[0].screenX - x0; y = e.originalEvent.touches[0].screenY - y0; } - //dcon.info("x = " + x + ", y = " + y); + //dcon.info("event " + e.type + ", x = " + x); var props = {}; @@ -148,6 +175,7 @@ draggable.trigger("dragEnd"); } } finally { + //dcon.info("Unbinding from events mousemove.drag touchmove.drag"); doc.unbind("mousemove.drag touchmove.drag"); draggable = null; } @@ -313,14 +341,7 @@ } } else { - // Android is very sluggish. We don't want or need animation here when we - // are dragging the handle, but since the duration is set to zero when we're - // dragging, I don't think it makes any difference. Note that it might be - // improved now that we only get to this point when the value has changed by - // a discrete step (used to be called with every touchmove event, even when the - // value didn't change.) handle.animate({left: x}, speed, callback); - //handle.css('left', x); if (conf.progress) { progress.animate({width: x + handle.width() / 2}, speed); } From d207a0a02e3afc902d93baa17e78c602d949ed0d Mon Sep 17 00:00:00 2001 From: Chris Maloney Date: Mon, 30 Jul 2012 10:56:29 -0400 Subject: [PATCH 09/10] Remove debug message --- src/rangeinput/rangeinput.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rangeinput/rangeinput.js b/src/rangeinput/rangeinput.js index 57ec681..006e470 100755 --- a/src/rangeinput/rangeinput.js +++ b/src/rangeinput/rangeinput.js @@ -329,7 +329,7 @@ // Function called at the end of the animation will fire a change event. var callback = function() { - console.info("rangeinput: firing a rangeinput change event."); + //console.info("rangeinput: firing a rangeinput change event."); evt.type = "change"; fire.trigger(evt, [val]); }; From 5c4b7cb0ae4930a49466d68629c8b78b2e1dfb92 Mon Sep 17 00:00:00 2001 From: Chris Maloney Date: Tue, 7 Aug 2012 14:51:45 -0400 Subject: [PATCH 10/10] PMC-15162 - Fix rangeinput initialization --- src/rangeinput/rangeinput.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rangeinput/rangeinput.js b/src/rangeinput/rangeinput.js index 006e470..c96866b 100755 --- a/src/rangeinput/rangeinput.js +++ b/src/rangeinput/rangeinput.js @@ -522,7 +522,7 @@ function begin() { init(); - self.setValue(conf.value !== undefined ? conf.value : conf.min); + //self.setValue(conf.value !== undefined ? conf.value : conf.min); } begin();