| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- /**
- * slider-shim.js
- * Minimal jQuery plugin shim for the bootstrap-slider API used by prettygcode.js.
- *
- * Supports the subset used by PrettyGCode:
- * $(el).slider(opts) — init
- * $(el).slider("setValue", v) — set value
- * $(el).slider("setMax", v) — update max
- * $(el).on("slide", fn) — fires with event.value
- * $(el).on("slideStart", fn)
- * $(el).on("slideStop", fn)
- */
- (function ($) {
- 'use strict';
- $.fn.slider = function (optsOrCmd, cmdArg1, cmdArg2, cmdArg3) {
- return this.each(function () {
- var $el = $(this);
- var data = $el.data('_pgslider');
- // ---------- init ----------
- if (!data || typeof optsOrCmd === 'object') {
- var opts = $.extend({
- id: null,
- orientation: 'horizontal',
- reversed: false,
- min: 0,
- max: 100,
- value: 0,
- }, typeof optsOrCmd === 'object' ? optsOrCmd : {});
- // Build the DOM. opts.id is HTML-attribute-escaped before
- // interpolation so a future caller passing a tainted id can't
- // break out of the attribute (CodeQL: js/html-constructed-from-input).
- function escapeAttr(s) {
- return String(s).replace(/&/g, '&')
- .replace(/"/g, '"')
- .replace(/'/g, ''')
- .replace(/</g, '<')
- .replace(/>/g, '>');
- }
- var isVertical = opts.orientation === 'vertical';
- var trackHtml =
- '<div class="slider' + (isVertical ? ' slider-vertical' : '') + '"' +
- (opts.id ? ' id="' + escapeAttr(opts.id) + '"' : '') + '>' +
- '<div class="slider-track"><div class="slider-selection"></div></div>' +
- '<div class="slider-handle round">0</div>' +
- '</div>';
- $el.html(trackHtml);
- var $slider = $el.find('.slider');
- var $handle = $el.find('.slider-handle');
- var $selection = $el.find('.slider-selection');
- var isDragging = false;
- data = {
- opts: opts,
- $slider: $slider,
- $handle: $handle,
- $selection: $selection,
- };
- $el.data('_pgslider', data);
- function pct(v) {
- var range = data.opts.max - data.opts.min;
- if (range === 0) return 0;
- var p = (v - data.opts.min) / range * 100;
- return opts.reversed ? 100 - p : p;
- }
- function updateUI(val) {
- var p = pct(val);
- $handle.text(val);
- if (isVertical) {
- $handle.css({ top: p + '%', bottom: '' });
- $selection.css({ height: (100 - p) + '%', top: p + '%' });
- } else {
- $handle.css({ left: p + '%' });
- $selection.css({ width: p + '%' });
- }
- }
- data.updateUI = updateUI;
- updateUI(opts.value);
- data.opts.value = opts.value;
- // Mouse interaction
- function getValueFromEvent(e) {
- var offset = $slider.offset();
- var range = data.opts.max - data.opts.min;
- var p;
- if (isVertical) {
- var h = $slider.height();
- p = (e.pageY - offset.top) / h;
- } else {
- var w = $slider.width();
- p = (e.pageX - offset.left) / w;
- }
- p = Math.max(0, Math.min(1, p));
- if (opts.reversed) p = 1 - p;
- return Math.round(data.opts.min + p * range);
- }
- $slider.on('mousedown', function (e) {
- isDragging = true;
- var val = getValueFromEvent(e);
- data.opts.value = val;
- updateUI(val);
- var ev = $.Event('slideStart'); ev.value = val;
- $el.trigger(ev);
- e.preventDefault();
- });
- $(document).on('mousemove.pgslider_' + $el.attr('id'), function (e) {
- if (!isDragging) return;
- var val = getValueFromEvent(e);
- data.opts.value = val;
- updateUI(val);
- var ev = $.Event('slide'); ev.value = val;
- $el.trigger(ev);
- });
- $(document).on('mouseup.pgslider_' + $el.attr('id'), function (e) {
- if (!isDragging) return;
- isDragging = false;
- var val = getValueFromEvent(e);
- data.opts.value = val;
- updateUI(val);
- var ev = $.Event('slideStop'); ev.value = val;
- $el.trigger(ev);
- });
- return;
- }
- // ---------- commands ----------
- if (optsOrCmd === 'setValue') {
- data.opts.value = cmdArg1;
- data.updateUI(cmdArg1);
- // prettygcode.js calls slider('setValue', N, false, true) after loading
- // — the third arg means "trigger the slide event so listeners update state"
- if (cmdArg3) {
- var ev = $.Event('slide'); ev.value = cmdArg1; $el.trigger(ev);
- }
- } else if (optsOrCmd === 'setMax') {
- data.opts.max = cmdArg1;
- data.updateUI(data.opts.value);
- }
- });
- };
- }(jQuery));
|