Built files from Bizgaze WebServer
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

jquery-ui-slider-pips.js 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. /*! jQuery-ui-Slider-Pips - v1.11.4 - 2016-09-04
  2. * Copyright (c) 2016 Simon Goellner <simey.me@gmail.com>; Licensed MIT */
  3. (function ($) {
  4. "use strict";
  5. var extensionMethods = {
  6. // pips
  7. pips: function (settings) {
  8. var slider = this,
  9. i, j, p,
  10. collection = "",
  11. mousedownHandlers,
  12. min = slider._valueMin(),
  13. max = slider._valueMax(),
  14. pips = (max - min) / slider.options.step,
  15. $handles = slider.element.find(".ui-slider-handle"),
  16. $pips;
  17. var options = {
  18. first: "label",
  19. /* "label", "pip", false */
  20. last: "label",
  21. /* "label", "pip", false */
  22. rest: "pip",
  23. /* "label", "pip", false */
  24. labels: false,
  25. /* [array], { first: "string", rest: [array], last: "string" }, false */
  26. prefix: "",
  27. /* "", string */
  28. suffix: "",
  29. /* "", string */
  30. step: (pips > 100) ? Math.floor(pips * 0.05) : 1,
  31. /* number */
  32. formatLabel: function (value) {
  33. return this.prefix + value + this.suffix;
  34. }
  35. /* function
  36. must return a value to display in the pip labels */
  37. };
  38. if ($.type(settings) === "object" || $.type(settings) === "undefined") {
  39. $.extend(options, settings);
  40. slider.element.data("pips-options", options);
  41. } else {
  42. if (settings === "destroy") {
  43. destroy();
  44. } else if (settings === "refresh") {
  45. slider.element.slider("pips", slider.element.data("pips-options"));
  46. }
  47. return;
  48. }
  49. // we don't want the step ever to be a floating point or negative
  50. // (or 0 actually, so we'll set it to 1 in that case).
  51. slider.options.pipStep = Math.abs(Math.round(options.step)) || 1;
  52. // get rid of all pips that might already exist.
  53. slider.element
  54. .off(".selectPip")
  55. .addClass("ui-slider-pips")
  56. .find(".ui-slider-pip")
  57. .remove();
  58. // small object with functions for marking pips as selected.
  59. var selectPip = {
  60. single: function (value) {
  61. this.resetClasses();
  62. $pips
  63. .filter(".ui-slider-pip-" + this.classLabel(value))
  64. .addClass("ui-slider-pip-selected");
  65. if (slider.options.range) {
  66. $pips.each(function (k, v) {
  67. var pipVal = $(v).children(".ui-slider-label").data("value");
  68. if ((slider.options.range === "min" && pipVal < value) ||
  69. (slider.options.range === "max" && pipVal > value)) {
  70. $(v).addClass("ui-slider-pip-inrange");
  71. }
  72. });
  73. }
  74. },
  75. range: function (values) {
  76. this.resetClasses();
  77. for (i = 0; i < values.length; i++) {
  78. $pips
  79. .filter(".ui-slider-pip-" + this.classLabel(values[i]))
  80. .addClass("ui-slider-pip-selected-" + (i + 1));
  81. }
  82. if (slider.options.range) {
  83. $pips.each(function (k, v) {
  84. var pipVal = $(v).children(".ui-slider-label").data("value");
  85. if (pipVal > values[0] && pipVal < values[1]) {
  86. $(v).addClass("ui-slider-pip-inrange");
  87. }
  88. });
  89. }
  90. },
  91. classLabel: function (value) {
  92. return value.toString().replace(".", "-");
  93. },
  94. resetClasses: function () {
  95. var regex = /(^|\s*)(ui-slider-pip-selected|ui-slider-pip-inrange)(-{1,2}\d+|\s|$)/gi;
  96. $pips.removeClass(function (index, css) {
  97. return (css.match(regex) || []).join(" ");
  98. });
  99. }
  100. };
  101. function getClosestHandle(val) {
  102. var h, k,
  103. sliderVals,
  104. comparedVals,
  105. closestVal,
  106. tempHandles = [],
  107. closestHandle = 0;
  108. if (slider.values() && slider.values().length) {
  109. // get the current values of the slider handles
  110. sliderVals = slider.values();
  111. // find the offset value from the `val` for each
  112. // handle, and store it in a new array
  113. comparedVals = $.map(sliderVals, function (v) {
  114. return Math.abs(v - val);
  115. });
  116. // figure out the closest handles to the value
  117. closestVal = Math.min.apply(Math, comparedVals);
  118. // if a comparedVal is the closestVal, then
  119. // set the value accordingly, and set the closest handle.
  120. for (h = 0; h < comparedVals.length; h++) {
  121. if (comparedVals[h] === closestVal) {
  122. tempHandles.push(h);
  123. }
  124. }
  125. // set the closest handle to the first handle in array,
  126. // just incase we have no _lastChangedValue to compare to.
  127. closestHandle = tempHandles[0];
  128. // now we want to find out if any of the closest handles were
  129. // the last changed handle, if so we specify that handle to change
  130. for (k = 0; k < tempHandles.length; k++) {
  131. if (slider._lastChangedValue === tempHandles[k]) {
  132. closestHandle = tempHandles[k];
  133. }
  134. }
  135. if (slider.options.range && tempHandles.length === 2) {
  136. if (val > sliderVals[1]) {
  137. closestHandle = tempHandles[1];
  138. } else if (val < sliderVals[0]) {
  139. closestHandle = tempHandles[0];
  140. }
  141. }
  142. }
  143. return closestHandle;
  144. }
  145. function destroy() {
  146. slider.element
  147. .off(".selectPip")
  148. .on("mousedown.slider", slider.element.data("mousedown-original"))
  149. .removeClass("ui-slider-pips")
  150. .find(".ui-slider-pip")
  151. .remove();
  152. }
  153. // when we click on a label, we want to make sure the
  154. // slider's handle actually goes to that label!
  155. // so we check all the handles and see which one is closest
  156. // to the label we clicked. If 2 handles are equidistant then
  157. // we move both of them. We also want to trigger focus on the
  158. // handle.
  159. // without this method the label is just treated like a part
  160. // of the slider and there's no accuracy in the selected value
  161. function labelClick(label, e) {
  162. if (slider.option("disabled")) {
  163. return;
  164. }
  165. var val = $(label).data("value"),
  166. indexToChange = getClosestHandle(val);
  167. if (slider.values() && slider.values().length) {
  168. slider.options.values[indexToChange] = slider._trimAlignValue(val);
  169. } else {
  170. slider.options.value = slider._trimAlignValue(val);
  171. }
  172. slider._refreshValue();
  173. slider._change(e, indexToChange);
  174. }
  175. // method for creating a pip. We loop this for creating all
  176. // the pips.
  177. function createPip(which) {
  178. var label,
  179. percent,
  180. number = which,
  181. classes = "ui-slider-pip",
  182. css = "",
  183. value = slider.value(),
  184. values = slider.values(),
  185. labelValue,
  186. classLabel,
  187. labelIndex;
  188. if (which === "first") {
  189. number = 0;
  190. } else if (which === "last") {
  191. number = pips;
  192. }
  193. // labelValue is the actual value of the pip based on the min/step
  194. labelValue = min + (slider.options.step * number);
  195. // classLabel replaces any decimals with hyphens
  196. classLabel = labelValue.toString().replace(".", "-");
  197. // get the index needed for selecting labels out of the array
  198. labelIndex = (number + min) - min;
  199. // we need to set the human-readable label to either the
  200. // corresponding element in the array, or the appropriate
  201. // item in the object... or an empty string.
  202. if ($.type(options.labels) === "array") {
  203. label = options.labels[labelIndex] || "";
  204. } else if ($.type(options.labels) === "object") {
  205. if (which === "first") {
  206. // set first label
  207. label = options.labels.first || "";
  208. } else if (which === "last") {
  209. // set last label
  210. label = options.labels.last || "";
  211. } else if ($.type(options.labels.rest) === "array") {
  212. // set other labels, but our index should start at -1
  213. // because of the first pip.
  214. label = options.labels.rest[labelIndex - 1] || "";
  215. } else {
  216. // urrggh, the options must be f**ked, just show nothing.
  217. label = labelValue;
  218. }
  219. } else {
  220. label = labelValue;
  221. }
  222. if (which === "first") {
  223. // first Pip on the Slider
  224. percent = "0%";
  225. classes += " ui-slider-pip-first";
  226. classes += (options.first === "label") ? " ui-slider-pip-label" : "";
  227. classes += (options.first === false) ? " ui-slider-pip-hide" : "";
  228. } else if (which === "last") {
  229. // last Pip on the Slider
  230. percent = "100%";
  231. classes += " ui-slider-pip-last";
  232. classes += (options.last === "label") ? " ui-slider-pip-label" : "";
  233. classes += (options.last === false) ? " ui-slider-pip-hide" : "";
  234. } else {
  235. // all other Pips
  236. percent = ((100 / pips) * which).toFixed(4) + "%";
  237. classes += (options.rest === "label") ? " ui-slider-pip-label" : "";
  238. classes += (options.rest === false) ? " ui-slider-pip-hide" : "";
  239. }
  240. classes += " ui-slider-pip-" + classLabel;
  241. // add classes for the initial-selected values.
  242. if (values && values.length) {
  243. for (i = 0; i < values.length; i++) {
  244. if (labelValue === values[i]) {
  245. classes += " ui-slider-pip-initial-" + (i + 1);
  246. classes += " ui-slider-pip-selected-" + (i + 1);
  247. }
  248. }
  249. if (slider.options.range) {
  250. if (labelValue > values[0] &&
  251. labelValue < values[1]) {
  252. classes += " ui-slider-pip-inrange";
  253. }
  254. }
  255. } else {
  256. if (labelValue === value) {
  257. classes += " ui-slider-pip-initial";
  258. classes += " ui-slider-pip-selected";
  259. }
  260. if (slider.options.range) {
  261. if ((slider.options.range === "min" && labelValue < value) ||
  262. (slider.options.range === "max" && labelValue > value)) {
  263. classes += " ui-slider-pip-inrange";
  264. }
  265. }
  266. }
  267. css = (slider.options.orientation === "horizontal") ?
  268. "left: " + percent :
  269. "bottom: " + percent;
  270. // add this current pip to the collection
  271. return "<span class=\"" + classes + "\" style=\"" + css + "\">" +
  272. "<span class=\"ui-slider-line\"></span>" +
  273. "<span class=\"ui-slider-label\" data-value=\"" +
  274. labelValue + "\">" + options.formatLabel(label) + "</span>" +
  275. "</span>";
  276. }
  277. // create our first pip
  278. collection += createPip("first");
  279. // for every stop in the slider where we need a pip; create one.
  280. for (p = slider.options.pipStep; p < pips; p += slider.options.pipStep) {
  281. collection += createPip(p);
  282. }
  283. // create our last pip
  284. collection += createPip("last");
  285. // append the collection of pips.
  286. slider.element.append(collection);
  287. // store the pips for setting classes later.
  288. $pips = slider.element.find(".ui-slider-pip");
  289. // store the mousedown handlers for later, just in case we reset
  290. // the slider, the handler would be lost!
  291. if ($._data(slider.element.get(0), "events").mousedown &&
  292. $._data(slider.element.get(0), "events").mousedown.length) {
  293. mousedownHandlers = $._data(slider.element.get(0), "events").mousedown;
  294. } else {
  295. mousedownHandlers = slider.element.data("mousedown-handlers");
  296. }
  297. slider.element.data("mousedown-handlers", mousedownHandlers.slice());
  298. // loop through all the mousedown handlers on the slider,
  299. // and store the original namespaced (.slider) event handler so
  300. // we can trigger it later.
  301. for (j = 0; j < mousedownHandlers.length; j++) {
  302. if (mousedownHandlers[j].namespace === "slider") {
  303. slider.element.data("mousedown-original", mousedownHandlers[j].handler);
  304. }
  305. }
  306. // unbind the mousedown.slider event, because it interferes with
  307. // the labelClick() method (stops smooth animation), and decide
  308. // if we want to trigger the original event based on which element
  309. // was clicked.
  310. slider.element
  311. .off("mousedown.slider")
  312. .on("mousedown.selectPip", function (e) {
  313. var $target = $(e.target),
  314. closest = getClosestHandle($target.data("value")),
  315. $handle = $handles.eq(closest);
  316. $handle.addClass("ui-state-active");
  317. if ($target.is(".ui-slider-label")) {
  318. labelClick($target, e);
  319. slider.element
  320. .one("mouseup.selectPip", function () {
  321. $handle
  322. .removeClass("ui-state-active")
  323. .focus();
  324. });
  325. } else {
  326. var originalMousedown = slider.element.data("mousedown-original");
  327. originalMousedown(e);
  328. }
  329. });
  330. slider.element.on("slide.selectPip slidechange.selectPip", function (e, ui) {
  331. var $slider = $(this),
  332. value = $slider.slider("value"),
  333. values = $slider.slider("values");
  334. if (ui) {
  335. value = ui.value;
  336. values = ui.values;
  337. }
  338. if (slider.values() && slider.values().length) {
  339. selectPip.range(values);
  340. } else {
  341. selectPip.single(value);
  342. }
  343. });
  344. },
  345. // floats
  346. float: function (settings) {
  347. var i,
  348. slider = this,
  349. min = slider._valueMin(),
  350. max = slider._valueMax(),
  351. value = slider._value(),
  352. values = slider._values(),
  353. tipValues = [],
  354. $handles = slider.element.find(".ui-slider-handle");
  355. var options = {
  356. handle: true,
  357. /* false */
  358. pips: false,
  359. /* true */
  360. labels: false,
  361. /* [array], { first: "string", rest: [array], last: "string" }, false */
  362. prefix: "",
  363. /* "", string */
  364. suffix: "",
  365. /* "", string */
  366. event: "slidechange slide",
  367. /* "slidechange", "slide", "slidechange slide" */
  368. formatLabel: function (value) {
  369. return this.prefix + value + this.suffix;
  370. }
  371. /* function
  372. must return a value to display in the floats */
  373. };
  374. if ($.type(settings) === "object" || $.type(settings) === "undefined") {
  375. $.extend(options, settings);
  376. slider.element.data("float-options", options);
  377. } else {
  378. if (settings === "destroy") {
  379. destroy();
  380. } else if (settings === "refresh") {
  381. slider.element.slider("float", slider.element.data("float-options"));
  382. }
  383. return;
  384. }
  385. if (value < min) {
  386. value = min;
  387. }
  388. if (value > max) {
  389. value = max;
  390. }
  391. if (values && values.length) {
  392. for (i = 0; i < values.length; i++) {
  393. if (values[i] < min) {
  394. values[i] = min;
  395. }
  396. if (values[i] > max) {
  397. values[i] = max;
  398. }
  399. }
  400. }
  401. // add a class for the CSS
  402. slider.element
  403. .addClass("ui-slider-float")
  404. .find(".ui-slider-tip, .ui-slider-tip-label")
  405. .remove();
  406. function destroy() {
  407. slider.element
  408. .off(".sliderFloat")
  409. .removeClass("ui-slider-float")
  410. .find(".ui-slider-tip, .ui-slider-tip-label")
  411. .remove();
  412. }
  413. function getPipLabels(values) {
  414. // when checking the array we need to divide
  415. // by the step option, so we store those values here.
  416. var vals = [],
  417. steppedVals = $.map(values, function (v) {
  418. return Math.ceil((v - min) / slider.options.step);
  419. });
  420. // now we just get the values we need to return
  421. // by looping through the values array and assigning the
  422. // label if it exists.
  423. if ($.type(options.labels) === "array") {
  424. for (i = 0; i < values.length; i++) {
  425. vals[i] = options.labels[steppedVals[i]] || values[i];
  426. }
  427. } else if ($.type(options.labels) === "object") {
  428. for (i = 0; i < values.length; i++) {
  429. if (values[i] === min) {
  430. vals[i] = options.labels.first || min;
  431. } else if (values[i] === max) {
  432. vals[i] = options.labels.last || max;
  433. } else if ($.type(options.labels.rest) === "array") {
  434. vals[i] = options.labels.rest[steppedVals[i] - 1] || values[i];
  435. } else {
  436. vals[i] = values[i];
  437. }
  438. }
  439. } else {
  440. for (i = 0; i < values.length; i++) {
  441. vals[i] = values[i];
  442. }
  443. }
  444. return vals;
  445. }
  446. // apply handle tip if settings allows.
  447. if (options.handle) {
  448. // we need to set the human-readable label to either the
  449. // corresponding element in the array, or the appropriate
  450. // item in the object... or an empty string.
  451. tipValues = (slider.values() && slider.values().length) ?
  452. getPipLabels(values) :
  453. getPipLabels([value]);
  454. for (i = 0; i < tipValues.length; i++) {
  455. $handles
  456. .eq(i)
  457. .append($("<span class=\"ui-slider-tip\">" + options.formatLabel(tipValues[i]) + "</span>"));
  458. }
  459. }
  460. if (options.pips) {
  461. // if this slider also has pip-labels, we make those into tips, too.
  462. slider.element.find(".ui-slider-label").each(function (k, v) {
  463. var $this = $(v),
  464. val = [$this.data("value")],
  465. label,
  466. $tip;
  467. label = options.formatLabel(getPipLabels(val)[0]);
  468. // create a tip element
  469. $tip =
  470. $("<span class=\"ui-slider-tip-label\">" + label + "</span>")
  471. .insertAfter($this);
  472. });
  473. }
  474. // check that the event option is actually valid against our
  475. // own list of the slider's events.
  476. if (options.event !== "slide" &&
  477. options.event !== "slidechange" &&
  478. options.event !== "slide slidechange" &&
  479. options.event !== "slidechange slide") {
  480. options.event = "slidechange slide";
  481. }
  482. // when slider changes, update handle tip label.
  483. slider.element
  484. .off(".sliderFloat")
  485. .on(options.event + ".sliderFloat", function (e, ui) {
  486. var uiValue = ($.type(ui.value) === "array") ? ui.value : [ui.value],
  487. val = options.formatLabel(getPipLabels(uiValue)[0]);
  488. $(ui.handle)
  489. .find(".ui-slider-tip")
  490. .html(val);
  491. });
  492. }
  493. };
  494. $.extend(true, $.ui.slider.prototype, extensionMethods);
  495. })(jQuery);