From b9679633861e08f0181fd018f0cf7e664b754f0a Mon Sep 17 00:00:00 2001 From: Martin Koistinen Date: Thu, 7 Mar 2013 14:12:43 +0200 Subject: [PATCH] =?UTF-8?q?Fixed=20step-support,=20removed=20=E2=80=9Cfilt?= =?UTF-8?q?h=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed “filth” by replacing for() with while(). --- range.js | 146 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 76 insertions(+), 70 deletions(-) diff --git a/range.js b/range.js index 1ff2c9b..89a1db2 100644 --- a/range.js +++ b/range.js @@ -2,7 +2,7 @@ * This was from a proposal that James Edwards / Brothercake had during * 2011 Highland Fling - to use select elements as a starting point for * the range element - so it's a pretty darn good fit, I put this together - * during his Q&A. In the end I needed to lift the detection code from + * during his Q&A. In the end I needed to lift the detection code from * Modernizr - which credit really goes to @miketaylr. * My code starts from "if (bool) {" * @@ -10,84 +10,90 @@ * enhance to a input[type=range] copying much of the attributes across. */ !function () { -var rangeTest = document.createElement('input'), - smile = ':)'; -rangeTest.setAttribute('type', 'range'); + var rangeTest = document.createElement('input') + , smile = ':)' + ; -var bool = rangeTest.type !== 'text'; -if (bool) { - rangeTest.style.cssText = 'position:absolute;visibility:hidden;'; - rangeTest.value = smile; - if (rangeTest.style.WebkitAppearance !== undefined ) { + rangeTest.setAttribute('type', 'range'); - document.body.appendChild(rangeTest); - defaultView = document.defaultView; + var bool = rangeTest.type !== 'text'; + if (bool) { + rangeTest.style.cssText = 'position:absolute;visibility:hidden;'; + rangeTest.value = smile; + if (rangeTest.style.WebkitAppearance !== undefined ) { - // Safari 2-4 allows the smiley as a value, despite making a slider - bool = defaultView.getComputedStyle && - defaultView.getComputedStyle(rangeTest, null).WebkitAppearance !== 'textfield' && - // Mobile android web browser has false positive, so must - // check the height to see if the widget is actually there. - (rangeTest.offsetHeight !== 0); + document.body.appendChild(rangeTest); + defaultView = document.defaultView; - document.body.removeChild(rangeTest); - } -} else { - bool = rangeTest.value == smile; -} + // Safari 2-4 allows the smiley as a value, despite making a slider + bool = defaultView.getComputedStyle && + defaultView.getComputedStyle(rangeTest, null).WebkitAppearance !== 'textfield' && + // Mobile android web browser has false positive, so must + // check the height to see if the widget is actually there. + (rangeTest.offsetHeight !== 0); -// if the input[range] is natively supported, then upgrade the + // into a range element. + if (bool) { + function firstChild(el, nodeName) { + nodeName = nodeName.toUpperCase(); + if (el.firstChild.nodeName === nodeName) { + return el.firstChild; + } else { + return el.firstChild.nextSibling; + } } - } - var selects = document.getElementsByTagName('select'), - i = 0; - - for (; i < selects.length; i++) { - if (selects[i].getAttribute('data-type') == 'range') (function (select) { - var range = document.createElement('input'), - parent = select.parentNode; - - range.setAttribute('type', 'range'); - // works with the select element removed from the DOM - select = parent.replaceChild(range, select); - range.autofocus = select.autofocus; - range.disabled = select.disabled; - range.autocomplete = select.autocomplete; // eh? how would this even work? - range.className = select.className; - range.id = select.id; - range.style = select.style; - range.tabindex = select.tabindex; - range.title = select.title; - range.min = firstChild(select, 'option').value; - range.max = lastChild(select, 'option').value; - range.value = select.value; - // Add step support - if ( select.getAttribute('data-type-range-step') ) { - range.step = select.getAttribute('data-type-range-step'); + function lastChild(el, nodeName) { + nodeName = nodeName.toUpperCase(); + if (el.lastChild.nodeName === nodeName) { + return el.lastChild; + } else { + return el.lastChild.previousSibling; } - // yeah, this is filth, but it's because getElementsByTagName is - // a live DOM collection, so when we removed the select element - // the selects object reduced in length. Freaky, eh? - i--; - })(selects[i]); + } + + var selects = document.getElementsByTagName('select') + , select + ; + + while(selects.length) { + var select = selects[0]; + + if (select.getAttribute('data-type') == 'range') (function (select) { + var range = document.createElement('input') + , parent = select.parentNode + ; + + range.setAttribute('type', 'range'); + // works with the select element removed from the DOM + select = parent.replaceChild(range, select); + range.autofocus = select.autofocus; + range.disabled = select.disabled; + range.autocomplete = select.autocomplete; // eh? how would this even work? + range.className = select.className; + range.id = select.id; + range.style = select.style; + range.tabindex = select.tabindex; + range.title = select.title; + range.min = firstChild(select, 'option').value; + range.max = lastChild(select, 'option').value; + // Add step support + // + // This must be set BEFORE copying over the value, else precision may be lost. + // E.g., 3.8 => 4.0 before the step of 0.1 is applied, but then it is too late. + if ( select.getAttribute('data-type-range-step') ) { + range.step = select.getAttribute('data-type-range-step'); + } + // OK, now it should be safe to set the range. + range.value = select.value; + })(select); + } } -} -}(); \ No newline at end of file +}();