UNPKG

jq-button-range-slider

Version:
376 lines (317 loc) 11.5 kB
/* * jq-button-range-slider - v1.0.2 * jQuery range slider plugin with buttons as a values. * https://mohandere.github.io/jq-button-range-slider/ * * Made by Mohan Dere * Under MIT License */ /* global window, document, define, jQuery */ (function(factory) { 'use strict'; if (typeof define === 'function' && define.amd) { define(['jquery'], factory); } else if (typeof exports !== 'undefined') { module.exports = factory(require('jquery')); } else { factory(jQuery); } }(function($) { 'use strict'; var JqButtonRangeSlider = window.JqButtonRangeSlider || {}; JqButtonRangeSlider = (function() { var instanceUid = 0; function JqButtonRangeSlider(element, settings) { var _ = this; _.isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/); _.defaults = { className: "yo-button-range-slider", sliderOptions: [], template: '<% for (var i = 0; i < sliderOptions.length; i++) { %> <button type="button" class="yo-btn yo-range-btn" value="<%=sliderOptions[i].value%>"><%=sliderOptions[i].name%></button><% } %>', }; _.options = $.extend({}, _.defaults, settings); _.$el = $(element); _.$sliderButtons = null; //Slider variables _.lastClickedButtonIndex = -9999; //set to unexpected value //set lower and upper bound _.sliderVars = { lowerBound: { index: -1 }, upperBound: { index: -1 } }; //set length _.sliderLength = _.options.sliderOptions.length; //calculate max index _.sliderMaxIndex = _.sliderLength - 1; //bind this context _.slideHandler = $.proxy(_.slideHandler, _); _.resizeHandler = $.proxy(_.resizeHandler, _); _.instanceUid = instanceUid++; _.init(true); } return JqButtonRangeSlider; }()); //Micro-Templating function JqButtonRangeSlider.prototype.tmpl = function(str, data){ // Figure out if we're getting a template, or if we need to // load the template - and be sure to cache the result. var fn = !/\W/.test(str) ? cache[str] = cache[str] || tmpl(document.getElementById(str).innerHTML) : // Generate a reusable function that will serve as a template // generator (and which will be cached). new Function("obj", "var p=[],print=function(){p.push.apply(p,arguments);};" + // Introduce the data as local variables using with(){} "with(obj){p.push('" + // Convert the template into pure JavaScript str .replace(/[\r\t\n]/g, " ") .split("<%").join("\t") .replace(/((^|%>)[^\t]*)'/g, "$1\r") .replace(/\t=(.*?)%>/g, "',$1,'") .split("\t").join("');") .split("%>").join("p.push('") .split("\r").join("\\'") + "');}return p.join('');"); // Provide some basic currying to the user return data ? fn(data) : fn; }; //init slider JqButtonRangeSlider.prototype.init = function(creation){ var _ = this; //add default class _.$el.addClass(_.options.className); //load html inside element _.$el.html(_.tmpl(_.options.template, { sliderOptions: _.options.sliderOptions })); _.$sliderButtons = _.$el.find(".yo-range-btn"); //bind events on slider _.$sliderButtons //When slider button clicked .click(_.slideHandler); _.$el //when resizing the site, we adjust the heights of the sections, slimScroll... .resize(_.resizeHandler); if (creation) { _.$el.trigger('init', [_]); } }; JqButtonRangeSlider.prototype.slideHandler = function(event){ var _ = this; var $node = $(event.currentTarget); var index = _.$sliderButtons.index($node); var direction = _.getDirectionToMove(index); switch (direction) { case "L": if (_.lastClickedButtonIndex === index || _.deActivateBtnAtIndex(index, direction)) { index += 1; _.setSliderBounds(index); } else { //if lower limit is not set then set both handle at same index if (!_.isLowerBoundSet()) { _.setSliderBounds(index); _.setSliderBounds(index, 1); } else { //if current index is greater than upper limit and direction is L //then set upper limit to index if (index > _.getSliderBounds(1)) { _.setSliderBounds(index, 1); } else { _.setSliderBounds(index); } } } break; case "R": if (_.lastClickedButtonIndex === index || _.deActivateBtnAtIndex(index, direction)) { index -= 1; _.setSliderBounds(index, 1); } else { //if upper limit is not set then set both handle at same index if (!_.isUpperBoundSet()) { _.setSliderBounds(index); _.setSliderBounds(index, 1); } else { //if current index if (index < _.getSliderBounds()) { _.setSliderBounds(index); } else { _.setSliderBounds(index, 1); } } } break; } _.highlightsUI(); //store last clicked btn index _.lastClickedButtonIndex = index; //check wheather we have to reset slider slider //if there is no any selected buttons then reset var l = _.$el.find(".yo-range-btn.active").length; if (!l) { _.reset(); } _.$el.trigger("afterChange", [_.getSliderValue(), _.getSliderRangeValue(), _]); return false; }; JqButtonRangeSlider.prototype.getDirectionToMove = function(goal){ var _ = this; var sliderLimits = [0, _.sliderMaxIndex]; //now after selection the slider middle will be move if(_.isLowerBoundSet() && _.isUpperBoundSet()){ sliderLimits = [_.getSliderBounds(), _.getSliderBounds(1)]; } var closest = sliderLimits.reduce(function (prev, curr) { return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev); }); return (closest === sliderLimits[1]) ? "R" : "L"; }; JqButtonRangeSlider.prototype.deActivateBtnAtIndex = function(index, direction) { var _ = this; //if button is active and its first in active buttons list - when direction is L //if button is active and its last in active buttons list - when direction is R var l = _.$el.find(".yo-range-btn.active").length, r, overallIndex; if (!l) { r = false; } switch (direction) { case "L": var $firstActiveBtn = _.$el.find(".yo-range-btn.active").eq(0); overallIndex = _.$sliderButtons.index($firstActiveBtn); r = overallIndex === index; break; case "R": var $lastActiveBtn = _.$el.find(".yo-range-btn.active").eq(l - 1); overallIndex = _.$sliderButtons.index($lastActiveBtn); r = overallIndex === index; break; } if (!r) { r = false; } return r; }; JqButtonRangeSlider.prototype.highlightsUI = function(){ var _ = this; _.$sliderButtons.removeClass("active"); for (var i = _.sliderVars.lowerBound.index; i <= _.sliderVars.upperBound.index; i++) { _.$sliderButtons.eq(i).addClass("active"); } }; JqButtonRangeSlider.prototype.isLowerBoundSet = function(){ var _ = this; return _.sliderVars.lowerBound.index > -1; }; JqButtonRangeSlider.prototype.isUpperBoundSet = function(){ var _ = this; return _.sliderVars.upperBound.index > -1; }; JqButtonRangeSlider.prototype.getSliderRangeValue = function(){ var _ = this; var lv = _.$sliderButtons.eq(_.sliderVars.lowerBound.index).attr("value"); var uv = _.$sliderButtons.eq(_.sliderVars.upperBound.index).attr("value"); var r = { "lb": { index: _.sliderVars.lowerBound.index, value: lv, }, "ub": { index: _.sliderVars.upperBound.index, value: uv, } }; return r; }; JqButtonRangeSlider.prototype.getSliderValue = function() { var _ = this; var r = []; _.$el.find(".yo-range-btn.active").each(function(index, el) { r.push($(el).val()); }); return r; }; JqButtonRangeSlider.prototype.getSliderBounds = function(isUpper) { var _ = this; if (isUpper) { return _.sliderVars.upperBound.index; } else { return _.sliderVars.lowerBound.index; } }; JqButtonRangeSlider.prototype.setSliderBounds = function(newIndex, isUpper) { var _ = this; if (isUpper) { _.sliderVars.upperBound.index = newIndex; } else { _.sliderVars.lowerBound.index = newIndex; } }; //Plugins internal methods //Exposed to users JqButtonRangeSlider.prototype.reset = function() { var _ = this; _.setSliderBounds(-9999); _.setSliderBounds(-9999, 1); _.highlightsUI(); //store last clicked btn index _.lastClickedButtonIndex = -9999; _.$el.trigger('reset', [_]); }; //destroy current slider instance JqButtonRangeSlider.prototype.destroy = function() { var _ = this; _.$sliderButtons.unbind(); _.$sliderButtons.remove(); _.$el.removeClass(_.options.className); _.$el.trigger('destroy', [_]); }; //set new upper and lower bound JqButtonRangeSlider.prototype.setRange = function(uiHash) { var _ = this; //check if lb and ub is valid or not $.each(_.options.sliderOptions, function(index, option) { if (option.value === uiHash.lb) { _.sliderVars.lowerBound.index = index; _.sliderVars.lowerBound.value = uiHash.lb; } if (option.value === uiHash.ub) { _.sliderVars.upperBound.index = index; _.sliderVars.upperBound.value = uiHash.ub; } }); //set last clicked button as a upper one _.lastClickedButtonIndex = _.sliderVars.upperBound.index; //get indices of new lower and uper bound _.highlightsUI(); }; JqButtonRangeSlider.prototype.resizeHandler = function(){ //do resize operation }; //get current slider JqButtonRangeSlider.prototype.getSlider = function() { return this; }; $.fn.jqButtonRangeSlider = function() { var _ = this, opt = arguments[0], args = Array.prototype.slice.call(arguments, 1), l = _.length, i, ret; for (i = 0; i < l; i++) { if (typeof opt == "object" || typeof opt == "undefined"){ _[i].jqButtonRangeSlider = new JqButtonRangeSlider(_[i], opt); } else{ ret = _[i].jqButtonRangeSlider[opt].apply(_[i].jqButtonRangeSlider, args); } if (typeof ret != "undefined"){ return ret; } } return _; }; }));