slider-shim.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /**
  2. * slider-shim.js
  3. * Minimal jQuery plugin shim for the bootstrap-slider API used by prettygcode.js.
  4. *
  5. * Supports the subset used by PrettyGCode:
  6. * $(el).slider(opts) — init
  7. * $(el).slider("setValue", v) — set value
  8. * $(el).slider("setMax", v) — update max
  9. * $(el).on("slide", fn) — fires with event.value
  10. * $(el).on("slideStart", fn)
  11. * $(el).on("slideStop", fn)
  12. */
  13. (function ($) {
  14. 'use strict';
  15. $.fn.slider = function (optsOrCmd, cmdArg1, cmdArg2, cmdArg3) {
  16. return this.each(function () {
  17. var $el = $(this);
  18. var data = $el.data('_pgslider');
  19. // ---------- init ----------
  20. if (!data || typeof optsOrCmd === 'object') {
  21. var opts = $.extend({
  22. id: null,
  23. orientation: 'horizontal',
  24. reversed: false,
  25. min: 0,
  26. max: 100,
  27. value: 0,
  28. }, typeof optsOrCmd === 'object' ? optsOrCmd : {});
  29. // Build the DOM
  30. var isVertical = opts.orientation === 'vertical';
  31. var trackHtml =
  32. '<div class="slider' + (isVertical ? ' slider-vertical' : '') + '"' +
  33. (opts.id ? ' id="' + opts.id + '"' : '') + '>' +
  34. '<div class="slider-track"><div class="slider-selection"></div></div>' +
  35. '<div class="slider-handle round">0</div>' +
  36. '</div>';
  37. $el.html(trackHtml);
  38. var $slider = $el.find('.slider');
  39. var $handle = $el.find('.slider-handle');
  40. var $selection = $el.find('.slider-selection');
  41. var isDragging = false;
  42. data = {
  43. opts: opts,
  44. $slider: $slider,
  45. $handle: $handle,
  46. $selection: $selection,
  47. };
  48. $el.data('_pgslider', data);
  49. function pct(v) {
  50. var range = data.opts.max - data.opts.min;
  51. if (range === 0) return 0;
  52. var p = (v - data.opts.min) / range * 100;
  53. return opts.reversed ? 100 - p : p;
  54. }
  55. function updateUI(val) {
  56. var p = pct(val);
  57. $handle.text(val);
  58. if (isVertical) {
  59. $handle.css({ top: p + '%', bottom: '' });
  60. $selection.css({ height: (100 - p) + '%', top: p + '%' });
  61. } else {
  62. $handle.css({ left: p + '%' });
  63. $selection.css({ width: p + '%' });
  64. }
  65. }
  66. data.updateUI = updateUI;
  67. updateUI(opts.value);
  68. data.opts.value = opts.value;
  69. // Mouse interaction
  70. function getValueFromEvent(e) {
  71. var offset = $slider.offset();
  72. var range = data.opts.max - data.opts.min;
  73. var p;
  74. if (isVertical) {
  75. var h = $slider.height();
  76. p = (e.pageY - offset.top) / h;
  77. } else {
  78. var w = $slider.width();
  79. p = (e.pageX - offset.left) / w;
  80. }
  81. p = Math.max(0, Math.min(1, p));
  82. if (opts.reversed) p = 1 - p;
  83. return Math.round(data.opts.min + p * range);
  84. }
  85. $slider.on('mousedown', function (e) {
  86. isDragging = true;
  87. var val = getValueFromEvent(e);
  88. data.opts.value = val;
  89. updateUI(val);
  90. var ev = $.Event('slideStart'); ev.value = val;
  91. $el.trigger(ev);
  92. e.preventDefault();
  93. });
  94. $(document).on('mousemove.pgslider_' + $el.attr('id'), function (e) {
  95. if (!isDragging) return;
  96. var val = getValueFromEvent(e);
  97. data.opts.value = val;
  98. updateUI(val);
  99. var ev = $.Event('slide'); ev.value = val;
  100. $el.trigger(ev);
  101. });
  102. $(document).on('mouseup.pgslider_' + $el.attr('id'), function (e) {
  103. if (!isDragging) return;
  104. isDragging = false;
  105. var val = getValueFromEvent(e);
  106. data.opts.value = val;
  107. updateUI(val);
  108. var ev = $.Event('slideStop'); ev.value = val;
  109. $el.trigger(ev);
  110. });
  111. return;
  112. }
  113. // ---------- commands ----------
  114. if (optsOrCmd === 'setValue') {
  115. data.opts.value = cmdArg1;
  116. data.updateUI(cmdArg1);
  117. // prettygcode.js calls slider('setValue', N, false, true) after loading
  118. // — the third arg means "trigger the slide event so listeners update state"
  119. if (cmdArg3) {
  120. var ev = $.Event('slide'); ev.value = cmdArg1; $el.trigger(ev);
  121. }
  122. } else if (optsOrCmd === 'setMax') {
  123. data.opts.max = cmdArg1;
  124. data.updateUI(data.opts.value);
  125. }
  126. });
  127. };
  128. }(jQuery));