Custom Web Software Development for the 21st CenturySM

PHP, SQLs, JavaScript, Ajax, HTML5, XHTML, & CSS3: Innovative Enterprise level Scripting for interactive sites, SaaS, & cross-platform desktop apps
  • Home
  • Automotive Dealer Website Development
  • Free software: PHP and JavaScript
  • PHP Rainbow-Maker
  • JavaScript MasterColorPicker
  • UniDOM.js x-browser solution +
  • JavaScript <input type="picker">
  • FormFieldGenie Text-Input Auto-Pop-Up
  • JavaScript <input type="range">
  • Form Input eMail Validation Script
  • PHP eMail Validation Script
  • PHP Utility Functions
  • Web Developer Resources
  • JavaScript powered <input type="range"> solution for older browsers

    The “FD-Slider” package, created and developed by Brian McAllister of Frequency-Decoder, gives older browsers the ability to use the new HTML5 <input type="range"> tag.  His fantastic package works well with basic page layouts, but chokes on some more complicated CSS layouts when the slider’s parent containing element(s) are in a “fixed” or “absolute” position.  The problem seems to be related to the “has layout” bug found in Microsoft’s Internet Exploder, but appears in other browsers as well.  The JavaScript properties offsetWidth and offsetHeight of many of the elements within the positioned element are erroneously found to be zero, and the FD-slider script can not then function correctly.  The solution is to use getComputedStyle() when necessary, but even then the elements must often be given distinct width/height values in your CSS file, or a value of auto is returned and we’re back where we started.  In my practice, though, the only element that seems to always (when a parent is positioned as noted above) need a defined width is the actual FD-slider element that the script adds to the HTML.  Without defining a width in numerical units (px|em|etc.) in your CSS file, the FD-slider displays but will not function when clicked on.  When the positioned parent is positioned absolutely, that seems to be the only needed work-around.  When the positioned parent is in a fixed-position, perhaps every parent of the FD-slider up the DOM-hierarchy to the positioned parent will need to have it’s dimensions set in the CSS file using numerical units.  You will have to experiment to find out!

    I didn’t stop at bug-fixes when I enhanced this project, though.  Modern browsers allow “transformations” using CSS, specifically “rotations.”  The FD-slider package was developed to accommodate vertical sliders as defined by the W3C, but in practice the browsers themselves that do support <input type="range"> natively do not render their sliders vertically when they should.  With a modern browser you can style your slider and rotate it (using transform: rotate(); in your CSS file) to overcome this defiance and achieve the desired result;  but when an element is transformed this way, the JavaScript properties offsetTop and offsetLeft of the transformed element reflect the values before the transformation (rotation), which as you should guess, mucks up the ability of the FD-slider script to determine where on the slider-bar the end-user is clicking (or dragging the handle to).  SoftMoon-WebWare’s enhancement allows the slider to be rotated by any angle (not simply vertical).

    I also found the need to have all mouse-events defined for the original input to be triggered by the FD-slider;  so that functionality has been added to the original script.  These events are onMouseOver, onMouseMove, onMouseOut, onMouseDown, onMouseUp, onClick.  Events are now also triggered in both DOM systems if they exist: standard DOM2 and old MSIE.  I also modified the “auto-finding” behavior (triggered at startup) to target only <input type="range"> inputs, avoiding <input type="number"> — I find no need for a slider with “number” types — that’s what “range” is for!  The original script differentiated the two based on whether the input has a step attribute and is supposed to target only inputs with steps, yet my <input type="number"> would dissapear with no slider in its place.  I never dug into “why” the bug was occurring, I just side-stepped it altogether.  Finally, there seemed to be a typo in the pixelsToPercent function; that was corrected, although I never saw any problems associated with it, nor any changes in performance, but perhaps that was hidden from my view.

    I have not had time to test these changes across all browsers, and indeed, I expect problems with older browsers like MSIE6-7 when rotating the slider(s).  You will have to use conditional comments at least to handle the different ways each browser works.  But as most end-users have generally graduated to MSIE7-8, with more to 9 every-day, the bleak past is fading.  With Opera, Chrome, & FireFox it seems more people stay updated to current versions which allow rotations and, except FireFox, native <input type="range">.  However, rotations are possible in versions of MSIE < 9 using the MS Matrix Filter, and the smart developer can then use this modified FD-Slider script.  Older browsers also do not have the getComputedStyle() function.  You’re SOL there on complex layouts involving positioned parent elements;  but this modified version degrades gracefully in those browsers, so no comparability problems or hacks needed when using this modified script (unless rotating as noted above).  As this demo below will show, all browsers except Internet Exploder (wow! it’s the only one working correctly!) have trouble locating the mouse while dragging the handle when the mouse is directly over the slider bar!  Click and hold on the handle to drag it, move the mouse off the bar, and the handle will then properly follow the mouse.  The browsers return a mouse position of {0,0} when hovering over rotated elements and I don’t see any possible way to work that bug out… Fortunately, it is only relevant to FireFox in my usage and general terms at this time (2013) (since Opera and Chrome have native support for <input type="range"> in the latest versions).

    Instructions on using the FD-Slider script is best left to its creator; see: frequency-decoder.com.  If you plan on rotating your sliders, you will need to add additional attributes to the native <input /> tag and the rotated element, which may be the input itself or a parent that contains it.  I know, I know … … … mixing presentation with content; perhaps soon I can rewrite it to work directly with the matrix values found using getComputedStyle(transformer).transform.  Any slider that is rotated (directly or through its parent transformer) closer to vertical than to horizontal will receive an additional classname: "fd-slider fd-slider-upright".  Contrast this with the fact that sliders that are rendered vertical have the classname "fd-slider-vertical" as opposed to simply "fd-slider".  Finally, note that nothing stops you from rendering the sliders as vertical and rotating them at an angle closer to vertical than horizontal, which will lead to a classname of "fd-slider-vertical fd-slider-upright" and rotating vertical sliders may not work with the modified script (untested).

    <style> samp:last-child { position: relative; border: 2px solid lightblue; height: 22em; width: 42em; } input#loner2, label#foobits2 { position: absolute; } samp > span.fd-slider, input#loner, label#foobits, input#loner2, label#foobits2 { width: 9em; height: 1em; margin: 5em 1em; transform: rotate(61.8deg); -ms-transform: rotate(61.8deg); -webkit-transform: rotate(61.8deg); -moz-transform: rotate(61.8deg); } label#foobits, label#foobits2 { display: block; margin: 7em 1em 9em 1em; } label#foobits > span.fd-slider, label#foobits2 > span.fd-slider { display: inline-block; margin: 0; } label#foobits2 { right: 4em; left: auto; margin: 0; } span.fd-slider { width: 9em; height: 1em; } </style> <samp> <input id="loner" type="range" value="50" min="0" max="100" step="1" data-fd-slider-transformer="loner" data-fd-slider-rotate="61.8" /> <label id="foobits" data-fd-slider-rotate="61.8">foobits:<input type="range" value="50" min="0" max="100" step="1" data-fd-slider-transformer="foobits" /></label> </samp> <samp> <input id="loner2" type="range" value="50" min="0" max="100" step="1" data-fd-slider-transformer="loner2" data-fd-slider-rotate="61.8" /> <label id="foobits2" data-fd-slider-rotate="61.8">foobits:<input type="range" value="50" min="0" max="100" step="1" data-fd-slider-transformer="foobits2" /></label> </samp>

    For an example of using this enhanced FD-Slider script with more complex page-layouts, see our MasterColorPicker project for which the slider script was enhanced.