]> git.ipfire.org Git - thirdparty/foundation/foundation-sites.git/commitdiff
Adds pow and log transforms to the Slider component
authorMaarten Brouwers <github.com@murb.nl>
Tue, 1 Nov 2016 16:59:08 +0000 (17:59 +0100)
committerMaarten Brouwers <github.com@murb.nl>
Tue, 1 Nov 2016 16:59:08 +0000 (17:59 +0100)
Introduces two settings, `nonLinearBase` and `positionValueFunction` which change the way in which the position of the slider is translated to an actual value.

Besides the default value of â€˜linear' for `positionValueFunction`, 'pow' and a 'log' can be used.

*Example application*

In example below we want to focus on the most recent years, hence we use a logarithmic transformation of the slider:

          <div class="slider" data-slider data-initial-start="2010" data-initial-end="2015" data-step="1" data-start="1950" data-end="2016" data-position-value-function="log">
            <span class="slider-handle" data-slider-handle role="slider" tabindex="1" aria-controls="car_search_year_from"></span>
            <span class="slider-fill" data-slider-fill></span>
            <span class="slider-handle" data-slider-handle role="slider" tabindex="1" aria-controls="car_search_year_to"></span>
          </div>

Since I didn't get the test-framework to run I submitting this for now without tests, if it is absolutely necessary to do so, and this functionality is desired, allow me some time to fix that.

js/foundation.slider.js

index ee539009bf66b1c2352afe1509c53cacdc5819c8..31a9835a05ae039775f015e7918c3a9444402831 100644 (file)
@@ -95,6 +95,63 @@ class Slider {
     }
   }
 
+  /**
+  * @function
+  * @private
+  * @param {Number} value - floating point (the value) to be transformed using to a relative position on the slider (the inverse of _value)
+  */
+  _pctOfBar(value) {
+    var pctOfBar = percent(value - this.options.start, this.options.end - this.options.start)
+
+    switch(this.options.positionValueFunction) {
+    case "pow":
+      pctOfBar = this._logTransform(pctOfBar);
+      break;
+    case "log":
+      pctOfBar = this._powTransform(pctOfBar);
+      break;
+    }
+
+    return pctOfBar.toFixed(2)
+  }
+
+  /**
+  * @function
+  * @private
+  * @param {Number} pctOfBar - floating point, the relative position of the slider (typically between 0-1) to be transformed to a value
+  */
+  _value(pctOfBar) {
+    switch(this.options.positionValueFunction) {
+    case "pow":
+      pctOfBar = this._powTransform(pctOfBar);
+      break;
+    case "log":
+      pctOfBar = this._logTransform(pctOfBar);
+      break;
+    }
+    var value = (this.options.end - this.options.start) * pctOfBar + this.options.start;
+
+    return value
+  }
+
+  /**
+  * @function
+  * @private
+  * @param {Number} value - floating point (typically between 0-1) to be transformed using the log function
+  */
+  _logTransform(value) {
+    return baseLog(this.options.nonLinearBase, ((value*(this.options.nonLinearBase-1))+1))
+  }
+
+  /**
+  * @function
+  * @private
+  * @param {Number} value - floating point (typically between 0-1) to be transformed using the power function
+  */
+  _powTransform(value) {
+    return (Math.pow(this.options.nonLinearBase, value) - 1) / (this.options.nonLinearBase - 1)
+  }
+
   /**
    * Sets the position of the selected handle and fill bar.
    * @function
@@ -142,7 +199,7 @@ class Slider {
         handleDim = $hndl[0].getBoundingClientRect()[hOrW],
         elemDim = this.$element[0].getBoundingClientRect()[hOrW],
         //percentage of bar min/max value based on click or drag point
-        pctOfBar = percent(location - this.options.start, this.options.end - this.options.start).toFixed(2),
+        pctOfBar = this._pctOfBar(location),
         //number of actual pixels to shift the handle, based on the percentage obtained above
         pxToMove = (elemDim - handleDim) * pctOfBar,
         //percentage of bar to shift the handle
@@ -296,7 +353,7 @@ class Slider {
       }
       var offsetPct = percent(barXY, barDim);
 
-      value = (this.options.end - this.options.start) * offsetPct + this.options.start;
+      value = this._value(offsetPct);
 
       // turn everything around for RTL, yay math!
       if (Foundation.rtl() && !this.options.vertical) {value = this.options.end - value;}
@@ -560,7 +617,19 @@ Slider.defaults = {
    * @option
    * @example 500
    */
-  changedDelay: 500
+  changedDelay: 500,
+  /**
+  * Basevalue for non-linear sliders
+  * @option
+  * @example 5
+  */
+  nonLinearBase: 5,
+  /**
+  * Basevalue for non-linear sliders, possible values are: 'linear', 'pow' & 'log'. Pow and Log use the nonLinearBase setting.
+  * @option
+  * @example 'linear'
+  */
+  positionValueFunction: 'linear',
 };
 
 function percent(frac, num) {
@@ -569,6 +638,9 @@ function percent(frac, num) {
 function absPosition($handle, dir, clickPos, param) {
   return Math.abs(($handle.position()[dir] + ($handle[param]() / 2)) - clickPos);
 }
+function baseLog(base, value) {
+  return Math.log(value)/Math.log(base)
+}
 
 // Window exports
 Foundation.plugin(Slider, 'Slider');