;(function ($, window, document, undefined) { 'use strict'; Foundation.libs.slider = { name : 'slider', version : '{{VERSION}}', settings : { start : 0, end : 100, step : 1, precision : 0, initial : null, display_selector : '', vertical : false, trigger_input_change : false, on_change : function () {} }, cache : {}, init : function (scope, method, options) { Foundation.inherit(this, 'throttle'); this.bindings(method, options); this.reflow(); }, events : function () { var self = this; $(this.scope) .off('.slider') .on('mousedown.fndtn.slider touchstart.fndtn.slider pointerdown.fndtn.slider', '[' + self.attr_name() + ']:not(.disabled, [disabled]) .range-slider-handle', function (e) { if (!self.cache.active) { e.preventDefault(); self.set_active_slider($(e.target)); } }) .on('mousemove.fndtn.slider touchmove.fndtn.slider pointermove.fndtn.slider', function (e) { if (!!self.cache.active) { e.preventDefault(); if ($.data(self.cache.active[0], 'settings').vertical) { var scroll_offset = 0; if (!e.pageY) { scroll_offset = window.scrollY; } self.calculate_position(self.cache.active, self.get_cursor_position(e, 'y') + scroll_offset); } else { self.calculate_position(self.cache.active, self.get_cursor_position(e, 'x')); } } }) .on('mouseup.fndtn.slider touchend.fndtn.slider pointerup.fndtn.slider', function (e) { if(!self.cache.active) { // if the user has just clicked into the slider without starting to drag the handle var slider = $(e.target).attr('role') === 'slider' ? $(e.target) : $(e.target).closest('.range-slider').find("[role='slider']"); if (slider.length && (!slider.parent().hasClass('disabled') && !slider.parent().attr('disabled'))) { self.set_active_slider(slider); if ($.data(self.cache.active[0], 'settings').vertical) { var scroll_offset = 0; if (!e.pageY) { scroll_offset = window.scrollY; } self.calculate_position(self.cache.active, self.get_cursor_position(e, 'y') + scroll_offset); } else { self.calculate_position(self.cache.active, self.get_cursor_position(e, 'x')); } } } self.remove_active_slider(); }) .on('change.fndtn.slider', function (e) { self.settings.on_change(); }); self.S(window) .on('resize.fndtn.slider', self.throttle(function (e) { self.reflow(); }, 300)); // update slider value as users change input value this.S('[' + this.attr_name() + ']').each(function () { var slider = $(this), handle = slider.children('.range-slider-handle')[0], settings = self.initialize_settings(handle); if (settings.display_selector != '') { $(settings.display_selector).each(function(){ if ($(this).attr('value')) { $(this).off('change').on('change', function () { slider.foundation("slider", "set_value", $(this).val()); }); } }); } }); }, get_cursor_position : function (e, xy) { var pageXY = 'page' + xy.toUpperCase(), clientXY = 'client' + xy.toUpperCase(), position; if (typeof e[pageXY] !== 'undefined') { position = e[pageXY]; } else if (typeof e.originalEvent[clientXY] !== 'undefined') { position = e.originalEvent[clientXY]; } else if (e.originalEvent.touches && e.originalEvent.touches[0] && typeof e.originalEvent.touches[0][clientXY] !== 'undefined') { position = e.originalEvent.touches[0][clientXY]; } else if (e.currentPoint && typeof e.currentPoint[xy] !== 'undefined') { position = e.currentPoint[xy]; } return position; }, set_active_slider : function ($handle) { this.cache.active = $handle; }, remove_active_slider : function () { this.cache.active = null; }, calculate_position : function ($handle, cursor_x) { var self = this, settings = $.data($handle[0], 'settings'), handle_l = $.data($handle[0], 'handle_l'), handle_o = $.data($handle[0], 'handle_o'), bar_l = $.data($handle[0], 'bar_l'), bar_o = $.data($handle[0], 'bar_o'); requestAnimationFrame(function () { var pct; if (Foundation.rtl && !settings.vertical) { pct = self.limit_to(((bar_o + bar_l - cursor_x) / bar_l), 0, 1); } else { pct = self.limit_to(((cursor_x - bar_o) / bar_l), 0, 1); } pct = settings.vertical ? 1 - pct : pct; var norm = self.normalized_value(pct, settings.start, settings.end, settings.step, settings.precision); self.set_ui($handle, norm); }); }, set_ui : function ($handle, value) { var settings = $.data($handle[0], 'settings'), handle_l = $.data($handle[0], 'handle_l'), bar_l = $.data($handle[0], 'bar_l'), norm_pct = this.normalized_percentage(value, settings.start, settings.end), handle_offset = norm_pct * (bar_l - handle_l) - 1, progress_bar_length = norm_pct * 100, $handle_parent = $handle.parent(), $hidden_inputs = $handle.parent().children('input[type=hidden]'); if (Foundation.rtl && !settings.vertical) { handle_offset = -handle_offset; } handle_offset = settings.vertical ? -handle_offset + bar_l - handle_l + 1 : handle_offset; this.set_translate($handle, handle_offset, settings.vertical); if (settings.vertical) { $handle.siblings('.range-slider-active-segment').css('height', progress_bar_length + '%'); } else { $handle.siblings('.range-slider-active-segment').css('width', progress_bar_length + '%'); } $handle_parent.attr(this.attr_name(), value).trigger('change.fndtn.slider'); $hidden_inputs.val(value); if (settings.trigger_input_change) { $hidden_inputs.trigger('change.fndtn.slider'); } if (!$handle[0].hasAttribute('aria-valuemin')) { $handle.attr({ 'aria-valuemin' : settings.start, 'aria-valuemax' : settings.end }); } $handle.attr('aria-valuenow', value); if (settings.display_selector != '') { $(settings.display_selector).each(function () { if (this.hasAttribute('value')) { $(this).val(value); } else { $(this).text(value); } }); } }, normalized_percentage : function (val, start, end) { return Math.min(1, (val - start) / (end - start)); }, normalized_value : function (val, start, end, step, precision) { var range = end - start, point = val * range, mod = (point - (point % step)) / step, rem = point % step, round = ( rem >= step * 0.5 ? step : 0); return ((mod * step + round) + start).toFixed(precision); }, set_translate : function (ele, offset, vertical) { if (vertical) { $(ele) .css('-webkit-transform', 'translateY(' + offset + 'px)') .css('-moz-transform', 'translateY(' + offset + 'px)') .css('-ms-transform', 'translateY(' + offset + 'px)') .css('-o-transform', 'translateY(' + offset + 'px)') .css('transform', 'translateY(' + offset + 'px)'); } else { $(ele) .css('-webkit-transform', 'translateX(' + offset + 'px)') .css('-moz-transform', 'translateX(' + offset + 'px)') .css('-ms-transform', 'translateX(' + offset + 'px)') .css('-o-transform', 'translateX(' + offset + 'px)') .css('transform', 'translateX(' + offset + 'px)'); } }, limit_to : function (val, min, max) { return Math.min(Math.max(val, min), max); }, initialize_settings : function (handle) { var settings = $.extend({}, this.settings, this.data_options($(handle).parent())), decimal_places_match_result; if (settings.precision === null) { decimal_places_match_result = ('' + settings.step).match(/\.([\d]*)/); settings.precision = decimal_places_match_result && decimal_places_match_result[1] ? decimal_places_match_result[1].length : 0; } if (settings.vertical) { $.data(handle, 'bar_o', $(handle).parent().offset().top); $.data(handle, 'bar_l', $(handle).parent().outerHeight()); $.data(handle, 'handle_o', $(handle).offset().top); $.data(handle, 'handle_l', $(handle).outerHeight()); } else { $.data(handle, 'bar_o', $(handle).parent().offset().left); $.data(handle, 'bar_l', $(handle).parent().outerWidth()); $.data(handle, 'handle_o', $(handle).offset().left); $.data(handle, 'handle_l', $(handle).outerWidth()); } $.data(handle, 'bar', $(handle).parent()); return $.data(handle, 'settings', settings); }, set_initial_position : function ($ele) { var settings = $.data($ele.children('.range-slider-handle')[0], 'settings'), initial = ((typeof settings.initial == 'number' && !isNaN(settings.initial)) ? settings.initial : Math.floor((settings.end - settings.start) * 0.5 / settings.step) * settings.step + settings.start), $handle = $ele.children('.range-slider-handle'); this.set_ui($handle, initial); }, set_value : function (value) { var self = this; $('[' + self.attr_name() + ']', this.scope).each(function () { $(this).attr(self.attr_name(), value); }); if (!!$(this.scope).attr(self.attr_name())) { $(this.scope).attr(self.attr_name(), value); } self.reflow(); }, reflow : function () { var self = this; self.S('[' + this.attr_name() + ']').each(function () { var handle = $(this).children('.range-slider-handle')[0], val = $(this).attr(self.attr_name()); self.initialize_settings(handle); if (val) { self.set_ui($(handle), parseFloat(val)); } else { self.set_initial_position($(this)); } }); } }; }(jQuery, window, window.document));