foundation.slider.js 10 KB

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