Use washington state
[web.git] / js / foundation / foundation.slider.js
1 ;
2 (function ($, window, document, undefined) {
3 'use strict';
4
5 Foundation.libs.slider = {
6 name: 'slider',
7
8 version: '5.5.0',
9
10 settings: {
11 start: 0,
12 end: 100,
13 step: 1,
14 precision: null,
15 initial: null,
16 display_selector: '',
17 vertical: false,
18 trigger_input_change: false,
19 on_change: function () {
20 }
21 },
22
23 cache: {},
24
25 init: function (scope, method, options) {
26 Foundation.inherit(this, 'throttle');
27 this.bindings(method, options);
28 this.reflow();
29 },
30
31 events: function () {
32 var self = this;
33
34 $(this.scope)
35 .off('.slider')
36 .on('mousedown.fndtn.slider touchstart.fndtn.slider pointerdown.fndtn.slider',
37 '[' + self.attr_name() + ']:not(.disabled, [disabled]) .range-slider-handle', function (e) {
38 if (!self.cache.active) {
39 e.preventDefault();
40 self.set_active_slider($(e.target));
41 }
42 })
43 .on('mousemove.fndtn.slider touchmove.fndtn.slider pointermove.fndtn.slider', function (e) {
44 if (!!self.cache.active) {
45 e.preventDefault();
46 if ($.data(self.cache.active[0], 'settings').vertical) {
47 var scroll_offset = 0;
48 if (!e.pageY) {
49 scroll_offset = window.scrollY;
50 }
51 self.calculate_position(self.cache.active, self.get_cursor_position(e, 'y') + scroll_offset);
52 } else {
53 self.calculate_position(self.cache.active, self.get_cursor_position(e, 'x'));
54 }
55 }
56 })
57 .on('mouseup.fndtn.slider touchend.fndtn.slider pointerup.fndtn.slider', function (e) {
58 self.remove_active_slider();
59 })
60 .on('change.fndtn.slider', function (e) {
61 self.settings.on_change();
62 });
63
64 self.S(window)
65 .on('resize.fndtn.slider', self.throttle(function (e) {
66 self.reflow();
67 }, 300));
68 },
69
70 get_cursor_position: function (e, xy) {
71 var pageXY = 'page' + xy.toUpperCase(),
72 clientXY = 'client' + xy.toUpperCase(),
73 position;
74
75 if (typeof e[pageXY] !== 'undefined') {
76 position = e[pageXY];
77 }
78 else if (typeof e.originalEvent[clientXY] !== 'undefined') {
79 position = e.originalEvent[clientXY];
80 }
81 else if (e.originalEvent.touches && e.originalEvent.touches[0] && typeof e.originalEvent.touches[0][clientXY] !== 'undefined') {
82 position = e.originalEvent.touches[0][clientXY];
83 }
84 else if (e.currentPoint && typeof e.currentPoint[xy] !== 'undefined') {
85 position = e.currentPoint[xy];
86 }
87 return position;
88 },
89
90 set_active_slider: function ($handle) {
91 this.cache.active = $handle;
92 },
93
94 remove_active_slider: function () {
95 this.cache.active = null;
96 },
97
98 calculate_position: function ($handle, cursor_x) {
99 var self = this,
100 settings = $.data($handle[0], 'settings'),
101 handle_l = $.data($handle[0], 'handle_l'),
102 handle_o = $.data($handle[0], 'handle_o'),
103 bar_l = $.data($handle[0], 'bar_l'),
104 bar_o = $.data($handle[0], 'bar_o');
105
106 requestAnimationFrame(function () {
107 var pct;
108
109 if (Foundation.rtl && !settings.vertical) {
110 pct = self.limit_to(((bar_o + bar_l - cursor_x) / bar_l), 0, 1);
111 } else {
112 pct = self.limit_to(((cursor_x - bar_o) / bar_l), 0, 1);
113 }
114
115 pct = settings.vertical ? 1 - pct : pct;
116
117 var norm = self.normalized_value(pct, settings.start, settings.end, settings.step, settings.precision);
118
119 self.set_ui($handle, norm);
120 });
121 },
122
123 set_ui: function ($handle, value) {
124 var settings = $.data($handle[0], 'settings'),
125 handle_l = $.data($handle[0], 'handle_l'),
126 bar_l = $.data($handle[0], 'bar_l'),
127 norm_pct = this.normalized_percentage(value, settings.start, settings.end),
128 handle_offset = norm_pct * (bar_l - handle_l) - 1,
129 progress_bar_length = norm_pct * 100,
130 $handle_parent = $handle.parent(),
131 $hidden_inputs = $handle.parent().children('input[type=hidden]');
132
133 if (Foundation.rtl && !settings.vertical) {
134 handle_offset = -handle_offset;
135 }
136
137 handle_offset = settings.vertical ? -handle_offset + bar_l - handle_l + 1 : handle_offset;
138 this.set_translate($handle, handle_offset, settings.vertical);
139
140 if (settings.vertical) {
141 $handle.siblings('.range-slider-active-segment').css('height', progress_bar_length + '%');
142 } else {
143 $handle.siblings('.range-slider-active-segment').css('width', progress_bar_length + '%');
144 }
145
146 $handle_parent.attr(this.attr_name(), value).trigger('change').trigger('change.fndtn.slider');
147
148 $hidden_inputs.val(value);
149 if (settings.trigger_input_change) {
150 $hidden_inputs.trigger('change');
151 }
152
153 if (!$handle[0].hasAttribute('aria-valuemin')) {
154 $handle.attr({
155 'aria-valuemin': settings.start,
156 'aria-valuemax': settings.end
157 });
158 }
159 $handle.attr('aria-valuenow', value);
160
161 if (settings.display_selector != '') {
162 $(settings.display_selector).each(function () {
163 if (this.hasOwnProperty('value')) {
164 $(this).val(value);
165 } else {
166 $(this).text(value);
167 }
168 });
169 }
170
171 },
172
173 normalized_percentage: function (val, start, end) {
174 return Math.min(1, (val - start) / (end - start));
175 },
176
177 normalized_value: function (val, start, end, step, precision) {
178 var range = end - start,
179 point = val * range,
180 mod = (point - (point % step)) / step,
181 rem = point % step,
182 round = ( rem >= step * 0.5 ? step : 0);
183 return ((mod * step + round) + start).toFixed(precision);
184 },
185
186 set_translate: function (ele, offset, vertical) {
187 if (vertical) {
188 $(ele)
189 .css('-webkit-transform', 'translateY(' + offset + 'px)')
190 .css('-moz-transform', 'translateY(' + offset + 'px)')
191 .css('-ms-transform', 'translateY(' + offset + 'px)')
192 .css('-o-transform', 'translateY(' + offset + 'px)')
193 .css('transform', 'translateY(' + offset + 'px)');
194 } else {
195 $(ele)
196 .css('-webkit-transform', 'translateX(' + offset + 'px)')
197 .css('-moz-transform', 'translateX(' + offset + 'px)')
198 .css('-ms-transform', 'translateX(' + offset + 'px)')
199 .css('-o-transform', 'translateX(' + offset + 'px)')
200 .css('transform', 'translateX(' + offset + 'px)');
201 }
202 },
203
204 limit_to: function (val, min, max) {
205 return Math.min(Math.max(val, min), max);
206 },
207
208
209 initialize_settings: function (handle) {
210 var settings = $.extend({}, this.settings, this.data_options($(handle).parent())),
211 decimal_places_match_result;
212
213 if (settings.precision === null) {
214 decimal_places_match_result = ('' + settings.step).match(/\.([\d]*)/);
215 settings.precision = decimal_places_match_result && decimal_places_match_result[1] ? decimal_places_match_result[1].length : 0;
216 }
217
218 if (settings.vertical) {
219 $.data(handle, 'bar_o', $(handle).parent().offset().top);
220 $.data(handle, 'bar_l', $(handle).parent().outerHeight());
221 $.data(handle, 'handle_o', $(handle).offset().top);
222 $.data(handle, 'handle_l', $(handle).outerHeight());
223 } else {
224 $.data(handle, 'bar_o', $(handle).parent().offset().left);
225 $.data(handle, 'bar_l', $(handle).parent().outerWidth());
226 $.data(handle, 'handle_o', $(handle).offset().left);
227 $.data(handle, 'handle_l', $(handle).outerWidth());
228 }
229
230 $.data(handle, 'bar', $(handle).parent());
231 $.data(handle, 'settings', settings);
232 },
233
234 set_initial_position: function ($ele) {
235 var settings = $.data($ele.children('.range-slider-handle')[0], 'settings'),
236 initial = ((typeof settings.initial == 'number' && !isNaN(settings.initial)) ? settings.initial : Math.floor((settings.end - settings.start) * 0.5 / settings.step) * settings.step + settings.start),
237 $handle = $ele.children('.range-slider-handle');
238 this.set_ui($handle, initial);
239 },
240
241 set_value: function (value) {
242 var self = this;
243 $('[' + self.attr_name() + ']', this.scope).each(function () {
244 $(this).attr(self.attr_name(), value);
245 });
246 if (!!$(this.scope).attr(self.attr_name())) {
247 $(this.scope).attr(self.attr_name(), value);
248 }
249 self.reflow();
250 },
251
252 reflow: function () {
253 var self = this;
254 self.S('[' + this.attr_name() + ']').each(function () {
255 var handle = $(this).children('.range-slider-handle')[0],
256 val = $(this).attr(self.attr_name());
257 self.initialize_settings(handle);
258
259 if (val) {
260 self.set_ui($(handle), parseFloat(val));
261 } else {
262 self.set_initial_position($(this));
263 }
264 });
265 }
266 };
267
268 }(jQuery, window, window.document));