phcthemes_admin_panel_pack 4.0.7 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (313) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +20 -20
  3. data/README.md +2 -0
  4. data/Rakefile +8 -8
  5. data/app/assets/config/phcthemes_admin_panel_pack_manifest.js +9 -9
  6. data/app/assets/javascripts/common/backstretch/jquery.backstretch.js +1602 -1602
  7. data/app/assets/javascripts/common/bootstrap/bootstrap.bundle.js +7023 -7023
  8. data/app/assets/javascripts/common/bootstrap/bootstrap.three.js +2377 -2377
  9. data/app/assets/javascripts/common/bootstrap-datepicker/bootstrap-datepicker.js +2039 -2039
  10. data/app/assets/javascripts/common/bootstrap-markdown/bootstrap-markdown.js +1390 -1390
  11. data/app/assets/javascripts/common/bootstrap-select/bootstrap-select.js +0 -0
  12. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-am_ET.js +0 -0
  13. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-am_ET.js.map +0 -0
  14. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-am_ET.min.js +7 -7
  15. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ar_AR.js +0 -0
  16. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ar_AR.js.map +0 -0
  17. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ar_AR.min.js +7 -7
  18. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-bg_BG.js +0 -0
  19. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-bg_BG.js.map +0 -0
  20. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-bg_BG.min.js +7 -7
  21. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-cs_CZ.js +0 -0
  22. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-cs_CZ.js.map +0 -0
  23. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-cs_CZ.min.js +7 -7
  24. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-da_DK.js +0 -0
  25. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-da_DK.js.map +0 -0
  26. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-da_DK.min.js +7 -7
  27. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-de_DE.js +0 -0
  28. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-de_DE.js.map +0 -0
  29. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-de_DE.min.js +7 -7
  30. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-en_US.js +0 -0
  31. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-en_US.js.map +0 -0
  32. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-en_US.min.js +7 -7
  33. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-es_CL.js +0 -0
  34. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-es_CL.js.map +0 -0
  35. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-es_CL.min.js +7 -7
  36. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-es_ES.js +0 -0
  37. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-es_ES.js.map +0 -0
  38. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-es_ES.min.js +7 -7
  39. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-et_EE.js +0 -0
  40. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-et_EE.js.map +0 -0
  41. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-et_EE.min.js +7 -7
  42. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-eu.js +0 -0
  43. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-eu.js.map +0 -0
  44. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-eu.min.js +7 -7
  45. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-fa_IR.js +0 -0
  46. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-fa_IR.js.map +0 -0
  47. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-fa_IR.min.js +7 -7
  48. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-fi_FI.js +0 -0
  49. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-fi_FI.js.map +0 -0
  50. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-fi_FI.min.js +7 -7
  51. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-fr_FR.js +0 -0
  52. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-fr_FR.js.map +0 -0
  53. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-fr_FR.min.js +7 -7
  54. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-hr_HR.js +0 -0
  55. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-hr_HR.js.map +0 -0
  56. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-hr_HR.min.js +7 -7
  57. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-hu_HU.js +0 -0
  58. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-hu_HU.js.map +0 -0
  59. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-hu_HU.min.js +7 -7
  60. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-id_ID.js +0 -0
  61. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-id_ID.js.map +0 -0
  62. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-id_ID.min.js +7 -7
  63. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-it_IT.js +0 -0
  64. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-it_IT.js.map +0 -0
  65. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-it_IT.min.js +7 -7
  66. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ja_JP.js +0 -0
  67. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ja_JP.js.map +0 -0
  68. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ja_JP.min.js +7 -7
  69. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-kh_KM.js +0 -0
  70. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-kh_KM.js.map +0 -0
  71. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-kh_KM.min.js +7 -7
  72. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ko_KR.js +0 -0
  73. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ko_KR.js.map +0 -0
  74. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ko_KR.min.js +7 -7
  75. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-lt_LT.js +0 -0
  76. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-lt_LT.js.map +0 -0
  77. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-lt_LT.min.js +7 -7
  78. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-lv_LV.js +0 -0
  79. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-lv_LV.js.map +0 -0
  80. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-lv_LV.min.js +7 -7
  81. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-nb_NO.js +0 -0
  82. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-nb_NO.js.map +0 -0
  83. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-nb_NO.min.js +7 -7
  84. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-nl_NL.js +0 -0
  85. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-nl_NL.js.map +0 -0
  86. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-nl_NL.min.js +7 -7
  87. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-pl_PL.js +0 -0
  88. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-pl_PL.js.map +0 -0
  89. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-pl_PL.min.js +7 -7
  90. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-pt_BR.js +0 -0
  91. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-pt_BR.js.map +0 -0
  92. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-pt_BR.min.js +7 -7
  93. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-pt_PT.js +0 -0
  94. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-pt_PT.js.map +0 -0
  95. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-pt_PT.min.js +7 -7
  96. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ro_RO.js +0 -0
  97. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ro_RO.js.map +0 -0
  98. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ro_RO.min.js +7 -7
  99. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ru_RU.js +0 -0
  100. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ru_RU.js.map +0 -0
  101. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ru_RU.min.js +7 -7
  102. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-sk_SK.js +0 -0
  103. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-sk_SK.js.map +0 -0
  104. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-sk_SK.min.js +7 -7
  105. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-sl_SI.js +0 -0
  106. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-sl_SI.js.map +0 -0
  107. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-sl_SI.min.js +7 -7
  108. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-sv_SE.js +0 -0
  109. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-sv_SE.js.map +0 -0
  110. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-sv_SE.min.js +7 -7
  111. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-tr_TR.js +0 -0
  112. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-tr_TR.js.map +0 -0
  113. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-tr_TR.min.js +7 -7
  114. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ua_UA.js +0 -0
  115. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ua_UA.js.map +0 -0
  116. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-ua_UA.min.js +7 -7
  117. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-vi_VN.js +0 -0
  118. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-vi_VN.js.map +0 -0
  119. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-vi_VN.min.js +7 -7
  120. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-zh_CN.js +0 -0
  121. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-zh_CN.js.map +0 -0
  122. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-zh_CN.min.js +7 -7
  123. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-zh_TW.js +0 -0
  124. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-zh_TW.js.map +0 -0
  125. data/app/assets/javascripts/common/bootstrap-select/i18n/defaults-zh_TW.min.js +7 -7
  126. data/app/assets/javascripts/common/chartjs/chart.js +0 -0
  127. data/app/assets/javascripts/common/ckeditor/ckeditor.js +6 -6
  128. data/app/assets/javascripts/common/ckeditor/ckeditor.js.map +0 -0
  129. data/app/assets/javascripts/common/ckeditor/translations/af.js +0 -0
  130. data/app/assets/javascripts/common/ckeditor/translations/ar.js +0 -0
  131. data/app/assets/javascripts/common/ckeditor/translations/ast.js +0 -0
  132. data/app/assets/javascripts/common/ckeditor/translations/az.js +0 -0
  133. data/app/assets/javascripts/common/ckeditor/translations/bg.js +0 -0
  134. data/app/assets/javascripts/common/ckeditor/translations/ca.js +0 -0
  135. data/app/assets/javascripts/common/ckeditor/translations/cs.js +0 -0
  136. data/app/assets/javascripts/common/ckeditor/translations/da.js +0 -0
  137. data/app/assets/javascripts/common/ckeditor/translations/de-ch.js +0 -0
  138. data/app/assets/javascripts/common/ckeditor/translations/de.js +0 -0
  139. data/app/assets/javascripts/common/ckeditor/translations/el.js +0 -0
  140. data/app/assets/javascripts/common/ckeditor/translations/en-au.js +0 -0
  141. data/app/assets/javascripts/common/ckeditor/translations/en-gb.js +0 -0
  142. data/app/assets/javascripts/common/ckeditor/translations/eo.js +0 -0
  143. data/app/assets/javascripts/common/ckeditor/translations/es.js +0 -0
  144. data/app/assets/javascripts/common/ckeditor/translations/et.js +0 -0
  145. data/app/assets/javascripts/common/ckeditor/translations/eu.js +0 -0
  146. data/app/assets/javascripts/common/ckeditor/translations/fa.js +0 -0
  147. data/app/assets/javascripts/common/ckeditor/translations/fi.js +0 -0
  148. data/app/assets/javascripts/common/ckeditor/translations/fr.js +0 -0
  149. data/app/assets/javascripts/common/ckeditor/translations/gl.js +0 -0
  150. data/app/assets/javascripts/common/ckeditor/translations/gu.js +0 -0
  151. data/app/assets/javascripts/common/ckeditor/translations/he.js +0 -0
  152. data/app/assets/javascripts/common/ckeditor/translations/hr.js +0 -0
  153. data/app/assets/javascripts/common/ckeditor/translations/hu.js +0 -0
  154. data/app/assets/javascripts/common/ckeditor/translations/id.js +0 -0
  155. data/app/assets/javascripts/common/ckeditor/translations/it.js +0 -0
  156. data/app/assets/javascripts/common/ckeditor/translations/ja.js +0 -0
  157. data/app/assets/javascripts/common/ckeditor/translations/km.js +0 -0
  158. data/app/assets/javascripts/common/ckeditor/translations/kn.js +0 -0
  159. data/app/assets/javascripts/common/ckeditor/translations/ko.js +0 -0
  160. data/app/assets/javascripts/common/ckeditor/translations/ku.js +0 -0
  161. data/app/assets/javascripts/common/ckeditor/translations/lt.js +0 -0
  162. data/app/assets/javascripts/common/ckeditor/translations/lv.js +0 -0
  163. data/app/assets/javascripts/common/ckeditor/translations/nb.js +0 -0
  164. data/app/assets/javascripts/common/ckeditor/translations/ne.js +0 -0
  165. data/app/assets/javascripts/common/ckeditor/translations/nl.js +0 -0
  166. data/app/assets/javascripts/common/ckeditor/translations/no.js +0 -0
  167. data/app/assets/javascripts/common/ckeditor/translations/oc.js +0 -0
  168. data/app/assets/javascripts/common/ckeditor/translations/pl.js +0 -0
  169. data/app/assets/javascripts/common/ckeditor/translations/pt-br.js +0 -0
  170. data/app/assets/javascripts/common/ckeditor/translations/pt.js +0 -0
  171. data/app/assets/javascripts/common/ckeditor/translations/ro.js +0 -0
  172. data/app/assets/javascripts/common/ckeditor/translations/ru.js +0 -0
  173. data/app/assets/javascripts/common/ckeditor/translations/si.js +0 -0
  174. data/app/assets/javascripts/common/ckeditor/translations/sk.js +0 -0
  175. data/app/assets/javascripts/common/ckeditor/translations/sl.js +0 -0
  176. data/app/assets/javascripts/common/ckeditor/translations/sq.js +0 -0
  177. data/app/assets/javascripts/common/ckeditor/translations/sr-latn.js +0 -0
  178. data/app/assets/javascripts/common/ckeditor/translations/sr.js +0 -0
  179. data/app/assets/javascripts/common/ckeditor/translations/sv.js +0 -0
  180. data/app/assets/javascripts/common/ckeditor/translations/th.js +0 -0
  181. data/app/assets/javascripts/common/ckeditor/translations/tr.js +0 -0
  182. data/app/assets/javascripts/common/ckeditor/translations/tt.js +0 -0
  183. data/app/assets/javascripts/common/ckeditor/translations/ug.js +0 -0
  184. data/app/assets/javascripts/common/ckeditor/translations/uk.js +0 -0
  185. data/app/assets/javascripts/common/ckeditor/translations/vi.js +0 -0
  186. data/app/assets/javascripts/common/ckeditor/translations/zh-cn.js +0 -0
  187. data/app/assets/javascripts/common/ckeditor/translations/zh.js +0 -0
  188. data/app/assets/javascripts/common/clipboardjs/clipboard.js +977 -977
  189. data/app/assets/javascripts/common/covervid/covervid.js +94 -94
  190. data/app/assets/javascripts/common/custom/custom.js +0 -0
  191. data/app/assets/javascripts/common/datatables/datatables.js +15310 -15310
  192. data/app/assets/javascripts/common/daterangepicker/daterangepicker.js +1565 -1565
  193. data/app/assets/javascripts/common/fastclick/fastclick.js +841 -841
  194. data/app/assets/javascripts/common/flexslider/jquery.flexslider.js +1252 -1252
  195. data/app/assets/javascripts/common/greenstock/greensock.js +35 -35
  196. data/app/assets/javascripts/common/html5sortable/jquery.sortable.js +98 -98
  197. data/app/assets/javascripts/common/icheck/icheck.js +509 -509
  198. data/app/assets/javascripts/common/imagesloaded/imagesloaded.pkgd.js +497 -497
  199. data/app/assets/javascripts/common/isotope/isotope.pkgd.js +3563 -3563
  200. data/app/assets/javascripts/common/jquery/jquery-3.4.1.js +10598 -10598
  201. data/app/assets/javascripts/common/jquery-countdown/jquery.countdown.js +245 -245
  202. data/app/assets/javascripts/common/jquery-filterizer/jquery.filterizr.min.js +0 -0
  203. data/app/assets/javascripts/common/jquery-jeditable/jquery.jeditable.autogrow.js +37 -37
  204. data/app/assets/javascripts/common/jquery-jeditable/jquery.jeditable.charcounter.js +53 -53
  205. data/app/assets/javascripts/common/jquery-jeditable/jquery.jeditable.checkbox.js +54 -54
  206. data/app/assets/javascripts/common/jquery-jeditable/jquery.jeditable.datepicker.js +59 -59
  207. data/app/assets/javascripts/common/jquery-jeditable/jquery.jeditable.js +823 -823
  208. data/app/assets/javascripts/common/jquery-jeditable/jquery.jeditable.masked.js +46 -46
  209. data/app/assets/javascripts/common/jquery-jeditable/jquery.jeditable.time.js +71 -71
  210. data/app/assets/javascripts/common/jquery-jvectormap/jquery-jvectormap.js +44 -44
  211. data/app/assets/javascripts/common/jquery-placeholder/jquery.placeholder.js +281 -281
  212. data/app/assets/javascripts/common/jquery-slimscroll/jquery.slimscroll.js +474 -474
  213. data/app/assets/javascripts/common/jquery-sparkline/jquery.sparkline.js +3054 -3054
  214. data/app/assets/javascripts/common/jquery-ui/jquery-ui.js +18705 -18705
  215. data/app/assets/javascripts/common/jquery-validation/jquery.validate.js +0 -0
  216. data/app/assets/javascripts/common/jqvmap/jquery.vmap.js +1281 -1281
  217. data/app/assets/javascripts/common/jqvmap/jquery.vmap.min.js +9 -9
  218. data/app/assets/javascripts/common/jqvmap/maps/continents/jquery.vmap.africa.js +2 -2
  219. data/app/assets/javascripts/common/jqvmap/maps/continents/jquery.vmap.asia.js +2 -2
  220. data/app/assets/javascripts/common/jqvmap/maps/continents/jquery.vmap.australia.js +2 -2
  221. data/app/assets/javascripts/common/jqvmap/maps/continents/jquery.vmap.europe.js +2 -2
  222. data/app/assets/javascripts/common/jqvmap/maps/continents/jquery.vmap.north-america.js +2 -2
  223. data/app/assets/javascripts/common/jqvmap/maps/continents/jquery.vmap.south-america.js +2 -2
  224. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.algeria.js +2 -2
  225. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.argentina.js +1 -1
  226. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.brazil.js +2 -2
  227. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.canada.js +1 -1
  228. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.europe.js +2 -2
  229. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.france.js +1 -1
  230. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.germany.js +2 -2
  231. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.greece.js +1 -1
  232. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.iran.js +6 -6
  233. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.iraq.js +1 -1
  234. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.russia.js +2 -2
  235. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.tunisia.js +2 -2
  236. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.turkey.js +11 -11
  237. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.usa.js +2 -2
  238. data/app/assets/javascripts/common/jqvmap/maps/jquery.vmap.world.js +2 -2
  239. data/app/assets/javascripts/common/js-cookie/js.cookie.js +165 -165
  240. data/app/assets/javascripts/common/layerslider/layerslider.kreaturamedia.jquery.js +12 -12
  241. data/app/assets/javascripts/common/layerslider/layerslider.origami.js +12 -12
  242. data/app/assets/javascripts/common/layerslider/layerslider.timeline.js +12 -12
  243. data/app/assets/javascripts/common/layerslider/layerslider.transitions.js +12 -12
  244. data/app/assets/javascripts/common/lazysizes/lazysizes.js +754 -754
  245. data/app/assets/javascripts/common/leaflet/leaflet.js +4 -4
  246. data/app/assets/javascripts/common/magnific-popup/jquery.magnific-popup.js +1859 -1859
  247. data/app/assets/javascripts/common/mapbox/mapbox.js +51 -51
  248. data/app/assets/javascripts/common/metismenu/metisMenu.js +340 -340
  249. data/app/assets/javascripts/common/moderizer/modernizr.js +11 -11
  250. data/app/assets/javascripts/common/nouislider/nouislider.js +2637 -2637
  251. data/app/assets/javascripts/common/owl-carousel/owl.carousel.js +3448 -3448
  252. data/app/assets/javascripts/common/pace/pace.js +935 -935
  253. data/app/assets/javascripts/common/paroller/jquery.paroller.js +228 -228
  254. data/app/assets/javascripts/common/particlejs/particles.js +1540 -1540
  255. data/app/assets/javascripts/common/perfect-scrollbar/perfect-scrollbar.common.js +1318 -1318
  256. data/app/assets/javascripts/common/perfect-scrollbar/perfect-scrollbar.esm.js +1316 -1316
  257. data/app/assets/javascripts/common/perfect-scrollbar/perfect-scrollbar.js +1324 -1324
  258. data/app/assets/javascripts/common/plyr/plyr.js +9137 -9137
  259. data/app/assets/javascripts/common/rangeslider/rangeslider.js +498 -498
  260. data/app/assets/javascripts/common/retina/retina.js +100 -100
  261. data/app/assets/javascripts/common/rev-slider/extensions/revolution.extension.actions.js +0 -0
  262. data/app/assets/javascripts/common/rev-slider/extensions/revolution.extension.carousel.js +0 -0
  263. data/app/assets/javascripts/common/rev-slider/extensions/revolution.extension.kenburn.js +0 -0
  264. data/app/assets/javascripts/common/rev-slider/extensions/revolution.extension.layeranimation.js +0 -0
  265. data/app/assets/javascripts/common/rev-slider/extensions/revolution.extension.migration.js +0 -0
  266. data/app/assets/javascripts/common/rev-slider/extensions/revolution.extension.navigation.js +0 -0
  267. data/app/assets/javascripts/common/rev-slider/extensions/revolution.extension.parallax.js +0 -0
  268. data/app/assets/javascripts/common/rev-slider/extensions/revolution.extension.slideanims.js +0 -0
  269. data/app/assets/javascripts/common/rev-slider/extensions/revolution.extension.video.js +0 -0
  270. data/app/assets/javascripts/common/rev-slider/jquery.themepunch.revolution.js +0 -0
  271. data/app/assets/javascripts/common/rev-slider/jquery.themepunch.tools.min.js +0 -0
  272. data/app/assets/javascripts/common/scrollme/jquery.scrollme.js +455 -455
  273. data/app/assets/javascripts/common/scrollup/jquery.scrollUp.js +168 -168
  274. data/app/assets/javascripts/common/select2/select2.full.js +6597 -6597
  275. data/app/assets/javascripts/common/selectbox/jquery.selectBox.js +1091 -1091
  276. data/app/assets/javascripts/common/slick/slick.js +3004 -3004
  277. data/app/assets/javascripts/common/smooth-scroll/SmoothScroll.js +788 -788
  278. data/app/assets/javascripts/common/spectrum/spectrum.js +2323 -2323
  279. data/app/assets/javascripts/common/stepper/jquery.fs.stepper.js +339 -339
  280. data/app/assets/javascripts/common/swiper/swiper.js +8124 -8124
  281. data/app/assets/javascripts/common/toaster/toastr.js +476 -476
  282. data/app/assets/javascripts/common/typed/typed.js +1044 -1044
  283. data/app/assets/javascripts/common/visable/jquery.visible.js +68 -68
  284. data/app/assets/javascripts/common/waypoints/jquery.waypoints.js +661 -661
  285. data/app/assets/javascripts/common/wow/wow.js +508 -508
  286. data/app/assets/javascripts/phcthemes_admin_panel_pack_adminlte.js +12 -12
  287. data/app/assets/javascripts/phcthemes_admin_panel_pack_boomerang.js +0 -0
  288. data/app/assets/javascripts/phcthemes_admin_panel_pack_coloradmin.js +5 -5
  289. data/app/assets/javascripts/phcthemes_admin_panel_pack_inspinia.js +10 -10
  290. data/app/assets/javascripts/phcthemes_admin_panel_pack_metronic.js +6 -6
  291. data/app/assets/javascripts/phcthemes_admin_panel_pack_quilpro.js +5 -5
  292. data/app/assets/javascripts/phcthemes_admin_panel_pack_starlight.js +5 -5
  293. data/app/assets/javascripts/themes/adminlte/theme/adminlte.js +1141 -1141
  294. data/app/assets/javascripts/themes/coloradmin/theme/color_admin_app.min.js +0 -0
  295. data/app/assets/javascripts/themes/coloradmin/theme/color_admin_default.js +0 -0
  296. data/app/assets/javascripts/themes/inspinia/theme/inspinia.js +279 -279
  297. data/app/assets/javascripts/themes/metronic/theme/plugins.bundle.js +0 -0
  298. data/app/assets/javascripts/themes/metronic/theme/prismjs.bundle.js +1922 -1922
  299. data/app/assets/javascripts/themes/metronic/theme/scripts.bundle.js +0 -0
  300. data/app/assets/javascripts/themes/metronic/theme/widgets.js +0 -0
  301. data/app/assets/stylesheets/common/hanna_hearts/hanna_hearts.scss +0 -0
  302. data/app/assets/stylesheets/phcthemes_admin_panel_pack_adminlte.scss +16 -16
  303. data/app/assets/stylesheets/phcthemes_admin_panel_pack_boomerang.scss +27 -27
  304. data/app/assets/stylesheets/phcthemes_admin_panel_pack_coloradmin.scss +11 -11
  305. data/app/assets/stylesheets/phcthemes_admin_panel_pack_inspinia.scss +18 -18
  306. data/app/assets/stylesheets/phcthemes_admin_panel_pack_metronic.scss +15 -15
  307. data/app/assets/stylesheets/phcthemes_admin_panel_pack_quilpro.scss +19 -19
  308. data/app/assets/stylesheets/phcthemes_admin_panel_pack_starlight.scss +15 -15
  309. data/lib/phcthemes_admin_panel_pack/engine.rb +20 -20
  310. data/lib/phcthemes_admin_panel_pack/version.rb +3 -3
  311. data/lib/phcthemes_admin_panel_pack.rb +6 -6
  312. data/lib/tasks/phcthemes_admin_panel_pack_tasks.rake +4 -4
  313. metadata +3 -3
@@ -1,2637 +1,2637 @@
1
- /*! nouislider - 14.5.0 - 5/11/2020 */
2
- (function(factory) {
3
- if (typeof define === "function" && define.amd) {
4
- // AMD. Register as an anonymous module.
5
- define([], factory);
6
- } else if (typeof exports === "object") {
7
- // Node/CommonJS
8
- module.exports = factory();
9
- } else {
10
- // Browser globals
11
- window.noUiSlider = factory();
12
- }
13
- })(function() {
14
- "use strict";
15
-
16
- var VERSION = "14.5.0";
17
-
18
- //region Helper Methods
19
-
20
- function isValidFormatter(entry) {
21
- return typeof entry === "object" && typeof entry.to === "function" && typeof entry.from === "function";
22
- }
23
-
24
- function removeElement(el) {
25
- el.parentElement.removeChild(el);
26
- }
27
-
28
- function isSet(value) {
29
- return value !== null && value !== undefined;
30
- }
31
-
32
- // Bindable version
33
- function preventDefault(e) {
34
- e.preventDefault();
35
- }
36
-
37
- // Removes duplicates from an array.
38
- function unique(array) {
39
- return array.filter(function(a) {
40
- return !this[a] ? (this[a] = true) : false;
41
- }, {});
42
- }
43
-
44
- // Round a value to the closest 'to'.
45
- function closest(value, to) {
46
- return Math.round(value / to) * to;
47
- }
48
-
49
- // Current position of an element relative to the document.
50
- function offset(elem, orientation) {
51
- var rect = elem.getBoundingClientRect();
52
- var doc = elem.ownerDocument;
53
- var docElem = doc.documentElement;
54
- var pageOffset = getPageOffset(doc);
55
-
56
- // getBoundingClientRect contains left scroll in Chrome on Android.
57
- // I haven't found a feature detection that proves this. Worst case
58
- // scenario on mis-match: the 'tap' feature on horizontal sliders breaks.
59
- if (/webkit.*Chrome.*Mobile/i.test(navigator.userAgent)) {
60
- pageOffset.x = 0;
61
- }
62
-
63
- return orientation
64
- ? rect.top + pageOffset.y - docElem.clientTop
65
- : rect.left + pageOffset.x - docElem.clientLeft;
66
- }
67
-
68
- // Checks whether a value is numerical.
69
- function isNumeric(a) {
70
- return typeof a === "number" && !isNaN(a) && isFinite(a);
71
- }
72
-
73
- // Sets a class and removes it after [duration] ms.
74
- function addClassFor(element, className, duration) {
75
- if (duration > 0) {
76
- addClass(element, className);
77
- setTimeout(function() {
78
- removeClass(element, className);
79
- }, duration);
80
- }
81
- }
82
-
83
- // Limits a value to 0 - 100
84
- function limit(a) {
85
- return Math.max(Math.min(a, 100), 0);
86
- }
87
-
88
- // Wraps a variable as an array, if it isn't one yet.
89
- // Note that an input array is returned by reference!
90
- function asArray(a) {
91
- return Array.isArray(a) ? a : [a];
92
- }
93
-
94
- // Counts decimals
95
- function countDecimals(numStr) {
96
- numStr = String(numStr);
97
- var pieces = numStr.split(".");
98
- return pieces.length > 1 ? pieces[1].length : 0;
99
- }
100
-
101
- // http://youmightnotneedjquery.com/#add_class
102
- function addClass(el, className) {
103
- if (el.classList && !/\s/.test(className)) {
104
- el.classList.add(className);
105
- } else {
106
- el.className += " " + className;
107
- }
108
- }
109
-
110
- // http://youmightnotneedjquery.com/#remove_class
111
- function removeClass(el, className) {
112
- if (el.classList && !/\s/.test(className)) {
113
- el.classList.remove(className);
114
- } else {
115
- el.className = el.className.replace(
116
- new RegExp("(^|\\b)" + className.split(" ").join("|") + "(\\b|$)", "gi"),
117
- " "
118
- );
119
- }
120
- }
121
-
122
- // https://plainjs.com/javascript/attributes/adding-removing-and-testing-for-classes-9/
123
- function hasClass(el, className) {
124
- return el.classList
125
- ? el.classList.contains(className)
126
- : new RegExp("\\b" + className + "\\b").test(el.className);
127
- }
128
-
129
- // https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY#Notes
130
- function getPageOffset(doc) {
131
- var supportPageOffset = window.pageXOffset !== undefined;
132
- var isCSS1Compat = (doc.compatMode || "") === "CSS1Compat";
133
- var x = supportPageOffset
134
- ? window.pageXOffset
135
- : isCSS1Compat
136
- ? doc.documentElement.scrollLeft
137
- : doc.body.scrollLeft;
138
- var y = supportPageOffset
139
- ? window.pageYOffset
140
- : isCSS1Compat
141
- ? doc.documentElement.scrollTop
142
- : doc.body.scrollTop;
143
-
144
- return {
145
- x: x,
146
- y: y
147
- };
148
- }
149
-
150
- // we provide a function to compute constants instead
151
- // of accessing window.* as soon as the module needs it
152
- // so that we do not compute anything if not needed
153
- function getActions() {
154
- // Determine the events to bind. IE11 implements pointerEvents without
155
- // a prefix, which breaks compatibility with the IE10 implementation.
156
- return window.navigator.pointerEnabled
157
- ? {
158
- start: "pointerdown",
159
- move: "pointermove",
160
- end: "pointerup"
161
- }
162
- : window.navigator.msPointerEnabled
163
- ? {
164
- start: "MSPointerDown",
165
- move: "MSPointerMove",
166
- end: "MSPointerUp"
167
- }
168
- : {
169
- start: "mousedown touchstart",
170
- move: "mousemove touchmove",
171
- end: "mouseup touchend"
172
- };
173
- }
174
-
175
- // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
176
- // Issue #785
177
- function getSupportsPassive() {
178
- var supportsPassive = false;
179
-
180
- /* eslint-disable */
181
- try {
182
- var opts = Object.defineProperty({}, "passive", {
183
- get: function() {
184
- supportsPassive = true;
185
- }
186
- });
187
-
188
- window.addEventListener("test", null, opts);
189
- } catch (e) {}
190
- /* eslint-enable */
191
-
192
- return supportsPassive;
193
- }
194
-
195
- function getSupportsTouchActionNone() {
196
- return window.CSS && CSS.supports && CSS.supports("touch-action", "none");
197
- }
198
-
199
- //endregion
200
-
201
- //region Range Calculation
202
-
203
- // Determine the size of a sub-range in relation to a full range.
204
- function subRangeRatio(pa, pb) {
205
- return 100 / (pb - pa);
206
- }
207
-
208
- // (percentage) How many percent is this value of this range?
209
- function fromPercentage(range, value, startRange) {
210
- return (value * 100) / (range[startRange + 1] - range[startRange]);
211
- }
212
-
213
- // (percentage) Where is this value on this range?
214
- function toPercentage(range, value) {
215
- return fromPercentage(range, range[0] < 0 ? value + Math.abs(range[0]) : value - range[0], 0);
216
- }
217
-
218
- // (value) How much is this percentage on this range?
219
- function isPercentage(range, value) {
220
- return (value * (range[1] - range[0])) / 100 + range[0];
221
- }
222
-
223
- function getJ(value, arr) {
224
- var j = 1;
225
-
226
- while (value >= arr[j]) {
227
- j += 1;
228
- }
229
-
230
- return j;
231
- }
232
-
233
- // (percentage) Input a value, find where, on a scale of 0-100, it applies.
234
- function toStepping(xVal, xPct, value) {
235
- if (value >= xVal.slice(-1)[0]) {
236
- return 100;
237
- }
238
-
239
- var j = getJ(value, xVal);
240
- var va = xVal[j - 1];
241
- var vb = xVal[j];
242
- var pa = xPct[j - 1];
243
- var pb = xPct[j];
244
-
245
- return pa + toPercentage([va, vb], value) / subRangeRatio(pa, pb);
246
- }
247
-
248
- // (value) Input a percentage, find where it is on the specified range.
249
- function fromStepping(xVal, xPct, value) {
250
- // There is no range group that fits 100
251
- if (value >= 100) {
252
- return xVal.slice(-1)[0];
253
- }
254
-
255
- var j = getJ(value, xPct);
256
- var va = xVal[j - 1];
257
- var vb = xVal[j];
258
- var pa = xPct[j - 1];
259
- var pb = xPct[j];
260
-
261
- return isPercentage([va, vb], (value - pa) * subRangeRatio(pa, pb));
262
- }
263
-
264
- // (percentage) Get the step that applies at a certain value.
265
- function getStep(xPct, xSteps, snap, value) {
266
- if (value === 100) {
267
- return value;
268
- }
269
-
270
- var j = getJ(value, xPct);
271
- var a = xPct[j - 1];
272
- var b = xPct[j];
273
-
274
- // If 'snap' is set, steps are used as fixed points on the slider.
275
- if (snap) {
276
- // Find the closest position, a or b.
277
- if (value - a > (b - a) / 2) {
278
- return b;
279
- }
280
-
281
- return a;
282
- }
283
-
284
- if (!xSteps[j - 1]) {
285
- return value;
286
- }
287
-
288
- return xPct[j - 1] + closest(value - xPct[j - 1], xSteps[j - 1]);
289
- }
290
-
291
- function handleEntryPoint(index, value, that) {
292
- var percentage;
293
-
294
- // Wrap numerical input in an array.
295
- if (typeof value === "number") {
296
- value = [value];
297
- }
298
-
299
- // Reject any invalid input, by testing whether value is an array.
300
- if (!Array.isArray(value)) {
301
- throw new Error("noUiSlider (" + VERSION + "): 'range' contains invalid value.");
302
- }
303
-
304
- // Covert min/max syntax to 0 and 100.
305
- if (index === "min") {
306
- percentage = 0;
307
- } else if (index === "max") {
308
- percentage = 100;
309
- } else {
310
- percentage = parseFloat(index);
311
- }
312
-
313
- // Check for correct input.
314
- if (!isNumeric(percentage) || !isNumeric(value[0])) {
315
- throw new Error("noUiSlider (" + VERSION + "): 'range' value isn't numeric.");
316
- }
317
-
318
- // Store values.
319
- that.xPct.push(percentage);
320
- that.xVal.push(value[0]);
321
-
322
- // NaN will evaluate to false too, but to keep
323
- // logging clear, set step explicitly. Make sure
324
- // not to override the 'step' setting with false.
325
- if (!percentage) {
326
- if (!isNaN(value[1])) {
327
- that.xSteps[0] = value[1];
328
- }
329
- } else {
330
- that.xSteps.push(isNaN(value[1]) ? false : value[1]);
331
- }
332
-
333
- that.xHighestCompleteStep.push(0);
334
- }
335
-
336
- function handleStepPoint(i, n, that) {
337
- // Ignore 'false' stepping.
338
- if (!n) {
339
- return;
340
- }
341
-
342
- // Step over zero-length ranges (#948);
343
- if (that.xVal[i] === that.xVal[i + 1]) {
344
- that.xSteps[i] = that.xHighestCompleteStep[i] = that.xVal[i];
345
-
346
- return;
347
- }
348
-
349
- // Factor to range ratio
350
- that.xSteps[i] =
351
- fromPercentage([that.xVal[i], that.xVal[i + 1]], n, 0) / subRangeRatio(that.xPct[i], that.xPct[i + 1]);
352
-
353
- var totalSteps = (that.xVal[i + 1] - that.xVal[i]) / that.xNumSteps[i];
354
- var highestStep = Math.ceil(Number(totalSteps.toFixed(3)) - 1);
355
- var step = that.xVal[i] + that.xNumSteps[i] * highestStep;
356
-
357
- that.xHighestCompleteStep[i] = step;
358
- }
359
-
360
- //endregion
361
-
362
- //region Spectrum
363
-
364
- function Spectrum(entry, snap, singleStep) {
365
- this.xPct = [];
366
- this.xVal = [];
367
- this.xSteps = [singleStep || false];
368
- this.xNumSteps = [false];
369
- this.xHighestCompleteStep = [];
370
-
371
- this.snap = snap;
372
-
373
- var index;
374
- var ordered = []; // [0, 'min'], [1, '50%'], [2, 'max']
375
-
376
- // Map the object keys to an array.
377
- for (index in entry) {
378
- if (entry.hasOwnProperty(index)) {
379
- ordered.push([entry[index], index]);
380
- }
381
- }
382
-
383
- // Sort all entries by value (numeric sort).
384
- if (ordered.length && typeof ordered[0][0] === "object") {
385
- ordered.sort(function(a, b) {
386
- return a[0][0] - b[0][0];
387
- });
388
- } else {
389
- ordered.sort(function(a, b) {
390
- return a[0] - b[0];
391
- });
392
- }
393
-
394
- // Convert all entries to subranges.
395
- for (index = 0; index < ordered.length; index++) {
396
- handleEntryPoint(ordered[index][1], ordered[index][0], this);
397
- }
398
-
399
- // Store the actual step values.
400
- // xSteps is sorted in the same order as xPct and xVal.
401
- this.xNumSteps = this.xSteps.slice(0);
402
-
403
- // Convert all numeric steps to the percentage of the subrange they represent.
404
- for (index = 0; index < this.xNumSteps.length; index++) {
405
- handleStepPoint(index, this.xNumSteps[index], this);
406
- }
407
- }
408
-
409
- Spectrum.prototype.getDistance = function(value) {
410
- var index;
411
- var distances = [];
412
-
413
- for (index = 0; index < this.xNumSteps.length - 1; index++) {
414
- // last "range" can't contain step size as it is purely an endpoint.
415
- var step = this.xNumSteps[index];
416
-
417
- if (step && (value / step) % 1 !== 0) {
418
- throw new Error(
419
- "noUiSlider (" +
420
- VERSION +
421
- "): 'limit', 'margin' and 'padding' of " +
422
- this.xPct[index] +
423
- "% range must be divisible by step."
424
- );
425
- }
426
-
427
- // Calculate percentual distance in current range of limit, margin or padding
428
- distances[index] = fromPercentage(this.xVal, value, index);
429
- }
430
-
431
- return distances;
432
- };
433
-
434
- // Calculate the percentual distance over the whole scale of ranges.
435
- // direction: 0 = backwards / 1 = forwards
436
- Spectrum.prototype.getAbsoluteDistance = function(value, distances, direction) {
437
- var xPct_index = 0;
438
-
439
- // Calculate range where to start calculation
440
- if (value < this.xPct[this.xPct.length - 1]) {
441
- while (value > this.xPct[xPct_index + 1]) {
442
- xPct_index++;
443
- }
444
- } else if (value === this.xPct[this.xPct.length - 1]) {
445
- xPct_index = this.xPct.length - 2;
446
- }
447
-
448
- // If looking backwards and the value is exactly at a range separator then look one range further
449
- if (!direction && value === this.xPct[xPct_index + 1]) {
450
- xPct_index++;
451
- }
452
-
453
- var start_factor;
454
- var rest_factor = 1;
455
-
456
- var rest_rel_distance = distances[xPct_index];
457
-
458
- var range_pct = 0;
459
-
460
- var rel_range_distance = 0;
461
- var abs_distance_counter = 0;
462
- var range_counter = 0;
463
-
464
- // Calculate what part of the start range the value is
465
- if (direction) {
466
- start_factor = (value - this.xPct[xPct_index]) / (this.xPct[xPct_index + 1] - this.xPct[xPct_index]);
467
- } else {
468
- start_factor = (this.xPct[xPct_index + 1] - value) / (this.xPct[xPct_index + 1] - this.xPct[xPct_index]);
469
- }
470
-
471
- // Do until the complete distance across ranges is calculated
472
- while (rest_rel_distance > 0) {
473
- // Calculate the percentage of total range
474
- range_pct = this.xPct[xPct_index + 1 + range_counter] - this.xPct[xPct_index + range_counter];
475
-
476
- // Detect if the margin, padding or limit is larger then the current range and calculate
477
- if (distances[xPct_index + range_counter] * rest_factor + 100 - start_factor * 100 > 100) {
478
- // If larger then take the percentual distance of the whole range
479
- rel_range_distance = range_pct * start_factor;
480
- // Rest factor of relative percentual distance still to be calculated
481
- rest_factor = (rest_rel_distance - 100 * start_factor) / distances[xPct_index + range_counter];
482
- // Set start factor to 1 as for next range it does not apply.
483
- start_factor = 1;
484
- } else {
485
- // If smaller or equal then take the percentual distance of the calculate percentual part of that range
486
- rel_range_distance = ((distances[xPct_index + range_counter] * range_pct) / 100) * rest_factor;
487
- // No rest left as the rest fits in current range
488
- rest_factor = 0;
489
- }
490
-
491
- if (direction) {
492
- abs_distance_counter = abs_distance_counter - rel_range_distance;
493
- // Limit range to first range when distance becomes outside of minimum range
494
- if (this.xPct.length + range_counter >= 1) {
495
- range_counter--;
496
- }
497
- } else {
498
- abs_distance_counter = abs_distance_counter + rel_range_distance;
499
- // Limit range to last range when distance becomes outside of maximum range
500
- if (this.xPct.length - range_counter >= 1) {
501
- range_counter++;
502
- }
503
- }
504
-
505
- // Rest of relative percentual distance still to be calculated
506
- rest_rel_distance = distances[xPct_index + range_counter] * rest_factor;
507
- }
508
-
509
- return value + abs_distance_counter;
510
- };
511
-
512
- Spectrum.prototype.toStepping = function(value) {
513
- value = toStepping(this.xVal, this.xPct, value);
514
-
515
- return value;
516
- };
517
-
518
- Spectrum.prototype.fromStepping = function(value) {
519
- return fromStepping(this.xVal, this.xPct, value);
520
- };
521
-
522
- Spectrum.prototype.getStep = function(value) {
523
- value = getStep(this.xPct, this.xSteps, this.snap, value);
524
-
525
- return value;
526
- };
527
-
528
- Spectrum.prototype.getDefaultStep = function(value, isDown, size) {
529
- var j = getJ(value, this.xPct);
530
-
531
- // When at the top or stepping down, look at the previous sub-range
532
- if (value === 100 || (isDown && value === this.xPct[j - 1])) {
533
- j = Math.max(j - 1, 1);
534
- }
535
-
536
- return (this.xVal[j] - this.xVal[j - 1]) / size;
537
- };
538
-
539
- Spectrum.prototype.getNearbySteps = function(value) {
540
- var j = getJ(value, this.xPct);
541
-
542
- return {
543
- stepBefore: {
544
- startValue: this.xVal[j - 2],
545
- step: this.xNumSteps[j - 2],
546
- highestStep: this.xHighestCompleteStep[j - 2]
547
- },
548
- thisStep: {
549
- startValue: this.xVal[j - 1],
550
- step: this.xNumSteps[j - 1],
551
- highestStep: this.xHighestCompleteStep[j - 1]
552
- },
553
- stepAfter: {
554
- startValue: this.xVal[j],
555
- step: this.xNumSteps[j],
556
- highestStep: this.xHighestCompleteStep[j]
557
- }
558
- };
559
- };
560
-
561
- Spectrum.prototype.countStepDecimals = function() {
562
- var stepDecimals = this.xNumSteps.map(countDecimals);
563
- return Math.max.apply(null, stepDecimals);
564
- };
565
-
566
- // Outside testing
567
- Spectrum.prototype.convert = function(value) {
568
- return this.getStep(this.toStepping(value));
569
- };
570
-
571
- //endregion
572
-
573
- //region Options
574
-
575
- /* Every input option is tested and parsed. This'll prevent
576
- endless validation in internal methods. These tests are
577
- structured with an item for every option available. An
578
- option can be marked as required by setting the 'r' flag.
579
- The testing function is provided with three arguments:
580
- - The provided value for the option;
581
- - A reference to the options object;
582
- - The name for the option;
583
-
584
- The testing function returns false when an error is detected,
585
- or true when everything is OK. It can also modify the option
586
- object, to make sure all values can be correctly looped elsewhere. */
587
-
588
- //region Defaults
589
-
590
- var defaultFormatter = {
591
- to: function(value) {
592
- return value !== undefined && value.toFixed(2);
593
- },
594
- from: Number
595
- };
596
-
597
- var cssClasses = {
598
- target: "target",
599
- base: "base",
600
- origin: "origin",
601
- handle: "handle",
602
- handleLower: "handle-lower",
603
- handleUpper: "handle-upper",
604
- touchArea: "touch-area",
605
- horizontal: "horizontal",
606
- vertical: "vertical",
607
- background: "background",
608
- connect: "connect",
609
- connects: "connects",
610
- ltr: "ltr",
611
- rtl: "rtl",
612
- textDirectionLtr: "txt-dir-ltr",
613
- textDirectionRtl: "txt-dir-rtl",
614
- draggable: "draggable",
615
- drag: "state-drag",
616
- tap: "state-tap",
617
- active: "active",
618
- tooltip: "tooltip",
619
- pips: "pips",
620
- pipsHorizontal: "pips-horizontal",
621
- pipsVertical: "pips-vertical",
622
- marker: "marker",
623
- markerHorizontal: "marker-horizontal",
624
- markerVertical: "marker-vertical",
625
- markerNormal: "marker-normal",
626
- markerLarge: "marker-large",
627
- markerSub: "marker-sub",
628
- value: "value",
629
- valueHorizontal: "value-horizontal",
630
- valueVertical: "value-vertical",
631
- valueNormal: "value-normal",
632
- valueLarge: "value-large",
633
- valueSub: "value-sub"
634
- };
635
-
636
- //endregion
637
-
638
- function validateFormat(entry) {
639
- // Any object with a to and from method is supported.
640
- if (isValidFormatter(entry)) {
641
- return true;
642
- }
643
-
644
- throw new Error("noUiSlider (" + VERSION + "): 'format' requires 'to' and 'from' methods.");
645
- }
646
-
647
- function testStep(parsed, entry) {
648
- if (!isNumeric(entry)) {
649
- throw new Error("noUiSlider (" + VERSION + "): 'step' is not numeric.");
650
- }
651
-
652
- // The step option can still be used to set stepping
653
- // for linear sliders. Overwritten if set in 'range'.
654
- parsed.singleStep = entry;
655
- }
656
-
657
- function testRange(parsed, entry) {
658
- // Filter incorrect input.
659
- if (typeof entry !== "object" || Array.isArray(entry)) {
660
- throw new Error("noUiSlider (" + VERSION + "): 'range' is not an object.");
661
- }
662
-
663
- // Catch missing start or end.
664
- if (entry.min === undefined || entry.max === undefined) {
665
- throw new Error("noUiSlider (" + VERSION + "): Missing 'min' or 'max' in 'range'.");
666
- }
667
-
668
- // Catch equal start or end.
669
- if (entry.min === entry.max) {
670
- throw new Error("noUiSlider (" + VERSION + "): 'range' 'min' and 'max' cannot be equal.");
671
- }
672
-
673
- parsed.spectrum = new Spectrum(entry, parsed.snap, parsed.singleStep);
674
- }
675
-
676
- function testStart(parsed, entry) {
677
- entry = asArray(entry);
678
-
679
- // Validate input. Values aren't tested, as the public .val method
680
- // will always provide a valid location.
681
- if (!Array.isArray(entry) || !entry.length) {
682
- throw new Error("noUiSlider (" + VERSION + "): 'start' option is incorrect.");
683
- }
684
-
685
- // Store the number of handles.
686
- parsed.handles = entry.length;
687
-
688
- // When the slider is initialized, the .val method will
689
- // be called with the start options.
690
- parsed.start = entry;
691
- }
692
-
693
- function testSnap(parsed, entry) {
694
- // Enforce 100% stepping within subranges.
695
- parsed.snap = entry;
696
-
697
- if (typeof entry !== "boolean") {
698
- throw new Error("noUiSlider (" + VERSION + "): 'snap' option must be a boolean.");
699
- }
700
- }
701
-
702
- function testAnimate(parsed, entry) {
703
- // Enforce 100% stepping within subranges.
704
- parsed.animate = entry;
705
-
706
- if (typeof entry !== "boolean") {
707
- throw new Error("noUiSlider (" + VERSION + "): 'animate' option must be a boolean.");
708
- }
709
- }
710
-
711
- function testAnimationDuration(parsed, entry) {
712
- parsed.animationDuration = entry;
713
-
714
- if (typeof entry !== "number") {
715
- throw new Error("noUiSlider (" + VERSION + "): 'animationDuration' option must be a number.");
716
- }
717
- }
718
-
719
- function testConnect(parsed, entry) {
720
- var connect = [false];
721
- var i;
722
-
723
- // Map legacy options
724
- if (entry === "lower") {
725
- entry = [true, false];
726
- } else if (entry === "upper") {
727
- entry = [false, true];
728
- }
729
-
730
- // Handle boolean options
731
- if (entry === true || entry === false) {
732
- for (i = 1; i < parsed.handles; i++) {
733
- connect.push(entry);
734
- }
735
-
736
- connect.push(false);
737
- }
738
-
739
- // Reject invalid input
740
- else if (!Array.isArray(entry) || !entry.length || entry.length !== parsed.handles + 1) {
741
- throw new Error("noUiSlider (" + VERSION + "): 'connect' option doesn't match handle count.");
742
- } else {
743
- connect = entry;
744
- }
745
-
746
- parsed.connect = connect;
747
- }
748
-
749
- function testOrientation(parsed, entry) {
750
- // Set orientation to an a numerical value for easy
751
- // array selection.
752
- switch (entry) {
753
- case "horizontal":
754
- parsed.ort = 0;
755
- break;
756
- case "vertical":
757
- parsed.ort = 1;
758
- break;
759
- default:
760
- throw new Error("noUiSlider (" + VERSION + "): 'orientation' option is invalid.");
761
- }
762
- }
763
-
764
- function testMargin(parsed, entry) {
765
- if (!isNumeric(entry)) {
766
- throw new Error("noUiSlider (" + VERSION + "): 'margin' option must be numeric.");
767
- }
768
-
769
- // Issue #582
770
- if (entry === 0) {
771
- return;
772
- }
773
-
774
- parsed.margin = parsed.spectrum.getDistance(entry);
775
- }
776
-
777
- function testLimit(parsed, entry) {
778
- if (!isNumeric(entry)) {
779
- throw new Error("noUiSlider (" + VERSION + "): 'limit' option must be numeric.");
780
- }
781
-
782
- parsed.limit = parsed.spectrum.getDistance(entry);
783
-
784
- if (!parsed.limit || parsed.handles < 2) {
785
- throw new Error(
786
- "noUiSlider (" +
787
- VERSION +
788
- "): 'limit' option is only supported on linear sliders with 2 or more handles."
789
- );
790
- }
791
- }
792
-
793
- function testPadding(parsed, entry) {
794
- var index;
795
-
796
- if (!isNumeric(entry) && !Array.isArray(entry)) {
797
- throw new Error(
798
- "noUiSlider (" + VERSION + "): 'padding' option must be numeric or array of exactly 2 numbers."
799
- );
800
- }
801
-
802
- if (Array.isArray(entry) && !(entry.length === 2 || isNumeric(entry[0]) || isNumeric(entry[1]))) {
803
- throw new Error(
804
- "noUiSlider (" + VERSION + "): 'padding' option must be numeric or array of exactly 2 numbers."
805
- );
806
- }
807
-
808
- if (entry === 0) {
809
- return;
810
- }
811
-
812
- if (!Array.isArray(entry)) {
813
- entry = [entry, entry];
814
- }
815
-
816
- // 'getDistance' returns false for invalid values.
817
- parsed.padding = [parsed.spectrum.getDistance(entry[0]), parsed.spectrum.getDistance(entry[1])];
818
-
819
- for (index = 0; index < parsed.spectrum.xNumSteps.length - 1; index++) {
820
- // last "range" can't contain step size as it is purely an endpoint.
821
- if (parsed.padding[0][index] < 0 || parsed.padding[1][index] < 0) {
822
- throw new Error("noUiSlider (" + VERSION + "): 'padding' option must be a positive number(s).");
823
- }
824
- }
825
-
826
- var totalPadding = entry[0] + entry[1];
827
- var firstValue = parsed.spectrum.xVal[0];
828
- var lastValue = parsed.spectrum.xVal[parsed.spectrum.xVal.length - 1];
829
-
830
- if (totalPadding / (lastValue - firstValue) > 1) {
831
- throw new Error("noUiSlider (" + VERSION + "): 'padding' option must not exceed 100% of the range.");
832
- }
833
- }
834
-
835
- function testDirection(parsed, entry) {
836
- // Set direction as a numerical value for easy parsing.
837
- // Invert connection for RTL sliders, so that the proper
838
- // handles get the connect/background classes.
839
- switch (entry) {
840
- case "ltr":
841
- parsed.dir = 0;
842
- break;
843
- case "rtl":
844
- parsed.dir = 1;
845
- break;
846
- default:
847
- throw new Error("noUiSlider (" + VERSION + "): 'direction' option was not recognized.");
848
- }
849
- }
850
-
851
- function testBehaviour(parsed, entry) {
852
- // Make sure the input is a string.
853
- if (typeof entry !== "string") {
854
- throw new Error("noUiSlider (" + VERSION + "): 'behaviour' must be a string containing options.");
855
- }
856
-
857
- // Check if the string contains any keywords.
858
- // None are required.
859
- var tap = entry.indexOf("tap") >= 0;
860
- var drag = entry.indexOf("drag") >= 0;
861
- var fixed = entry.indexOf("fixed") >= 0;
862
- var snap = entry.indexOf("snap") >= 0;
863
- var hover = entry.indexOf("hover") >= 0;
864
- var unconstrained = entry.indexOf("unconstrained") >= 0;
865
-
866
- if (fixed) {
867
- if (parsed.handles !== 2) {
868
- throw new Error("noUiSlider (" + VERSION + "): 'fixed' behaviour must be used with 2 handles");
869
- }
870
-
871
- // Use margin to enforce fixed state
872
- testMargin(parsed, parsed.start[1] - parsed.start[0]);
873
- }
874
-
875
- if (unconstrained && (parsed.margin || parsed.limit)) {
876
- throw new Error(
877
- "noUiSlider (" + VERSION + "): 'unconstrained' behaviour cannot be used with margin or limit"
878
- );
879
- }
880
-
881
- parsed.events = {
882
- tap: tap || snap,
883
- drag: drag,
884
- fixed: fixed,
885
- snap: snap,
886
- hover: hover,
887
- unconstrained: unconstrained
888
- };
889
- }
890
-
891
- function testTooltips(parsed, entry) {
892
- if (entry === false) {
893
- return;
894
- }
895
-
896
- if (entry === true) {
897
- parsed.tooltips = [];
898
-
899
- for (var i = 0; i < parsed.handles; i++) {
900
- parsed.tooltips.push(true);
901
- }
902
- } else {
903
- parsed.tooltips = asArray(entry);
904
-
905
- if (parsed.tooltips.length !== parsed.handles) {
906
- throw new Error("noUiSlider (" + VERSION + "): must pass a formatter for all handles.");
907
- }
908
-
909
- parsed.tooltips.forEach(function(formatter) {
910
- if (
911
- typeof formatter !== "boolean" &&
912
- (typeof formatter !== "object" || typeof formatter.to !== "function")
913
- ) {
914
- throw new Error("noUiSlider (" + VERSION + "): 'tooltips' must be passed a formatter or 'false'.");
915
- }
916
- });
917
- }
918
- }
919
-
920
- function testAriaFormat(parsed, entry) {
921
- parsed.ariaFormat = entry;
922
- validateFormat(entry);
923
- }
924
-
925
- function testFormat(parsed, entry) {
926
- parsed.format = entry;
927
- validateFormat(entry);
928
- }
929
-
930
- function testKeyboardSupport(parsed, entry) {
931
- parsed.keyboardSupport = entry;
932
-
933
- if (typeof entry !== "boolean") {
934
- throw new Error("noUiSlider (" + VERSION + "): 'keyboardSupport' option must be a boolean.");
935
- }
936
- }
937
-
938
- function testDocumentElement(parsed, entry) {
939
- // This is an advanced option. Passed values are used without validation.
940
- parsed.documentElement = entry;
941
- }
942
-
943
- function testCssPrefix(parsed, entry) {
944
- if (typeof entry !== "string" && entry !== false) {
945
- throw new Error("noUiSlider (" + VERSION + "): 'cssPrefix' must be a string or `false`.");
946
- }
947
-
948
- parsed.cssPrefix = entry;
949
- }
950
-
951
- function testCssClasses(parsed, entry) {
952
- if (typeof entry !== "object") {
953
- throw new Error("noUiSlider (" + VERSION + "): 'cssClasses' must be an object.");
954
- }
955
-
956
- if (typeof parsed.cssPrefix === "string") {
957
- parsed.cssClasses = {};
958
-
959
- for (var key in entry) {
960
- if (!entry.hasOwnProperty(key)) {
961
- continue;
962
- }
963
-
964
- parsed.cssClasses[key] = parsed.cssPrefix + entry[key];
965
- }
966
- } else {
967
- parsed.cssClasses = entry;
968
- }
969
- }
970
-
971
- // Test all developer settings and parse to assumption-safe values.
972
- function testOptions(options) {
973
- // To prove a fix for #537, freeze options here.
974
- // If the object is modified, an error will be thrown.
975
- // Object.freeze(options);
976
-
977
- var parsed = {
978
- margin: 0,
979
- limit: 0,
980
- padding: 0,
981
- animate: true,
982
- animationDuration: 300,
983
- ariaFormat: defaultFormatter,
984
- format: defaultFormatter
985
- };
986
-
987
- // Tests are executed in the order they are presented here.
988
- var tests = {
989
- step: { r: false, t: testStep },
990
- start: { r: true, t: testStart },
991
- connect: { r: true, t: testConnect },
992
- direction: { r: true, t: testDirection },
993
- snap: { r: false, t: testSnap },
994
- animate: { r: false, t: testAnimate },
995
- animationDuration: { r: false, t: testAnimationDuration },
996
- range: { r: true, t: testRange },
997
- orientation: { r: false, t: testOrientation },
998
- margin: { r: false, t: testMargin },
999
- limit: { r: false, t: testLimit },
1000
- padding: { r: false, t: testPadding },
1001
- behaviour: { r: true, t: testBehaviour },
1002
- ariaFormat: { r: false, t: testAriaFormat },
1003
- format: { r: false, t: testFormat },
1004
- tooltips: { r: false, t: testTooltips },
1005
- keyboardSupport: { r: true, t: testKeyboardSupport },
1006
- documentElement: { r: false, t: testDocumentElement },
1007
- cssPrefix: { r: true, t: testCssPrefix },
1008
- cssClasses: { r: true, t: testCssClasses }
1009
- };
1010
-
1011
- var defaults = {
1012
- connect: false,
1013
- direction: "ltr",
1014
- behaviour: "tap",
1015
- orientation: "horizontal",
1016
- keyboardSupport: true,
1017
- cssPrefix: "noUi-",
1018
- cssClasses: cssClasses
1019
- };
1020
-
1021
- // AriaFormat defaults to regular format, if any.
1022
- if (options.format && !options.ariaFormat) {
1023
- options.ariaFormat = options.format;
1024
- }
1025
-
1026
- // Run all options through a testing mechanism to ensure correct
1027
- // input. It should be noted that options might get modified to
1028
- // be handled properly. E.g. wrapping integers in arrays.
1029
- Object.keys(tests).forEach(function(name) {
1030
- // If the option isn't set, but it is required, throw an error.
1031
- if (!isSet(options[name]) && defaults[name] === undefined) {
1032
- if (tests[name].r) {
1033
- throw new Error("noUiSlider (" + VERSION + "): '" + name + "' is required.");
1034
- }
1035
-
1036
- return true;
1037
- }
1038
-
1039
- tests[name].t(parsed, !isSet(options[name]) ? defaults[name] : options[name]);
1040
- });
1041
-
1042
- // Forward pips options
1043
- parsed.pips = options.pips;
1044
-
1045
- // All recent browsers accept unprefixed transform.
1046
- // We need -ms- for IE9 and -webkit- for older Android;
1047
- // Assume use of -webkit- if unprefixed and -ms- are not supported.
1048
- // https://caniuse.com/#feat=transforms2d
1049
- var d = document.createElement("div");
1050
- var msPrefix = d.style.msTransform !== undefined;
1051
- var noPrefix = d.style.transform !== undefined;
1052
-
1053
- parsed.transformRule = noPrefix ? "transform" : msPrefix ? "msTransform" : "webkitTransform";
1054
-
1055
- // Pips don't move, so we can place them using left/top.
1056
- var styles = [["left", "top"], ["right", "bottom"]];
1057
-
1058
- parsed.style = styles[parsed.dir][parsed.ort];
1059
-
1060
- return parsed;
1061
- }
1062
-
1063
- //endregion
1064
-
1065
- function scope(target, options, originalOptions) {
1066
- var actions = getActions();
1067
- var supportsTouchActionNone = getSupportsTouchActionNone();
1068
- var supportsPassive = supportsTouchActionNone && getSupportsPassive();
1069
-
1070
- // All variables local to 'scope' are prefixed with 'scope_'
1071
-
1072
- // Slider DOM Nodes
1073
- var scope_Target = target;
1074
- var scope_Base;
1075
- var scope_Handles;
1076
- var scope_Connects;
1077
- var scope_Pips;
1078
- var scope_Tooltips;
1079
-
1080
- // Slider state values
1081
- var scope_Spectrum = options.spectrum;
1082
- var scope_Values = [];
1083
- var scope_Locations = [];
1084
- var scope_HandleNumbers = [];
1085
- var scope_ActiveHandlesCount = 0;
1086
- var scope_Events = {};
1087
-
1088
- // Exposed API
1089
- var scope_Self;
1090
-
1091
- // Document Nodes
1092
- var scope_Document = target.ownerDocument;
1093
- var scope_DocumentElement = options.documentElement || scope_Document.documentElement;
1094
- var scope_Body = scope_Document.body;
1095
-
1096
- // Pips constants
1097
- var PIPS_NONE = -1;
1098
- var PIPS_NO_VALUE = 0;
1099
- var PIPS_LARGE_VALUE = 1;
1100
- var PIPS_SMALL_VALUE = 2;
1101
-
1102
- // For horizontal sliders in standard ltr documents,
1103
- // make .noUi-origin overflow to the left so the document doesn't scroll.
1104
- var scope_DirOffset = scope_Document.dir === "rtl" || options.ort === 1 ? 0 : 100;
1105
-
1106
- // Creates a node, adds it to target, returns the new node.
1107
- function addNodeTo(addTarget, className) {
1108
- var div = scope_Document.createElement("div");
1109
-
1110
- if (className) {
1111
- addClass(div, className);
1112
- }
1113
-
1114
- addTarget.appendChild(div);
1115
-
1116
- return div;
1117
- }
1118
-
1119
- // Append a origin to the base
1120
- function addOrigin(base, handleNumber) {
1121
- var origin = addNodeTo(base, options.cssClasses.origin);
1122
- var handle = addNodeTo(origin, options.cssClasses.handle);
1123
-
1124
- addNodeTo(handle, options.cssClasses.touchArea);
1125
-
1126
- handle.setAttribute("data-handle", handleNumber);
1127
-
1128
- if (options.keyboardSupport) {
1129
- // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
1130
- // 0 = focusable and reachable
1131
- handle.setAttribute("tabindex", "0");
1132
- handle.addEventListener("keydown", function(event) {
1133
- return eventKeydown(event, handleNumber);
1134
- });
1135
- }
1136
-
1137
- handle.setAttribute("role", "slider");
1138
- handle.setAttribute("aria-orientation", options.ort ? "vertical" : "horizontal");
1139
-
1140
- if (handleNumber === 0) {
1141
- addClass(handle, options.cssClasses.handleLower);
1142
- } else if (handleNumber === options.handles - 1) {
1143
- addClass(handle, options.cssClasses.handleUpper);
1144
- }
1145
-
1146
- return origin;
1147
- }
1148
-
1149
- // Insert nodes for connect elements
1150
- function addConnect(base, add) {
1151
- if (!add) {
1152
- return false;
1153
- }
1154
-
1155
- return addNodeTo(base, options.cssClasses.connect);
1156
- }
1157
-
1158
- // Add handles to the slider base.
1159
- function addElements(connectOptions, base) {
1160
- var connectBase = addNodeTo(base, options.cssClasses.connects);
1161
-
1162
- scope_Handles = [];
1163
- scope_Connects = [];
1164
-
1165
- scope_Connects.push(addConnect(connectBase, connectOptions[0]));
1166
-
1167
- // [::::O====O====O====]
1168
- // connectOptions = [0, 1, 1, 1]
1169
-
1170
- for (var i = 0; i < options.handles; i++) {
1171
- // Keep a list of all added handles.
1172
- scope_Handles.push(addOrigin(base, i));
1173
- scope_HandleNumbers[i] = i;
1174
- scope_Connects.push(addConnect(connectBase, connectOptions[i + 1]));
1175
- }
1176
- }
1177
-
1178
- // Initialize a single slider.
1179
- function addSlider(addTarget) {
1180
- // Apply classes and data to the target.
1181
- addClass(addTarget, options.cssClasses.target);
1182
-
1183
- if (options.dir === 0) {
1184
- addClass(addTarget, options.cssClasses.ltr);
1185
- } else {
1186
- addClass(addTarget, options.cssClasses.rtl);
1187
- }
1188
-
1189
- if (options.ort === 0) {
1190
- addClass(addTarget, options.cssClasses.horizontal);
1191
- } else {
1192
- addClass(addTarget, options.cssClasses.vertical);
1193
- }
1194
-
1195
- var textDirection = getComputedStyle(addTarget).direction;
1196
-
1197
- if (textDirection === "rtl") {
1198
- addClass(addTarget, options.cssClasses.textDirectionRtl);
1199
- } else {
1200
- addClass(addTarget, options.cssClasses.textDirectionLtr);
1201
- }
1202
-
1203
- return addNodeTo(addTarget, options.cssClasses.base);
1204
- }
1205
-
1206
- function addTooltip(handle, handleNumber) {
1207
- if (!options.tooltips[handleNumber]) {
1208
- return false;
1209
- }
1210
-
1211
- return addNodeTo(handle.firstChild, options.cssClasses.tooltip);
1212
- }
1213
-
1214
- function isSliderDisabled() {
1215
- return scope_Target.hasAttribute("disabled");
1216
- }
1217
-
1218
- // Disable the slider dragging if any handle is disabled
1219
- function isHandleDisabled(handleNumber) {
1220
- var handleOrigin = scope_Handles[handleNumber];
1221
- return handleOrigin.hasAttribute("disabled");
1222
- }
1223
-
1224
- function removeTooltips() {
1225
- if (scope_Tooltips) {
1226
- removeEvent("update.tooltips");
1227
- scope_Tooltips.forEach(function(tooltip) {
1228
- if (tooltip) {
1229
- removeElement(tooltip);
1230
- }
1231
- });
1232
- scope_Tooltips = null;
1233
- }
1234
- }
1235
-
1236
- // The tooltips option is a shorthand for using the 'update' event.
1237
- function tooltips() {
1238
- removeTooltips();
1239
-
1240
- // Tooltips are added with options.tooltips in original order.
1241
- scope_Tooltips = scope_Handles.map(addTooltip);
1242
-
1243
- bindEvent("update.tooltips", function(values, handleNumber, unencoded) {
1244
- if (!scope_Tooltips[handleNumber]) {
1245
- return;
1246
- }
1247
-
1248
- var formattedValue = values[handleNumber];
1249
-
1250
- if (options.tooltips[handleNumber] !== true) {
1251
- formattedValue = options.tooltips[handleNumber].to(unencoded[handleNumber]);
1252
- }
1253
-
1254
- scope_Tooltips[handleNumber].innerHTML = formattedValue;
1255
- });
1256
- }
1257
-
1258
- function aria() {
1259
- bindEvent("update", function(values, handleNumber, unencoded, tap, positions) {
1260
- // Update Aria Values for all handles, as a change in one changes min and max values for the next.
1261
- scope_HandleNumbers.forEach(function(index) {
1262
- var handle = scope_Handles[index];
1263
-
1264
- var min = checkHandlePosition(scope_Locations, index, 0, true, true, true);
1265
- var max = checkHandlePosition(scope_Locations, index, 100, true, true, true);
1266
-
1267
- var now = positions[index];
1268
-
1269
- // Formatted value for display
1270
- var text = options.ariaFormat.to(unencoded[index]);
1271
-
1272
- // Map to slider range values
1273
- min = scope_Spectrum.fromStepping(min).toFixed(1);
1274
- max = scope_Spectrum.fromStepping(max).toFixed(1);
1275
- now = scope_Spectrum.fromStepping(now).toFixed(1);
1276
-
1277
- handle.children[0].setAttribute("aria-valuemin", min);
1278
- handle.children[0].setAttribute("aria-valuemax", max);
1279
- handle.children[0].setAttribute("aria-valuenow", now);
1280
- handle.children[0].setAttribute("aria-valuetext", text);
1281
- });
1282
- });
1283
- }
1284
-
1285
- function getGroup(mode, values, stepped) {
1286
- // Use the range.
1287
- if (mode === "range" || mode === "steps") {
1288
- return scope_Spectrum.xVal;
1289
- }
1290
-
1291
- if (mode === "count") {
1292
- if (values < 2) {
1293
- throw new Error("noUiSlider (" + VERSION + "): 'values' (>= 2) required for mode 'count'.");
1294
- }
1295
-
1296
- // Divide 0 - 100 in 'count' parts.
1297
- var interval = values - 1;
1298
- var spread = 100 / interval;
1299
-
1300
- values = [];
1301
-
1302
- // List these parts and have them handled as 'positions'.
1303
- while (interval--) {
1304
- values[interval] = interval * spread;
1305
- }
1306
-
1307
- values.push(100);
1308
-
1309
- mode = "positions";
1310
- }
1311
-
1312
- if (mode === "positions") {
1313
- // Map all percentages to on-range values.
1314
- return values.map(function(value) {
1315
- return scope_Spectrum.fromStepping(stepped ? scope_Spectrum.getStep(value) : value);
1316
- });
1317
- }
1318
-
1319
- if (mode === "values") {
1320
- // If the value must be stepped, it needs to be converted to a percentage first.
1321
- if (stepped) {
1322
- return values.map(function(value) {
1323
- // Convert to percentage, apply step, return to value.
1324
- return scope_Spectrum.fromStepping(scope_Spectrum.getStep(scope_Spectrum.toStepping(value)));
1325
- });
1326
- }
1327
-
1328
- // Otherwise, we can simply use the values.
1329
- return values;
1330
- }
1331
- }
1332
-
1333
- function generateSpread(density, mode, group) {
1334
- function safeIncrement(value, increment) {
1335
- // Avoid floating point variance by dropping the smallest decimal places.
1336
- return (value + increment).toFixed(7) / 1;
1337
- }
1338
-
1339
- var indexes = {};
1340
- var firstInRange = scope_Spectrum.xVal[0];
1341
- var lastInRange = scope_Spectrum.xVal[scope_Spectrum.xVal.length - 1];
1342
- var ignoreFirst = false;
1343
- var ignoreLast = false;
1344
- var prevPct = 0;
1345
-
1346
- // Create a copy of the group, sort it and filter away all duplicates.
1347
- group = unique(
1348
- group.slice().sort(function(a, b) {
1349
- return a - b;
1350
- })
1351
- );
1352
-
1353
- // Make sure the range starts with the first element.
1354
- if (group[0] !== firstInRange) {
1355
- group.unshift(firstInRange);
1356
- ignoreFirst = true;
1357
- }
1358
-
1359
- // Likewise for the last one.
1360
- if (group[group.length - 1] !== lastInRange) {
1361
- group.push(lastInRange);
1362
- ignoreLast = true;
1363
- }
1364
-
1365
- group.forEach(function(current, index) {
1366
- // Get the current step and the lower + upper positions.
1367
- var step;
1368
- var i;
1369
- var q;
1370
- var low = current;
1371
- var high = group[index + 1];
1372
- var newPct;
1373
- var pctDifference;
1374
- var pctPos;
1375
- var type;
1376
- var steps;
1377
- var realSteps;
1378
- var stepSize;
1379
- var isSteps = mode === "steps";
1380
-
1381
- // When using 'steps' mode, use the provided steps.
1382
- // Otherwise, we'll step on to the next subrange.
1383
- if (isSteps) {
1384
- step = scope_Spectrum.xNumSteps[index];
1385
- }
1386
-
1387
- // Default to a 'full' step.
1388
- if (!step) {
1389
- step = high - low;
1390
- }
1391
-
1392
- // Low can be 0, so test for false. If high is undefined,
1393
- // we are at the last subrange. Index 0 is already handled.
1394
- if (low === false || high === undefined) {
1395
- return;
1396
- }
1397
-
1398
- // Make sure step isn't 0, which would cause an infinite loop (#654)
1399
- step = Math.max(step, 0.0000001);
1400
-
1401
- // Find all steps in the subrange.
1402
- for (i = low; i <= high; i = safeIncrement(i, step)) {
1403
- // Get the percentage value for the current step,
1404
- // calculate the size for the subrange.
1405
- newPct = scope_Spectrum.toStepping(i);
1406
- pctDifference = newPct - prevPct;
1407
-
1408
- steps = pctDifference / density;
1409
- realSteps = Math.round(steps);
1410
-
1411
- // This ratio represents the amount of percentage-space a point indicates.
1412
- // For a density 1 the points/percentage = 1. For density 2, that percentage needs to be re-divided.
1413
- // Round the percentage offset to an even number, then divide by two
1414
- // to spread the offset on both sides of the range.
1415
- stepSize = pctDifference / realSteps;
1416
-
1417
- // Divide all points evenly, adding the correct number to this subrange.
1418
- // Run up to <= so that 100% gets a point, event if ignoreLast is set.
1419
- for (q = 1; q <= realSteps; q += 1) {
1420
- // The ratio between the rounded value and the actual size might be ~1% off.
1421
- // Correct the percentage offset by the number of points
1422
- // per subrange. density = 1 will result in 100 points on the
1423
- // full range, 2 for 50, 4 for 25, etc.
1424
- pctPos = prevPct + q * stepSize;
1425
- indexes[pctPos.toFixed(5)] = [scope_Spectrum.fromStepping(pctPos), 0];
1426
- }
1427
-
1428
- // Determine the point type.
1429
- type = group.indexOf(i) > -1 ? PIPS_LARGE_VALUE : isSteps ? PIPS_SMALL_VALUE : PIPS_NO_VALUE;
1430
-
1431
- // Enforce the 'ignoreFirst' option by overwriting the type for 0.
1432
- if (!index && ignoreFirst && i !== high) {
1433
- type = 0;
1434
- }
1435
-
1436
- if (!(i === high && ignoreLast)) {
1437
- // Mark the 'type' of this point. 0 = plain, 1 = real value, 2 = step value.
1438
- indexes[newPct.toFixed(5)] = [i, type];
1439
- }
1440
-
1441
- // Update the percentage count.
1442
- prevPct = newPct;
1443
- }
1444
- });
1445
-
1446
- return indexes;
1447
- }
1448
-
1449
- function addMarking(spread, filterFunc, formatter) {
1450
- var element = scope_Document.createElement("div");
1451
-
1452
- var valueSizeClasses = [];
1453
- valueSizeClasses[PIPS_NO_VALUE] = options.cssClasses.valueNormal;
1454
- valueSizeClasses[PIPS_LARGE_VALUE] = options.cssClasses.valueLarge;
1455
- valueSizeClasses[PIPS_SMALL_VALUE] = options.cssClasses.valueSub;
1456
-
1457
- var markerSizeClasses = [];
1458
- markerSizeClasses[PIPS_NO_VALUE] = options.cssClasses.markerNormal;
1459
- markerSizeClasses[PIPS_LARGE_VALUE] = options.cssClasses.markerLarge;
1460
- markerSizeClasses[PIPS_SMALL_VALUE] = options.cssClasses.markerSub;
1461
-
1462
- var valueOrientationClasses = [options.cssClasses.valueHorizontal, options.cssClasses.valueVertical];
1463
- var markerOrientationClasses = [options.cssClasses.markerHorizontal, options.cssClasses.markerVertical];
1464
-
1465
- addClass(element, options.cssClasses.pips);
1466
- addClass(element, options.ort === 0 ? options.cssClasses.pipsHorizontal : options.cssClasses.pipsVertical);
1467
-
1468
- function getClasses(type, source) {
1469
- var a = source === options.cssClasses.value;
1470
- var orientationClasses = a ? valueOrientationClasses : markerOrientationClasses;
1471
- var sizeClasses = a ? valueSizeClasses : markerSizeClasses;
1472
-
1473
- return source + " " + orientationClasses[options.ort] + " " + sizeClasses[type];
1474
- }
1475
-
1476
- function addSpread(offset, value, type) {
1477
- // Apply the filter function, if it is set.
1478
- type = filterFunc ? filterFunc(value, type) : type;
1479
-
1480
- if (type === PIPS_NONE) {
1481
- return;
1482
- }
1483
-
1484
- // Add a marker for every point
1485
- var node = addNodeTo(element, false);
1486
- node.className = getClasses(type, options.cssClasses.marker);
1487
- node.style[options.style] = offset + "%";
1488
-
1489
- // Values are only appended for points marked '1' or '2'.
1490
- if (type > PIPS_NO_VALUE) {
1491
- node = addNodeTo(element, false);
1492
- node.className = getClasses(type, options.cssClasses.value);
1493
- node.setAttribute("data-value", value);
1494
- node.style[options.style] = offset + "%";
1495
- node.innerHTML = formatter.to(value);
1496
- }
1497
- }
1498
-
1499
- // Append all points.
1500
- Object.keys(spread).forEach(function(offset) {
1501
- addSpread(offset, spread[offset][0], spread[offset][1]);
1502
- });
1503
-
1504
- return element;
1505
- }
1506
-
1507
- function removePips() {
1508
- if (scope_Pips) {
1509
- removeElement(scope_Pips);
1510
- scope_Pips = null;
1511
- }
1512
- }
1513
-
1514
- function pips(grid) {
1515
- // Fix #669
1516
- removePips();
1517
-
1518
- var mode = grid.mode;
1519
- var density = grid.density || 1;
1520
- var filter = grid.filter || false;
1521
- var values = grid.values || false;
1522
- var stepped = grid.stepped || false;
1523
- var group = getGroup(mode, values, stepped);
1524
- var spread = generateSpread(density, mode, group);
1525
- var format = grid.format || {
1526
- to: Math.round
1527
- };
1528
-
1529
- scope_Pips = scope_Target.appendChild(addMarking(spread, filter, format));
1530
-
1531
- return scope_Pips;
1532
- }
1533
-
1534
- // Shorthand for base dimensions.
1535
- function baseSize() {
1536
- var rect = scope_Base.getBoundingClientRect();
1537
- var alt = "offset" + ["Width", "Height"][options.ort];
1538
- return options.ort === 0 ? rect.width || scope_Base[alt] : rect.height || scope_Base[alt];
1539
- }
1540
-
1541
- // Handler for attaching events trough a proxy.
1542
- function attachEvent(events, element, callback, data) {
1543
- // This function can be used to 'filter' events to the slider.
1544
- // element is a node, not a nodeList
1545
-
1546
- var method = function(e) {
1547
- e = fixEvent(e, data.pageOffset, data.target || element);
1548
-
1549
- // fixEvent returns false if this event has a different target
1550
- // when handling (multi-) touch events;
1551
- if (!e) {
1552
- return false;
1553
- }
1554
-
1555
- // doNotReject is passed by all end events to make sure released touches
1556
- // are not rejected, leaving the slider "stuck" to the cursor;
1557
- if (isSliderDisabled() && !data.doNotReject) {
1558
- return false;
1559
- }
1560
-
1561
- // Stop if an active 'tap' transition is taking place.
1562
- if (hasClass(scope_Target, options.cssClasses.tap) && !data.doNotReject) {
1563
- return false;
1564
- }
1565
-
1566
- // Ignore right or middle clicks on start #454
1567
- if (events === actions.start && e.buttons !== undefined && e.buttons > 1) {
1568
- return false;
1569
- }
1570
-
1571
- // Ignore right or middle clicks on start #454
1572
- if (data.hover && e.buttons) {
1573
- return false;
1574
- }
1575
-
1576
- // 'supportsPassive' is only true if a browser also supports touch-action: none in CSS.
1577
- // iOS safari does not, so it doesn't get to benefit from passive scrolling. iOS does support
1578
- // touch-action: manipulation, but that allows panning, which breaks
1579
- // sliders after zooming/on non-responsive pages.
1580
- // See: https://bugs.webkit.org/show_bug.cgi?id=133112
1581
- if (!supportsPassive) {
1582
- e.preventDefault();
1583
- }
1584
-
1585
- e.calcPoint = e.points[options.ort];
1586
-
1587
- // Call the event handler with the event [ and additional data ].
1588
- callback(e, data);
1589
- };
1590
-
1591
- var methods = [];
1592
-
1593
- // Bind a closure on the target for every event type.
1594
- events.split(" ").forEach(function(eventName) {
1595
- element.addEventListener(eventName, method, supportsPassive ? { passive: true } : false);
1596
- methods.push([eventName, method]);
1597
- });
1598
-
1599
- return methods;
1600
- }
1601
-
1602
- // Provide a clean event with standardized offset values.
1603
- function fixEvent(e, pageOffset, eventTarget) {
1604
- // Filter the event to register the type, which can be
1605
- // touch, mouse or pointer. Offset changes need to be
1606
- // made on an event specific basis.
1607
- var touch = e.type.indexOf("touch") === 0;
1608
- var mouse = e.type.indexOf("mouse") === 0;
1609
- var pointer = e.type.indexOf("pointer") === 0;
1610
-
1611
- var x;
1612
- var y;
1613
-
1614
- // IE10 implemented pointer events with a prefix;
1615
- if (e.type.indexOf("MSPointer") === 0) {
1616
- pointer = true;
1617
- }
1618
-
1619
- // The only thing one handle should be concerned about is the touches that originated on top of it.
1620
- if (touch) {
1621
- // Returns true if a touch originated on the target.
1622
- var isTouchOnTarget = function(checkTouch) {
1623
- return (
1624
- checkTouch.target === eventTarget ||
1625
- eventTarget.contains(checkTouch.target) ||
1626
- (checkTouch.target.shadowRoot && checkTouch.target.shadowRoot.contains(eventTarget))
1627
- );
1628
- };
1629
-
1630
- // In the case of touchstart events, we need to make sure there is still no more than one
1631
- // touch on the target so we look amongst all touches.
1632
- if (e.type === "touchstart") {
1633
- var targetTouches = Array.prototype.filter.call(e.touches, isTouchOnTarget);
1634
-
1635
- // Do not support more than one touch per handle.
1636
- if (targetTouches.length > 1) {
1637
- return false;
1638
- }
1639
-
1640
- x = targetTouches[0].pageX;
1641
- y = targetTouches[0].pageY;
1642
- } else {
1643
- // In the other cases, find on changedTouches is enough.
1644
- var targetTouch = Array.prototype.find.call(e.changedTouches, isTouchOnTarget);
1645
-
1646
- // Cancel if the target touch has not moved.
1647
- if (!targetTouch) {
1648
- return false;
1649
- }
1650
-
1651
- x = targetTouch.pageX;
1652
- y = targetTouch.pageY;
1653
- }
1654
- }
1655
-
1656
- pageOffset = pageOffset || getPageOffset(scope_Document);
1657
-
1658
- if (mouse || pointer) {
1659
- x = e.clientX + pageOffset.x;
1660
- y = e.clientY + pageOffset.y;
1661
- }
1662
-
1663
- e.pageOffset = pageOffset;
1664
- e.points = [x, y];
1665
- e.cursor = mouse || pointer; // Fix #435
1666
-
1667
- return e;
1668
- }
1669
-
1670
- // Translate a coordinate in the document to a percentage on the slider
1671
- function calcPointToPercentage(calcPoint) {
1672
- var location = calcPoint - offset(scope_Base, options.ort);
1673
- var proposal = (location * 100) / baseSize();
1674
-
1675
- // Clamp proposal between 0% and 100%
1676
- // Out-of-bound coordinates may occur when .noUi-base pseudo-elements
1677
- // are used (e.g. contained handles feature)
1678
- proposal = limit(proposal);
1679
-
1680
- return options.dir ? 100 - proposal : proposal;
1681
- }
1682
-
1683
- // Find handle closest to a certain percentage on the slider
1684
- function getClosestHandle(clickedPosition) {
1685
- var smallestDifference = 100;
1686
- var handleNumber = false;
1687
-
1688
- scope_Handles.forEach(function(handle, index) {
1689
- // Disabled handles are ignored
1690
- if (isHandleDisabled(index)) {
1691
- return;
1692
- }
1693
-
1694
- var handlePosition = scope_Locations[index];
1695
- var differenceWithThisHandle = Math.abs(handlePosition - clickedPosition);
1696
-
1697
- // Initial state
1698
- var clickAtEdge = differenceWithThisHandle === 100 && smallestDifference === 100;
1699
-
1700
- // Difference with this handle is smaller than the previously checked handle
1701
- var isCloser = differenceWithThisHandle < smallestDifference;
1702
- var isCloserAfter = differenceWithThisHandle <= smallestDifference && clickedPosition > handlePosition;
1703
-
1704
- if (isCloser || isCloserAfter || clickAtEdge) {
1705
- handleNumber = index;
1706
- smallestDifference = differenceWithThisHandle;
1707
- }
1708
- });
1709
-
1710
- return handleNumber;
1711
- }
1712
-
1713
- // Fire 'end' when a mouse or pen leaves the document.
1714
- function documentLeave(event, data) {
1715
- if (event.type === "mouseout" && event.target.nodeName === "HTML" && event.relatedTarget === null) {
1716
- eventEnd(event, data);
1717
- }
1718
- }
1719
-
1720
- // Handle movement on document for handle and range drag.
1721
- function eventMove(event, data) {
1722
- // Fix #498
1723
- // Check value of .buttons in 'start' to work around a bug in IE10 mobile (data.buttonsProperty).
1724
- // https://connect.microsoft.com/IE/feedback/details/927005/mobile-ie10-windows-phone-buttons-property-of-pointermove-event-always-zero
1725
- // IE9 has .buttons and .which zero on mousemove.
1726
- // Firefox breaks the spec MDN defines.
1727
- if (navigator.appVersion.indexOf("MSIE 9") === -1 && event.buttons === 0 && data.buttonsProperty !== 0) {
1728
- return eventEnd(event, data);
1729
- }
1730
-
1731
- // Check if we are moving up or down
1732
- var movement = (options.dir ? -1 : 1) * (event.calcPoint - data.startCalcPoint);
1733
-
1734
- // Convert the movement into a percentage of the slider width/height
1735
- var proposal = (movement * 100) / data.baseSize;
1736
-
1737
- moveHandles(movement > 0, proposal, data.locations, data.handleNumbers);
1738
- }
1739
-
1740
- // Unbind move events on document, call callbacks.
1741
- function eventEnd(event, data) {
1742
- // The handle is no longer active, so remove the class.
1743
- if (data.handle) {
1744
- removeClass(data.handle, options.cssClasses.active);
1745
- scope_ActiveHandlesCount -= 1;
1746
- }
1747
-
1748
- // Unbind the move and end events, which are added on 'start'.
1749
- data.listeners.forEach(function(c) {
1750
- scope_DocumentElement.removeEventListener(c[0], c[1]);
1751
- });
1752
-
1753
- if (scope_ActiveHandlesCount === 0) {
1754
- // Remove dragging class.
1755
- removeClass(scope_Target, options.cssClasses.drag);
1756
- setZindex();
1757
-
1758
- // Remove cursor styles and text-selection events bound to the body.
1759
- if (event.cursor) {
1760
- scope_Body.style.cursor = "";
1761
- scope_Body.removeEventListener("selectstart", preventDefault);
1762
- }
1763
- }
1764
-
1765
- data.handleNumbers.forEach(function(handleNumber) {
1766
- fireEvent("change", handleNumber);
1767
- fireEvent("set", handleNumber);
1768
- fireEvent("end", handleNumber);
1769
- });
1770
- }
1771
-
1772
- // Bind move events on document.
1773
- function eventStart(event, data) {
1774
- // Ignore event if any handle is disabled
1775
- if (data.handleNumbers.some(isHandleDisabled)) {
1776
- return false;
1777
- }
1778
-
1779
- var handle;
1780
-
1781
- if (data.handleNumbers.length === 1) {
1782
- var handleOrigin = scope_Handles[data.handleNumbers[0]];
1783
-
1784
- handle = handleOrigin.children[0];
1785
- scope_ActiveHandlesCount += 1;
1786
-
1787
- // Mark the handle as 'active' so it can be styled.
1788
- addClass(handle, options.cssClasses.active);
1789
- }
1790
-
1791
- // A drag should never propagate up to the 'tap' event.
1792
- event.stopPropagation();
1793
-
1794
- // Record the event listeners.
1795
- var listeners = [];
1796
-
1797
- // Attach the move and end events.
1798
- var moveEvent = attachEvent(actions.move, scope_DocumentElement, eventMove, {
1799
- // The event target has changed so we need to propagate the original one so that we keep
1800
- // relying on it to extract target touches.
1801
- target: event.target,
1802
- handle: handle,
1803
- listeners: listeners,
1804
- startCalcPoint: event.calcPoint,
1805
- baseSize: baseSize(),
1806
- pageOffset: event.pageOffset,
1807
- handleNumbers: data.handleNumbers,
1808
- buttonsProperty: event.buttons,
1809
- locations: scope_Locations.slice()
1810
- });
1811
-
1812
- var endEvent = attachEvent(actions.end, scope_DocumentElement, eventEnd, {
1813
- target: event.target,
1814
- handle: handle,
1815
- listeners: listeners,
1816
- doNotReject: true,
1817
- handleNumbers: data.handleNumbers
1818
- });
1819
-
1820
- var outEvent = attachEvent("mouseout", scope_DocumentElement, documentLeave, {
1821
- target: event.target,
1822
- handle: handle,
1823
- listeners: listeners,
1824
- doNotReject: true,
1825
- handleNumbers: data.handleNumbers
1826
- });
1827
-
1828
- // We want to make sure we pushed the listeners in the listener list rather than creating
1829
- // a new one as it has already been passed to the event handlers.
1830
- listeners.push.apply(listeners, moveEvent.concat(endEvent, outEvent));
1831
-
1832
- // Text selection isn't an issue on touch devices,
1833
- // so adding cursor styles can be skipped.
1834
- if (event.cursor) {
1835
- // Prevent the 'I' cursor and extend the range-drag cursor.
1836
- scope_Body.style.cursor = getComputedStyle(event.target).cursor;
1837
-
1838
- // Mark the target with a dragging state.
1839
- if (scope_Handles.length > 1) {
1840
- addClass(scope_Target, options.cssClasses.drag);
1841
- }
1842
-
1843
- // Prevent text selection when dragging the handles.
1844
- // In noUiSlider <= 9.2.0, this was handled by calling preventDefault on mouse/touch start/move,
1845
- // which is scroll blocking. The selectstart event is supported by FireFox starting from version 52,
1846
- // meaning the only holdout is iOS Safari. This doesn't matter: text selection isn't triggered there.
1847
- // The 'cursor' flag is false.
1848
- // See: http://caniuse.com/#search=selectstart
1849
- scope_Body.addEventListener("selectstart", preventDefault, false);
1850
- }
1851
-
1852
- data.handleNumbers.forEach(function(handleNumber) {
1853
- fireEvent("start", handleNumber);
1854
- });
1855
- }
1856
-
1857
- // Move closest handle to tapped location.
1858
- function eventTap(event) {
1859
- // The tap event shouldn't propagate up
1860
- event.stopPropagation();
1861
-
1862
- var proposal = calcPointToPercentage(event.calcPoint);
1863
- var handleNumber = getClosestHandle(proposal);
1864
-
1865
- // Tackle the case that all handles are 'disabled'.
1866
- if (handleNumber === false) {
1867
- return false;
1868
- }
1869
-
1870
- // Flag the slider as it is now in a transitional state.
1871
- // Transition takes a configurable amount of ms (default 300). Re-enable the slider after that.
1872
- if (!options.events.snap) {
1873
- addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration);
1874
- }
1875
-
1876
- setHandle(handleNumber, proposal, true, true);
1877
-
1878
- setZindex();
1879
-
1880
- fireEvent("slide", handleNumber, true);
1881
- fireEvent("update", handleNumber, true);
1882
- fireEvent("change", handleNumber, true);
1883
- fireEvent("set", handleNumber, true);
1884
-
1885
- if (options.events.snap) {
1886
- eventStart(event, { handleNumbers: [handleNumber] });
1887
- }
1888
- }
1889
-
1890
- // Fires a 'hover' event for a hovered mouse/pen position.
1891
- function eventHover(event) {
1892
- var proposal = calcPointToPercentage(event.calcPoint);
1893
-
1894
- var to = scope_Spectrum.getStep(proposal);
1895
- var value = scope_Spectrum.fromStepping(to);
1896
-
1897
- Object.keys(scope_Events).forEach(function(targetEvent) {
1898
- if ("hover" === targetEvent.split(".")[0]) {
1899
- scope_Events[targetEvent].forEach(function(callback) {
1900
- callback.call(scope_Self, value);
1901
- });
1902
- }
1903
- });
1904
- }
1905
-
1906
- // Handles keydown on focused handles
1907
- // Don't move the document when pressing arrow keys on focused handles
1908
- function eventKeydown(event, handleNumber) {
1909
- if (isSliderDisabled() || isHandleDisabled(handleNumber)) {
1910
- return false;
1911
- }
1912
-
1913
- var horizontalKeys = ["Left", "Right"];
1914
- var verticalKeys = ["Down", "Up"];
1915
- var largeStepKeys = ["PageDown", "PageUp"];
1916
- var edgeKeys = ["Home", "End"];
1917
-
1918
- if (options.dir && !options.ort) {
1919
- // On an right-to-left slider, the left and right keys act inverted
1920
- horizontalKeys.reverse();
1921
- } else if (options.ort && !options.dir) {
1922
- // On a top-to-bottom slider, the up and down keys act inverted
1923
- verticalKeys.reverse();
1924
- largeStepKeys.reverse();
1925
- }
1926
-
1927
- // Strip "Arrow" for IE compatibility. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
1928
- var key = event.key.replace("Arrow", "");
1929
-
1930
- var isLargeDown = key === largeStepKeys[0];
1931
- var isLargeUp = key === largeStepKeys[1];
1932
- var isDown = key === verticalKeys[0] || key === horizontalKeys[0] || isLargeDown;
1933
- var isUp = key === verticalKeys[1] || key === horizontalKeys[1] || isLargeUp;
1934
- var isMin = key === edgeKeys[0];
1935
- var isMax = key === edgeKeys[1];
1936
-
1937
- if (!isDown && !isUp && !isMin && !isMax) {
1938
- return true;
1939
- }
1940
-
1941
- event.preventDefault();
1942
-
1943
- var to;
1944
-
1945
- if (isUp || isDown) {
1946
- var multiplier = 5;
1947
- var direction = isDown ? 0 : 1;
1948
- var steps = getNextStepsForHandle(handleNumber);
1949
- var step = steps[direction];
1950
-
1951
- // At the edge of a slider, do nothing
1952
- if (step === null) {
1953
- return false;
1954
- }
1955
-
1956
- // No step set, use the default of 10% of the sub-range
1957
- if (step === false) {
1958
- step = scope_Spectrum.getDefaultStep(scope_Locations[handleNumber], isDown, 10);
1959
- }
1960
-
1961
- if (isLargeUp || isLargeDown) {
1962
- step *= multiplier;
1963
- }
1964
-
1965
- // Step over zero-length ranges (#948);
1966
- step = Math.max(step, 0.0000001);
1967
-
1968
- // Decrement for down steps
1969
- step = (isDown ? -1 : 1) * step;
1970
-
1971
- to = scope_Values[handleNumber] + step;
1972
- } else if (isMax) {
1973
- // End key
1974
- to = options.spectrum.xVal[options.spectrum.xVal.length - 1];
1975
- } else {
1976
- // Home key
1977
- to = options.spectrum.xVal[0];
1978
- }
1979
-
1980
- setHandle(handleNumber, scope_Spectrum.toStepping(to), true, true);
1981
-
1982
- fireEvent("slide", handleNumber);
1983
- fireEvent("update", handleNumber);
1984
- fireEvent("change", handleNumber);
1985
- fireEvent("set", handleNumber);
1986
-
1987
- return false;
1988
- }
1989
-
1990
- // Attach events to several slider parts.
1991
- function bindSliderEvents(behaviour) {
1992
- // Attach the standard drag event to the handles.
1993
- if (!behaviour.fixed) {
1994
- scope_Handles.forEach(function(handle, index) {
1995
- // These events are only bound to the visual handle
1996
- // element, not the 'real' origin element.
1997
- attachEvent(actions.start, handle.children[0], eventStart, {
1998
- handleNumbers: [index]
1999
- });
2000
- });
2001
- }
2002
-
2003
- // Attach the tap event to the slider base.
2004
- if (behaviour.tap) {
2005
- attachEvent(actions.start, scope_Base, eventTap, {});
2006
- }
2007
-
2008
- // Fire hover events
2009
- if (behaviour.hover) {
2010
- attachEvent(actions.move, scope_Base, eventHover, {
2011
- hover: true
2012
- });
2013
- }
2014
-
2015
- // Make the range draggable.
2016
- if (behaviour.drag) {
2017
- scope_Connects.forEach(function(connect, index) {
2018
- if (connect === false || index === 0 || index === scope_Connects.length - 1) {
2019
- return;
2020
- }
2021
-
2022
- var handleBefore = scope_Handles[index - 1];
2023
- var handleAfter = scope_Handles[index];
2024
- var eventHolders = [connect];
2025
-
2026
- addClass(connect, options.cssClasses.draggable);
2027
-
2028
- // When the range is fixed, the entire range can
2029
- // be dragged by the handles. The handle in the first
2030
- // origin will propagate the start event upward,
2031
- // but it needs to be bound manually on the other.
2032
- if (behaviour.fixed) {
2033
- eventHolders.push(handleBefore.children[0]);
2034
- eventHolders.push(handleAfter.children[0]);
2035
- }
2036
-
2037
- eventHolders.forEach(function(eventHolder) {
2038
- attachEvent(actions.start, eventHolder, eventStart, {
2039
- handles: [handleBefore, handleAfter],
2040
- handleNumbers: [index - 1, index]
2041
- });
2042
- });
2043
- });
2044
- }
2045
- }
2046
-
2047
- // Attach an event to this slider, possibly including a namespace
2048
- function bindEvent(namespacedEvent, callback) {
2049
- scope_Events[namespacedEvent] = scope_Events[namespacedEvent] || [];
2050
- scope_Events[namespacedEvent].push(callback);
2051
-
2052
- // If the event bound is 'update,' fire it immediately for all handles.
2053
- if (namespacedEvent.split(".")[0] === "update") {
2054
- scope_Handles.forEach(function(a, index) {
2055
- fireEvent("update", index);
2056
- });
2057
- }
2058
- }
2059
-
2060
- // Undo attachment of event
2061
- function removeEvent(namespacedEvent) {
2062
- var event = namespacedEvent && namespacedEvent.split(".")[0];
2063
- var namespace = event && namespacedEvent.substring(event.length);
2064
-
2065
- Object.keys(scope_Events).forEach(function(bind) {
2066
- var tEvent = bind.split(".")[0];
2067
- var tNamespace = bind.substring(tEvent.length);
2068
-
2069
- if ((!event || event === tEvent) && (!namespace || namespace === tNamespace)) {
2070
- delete scope_Events[bind];
2071
- }
2072
- });
2073
- }
2074
-
2075
- // External event handling
2076
- function fireEvent(eventName, handleNumber, tap) {
2077
- Object.keys(scope_Events).forEach(function(targetEvent) {
2078
- var eventType = targetEvent.split(".")[0];
2079
-
2080
- if (eventName === eventType) {
2081
- scope_Events[targetEvent].forEach(function(callback) {
2082
- callback.call(
2083
- // Use the slider public API as the scope ('this')
2084
- scope_Self,
2085
- // Return values as array, so arg_1[arg_2] is always valid.
2086
- scope_Values.map(options.format.to),
2087
- // Handle index, 0 or 1
2088
- handleNumber,
2089
- // Un-formatted slider values
2090
- scope_Values.slice(),
2091
- // Event is fired by tap, true or false
2092
- tap || false,
2093
- // Left offset of the handle, in relation to the slider
2094
- scope_Locations.slice(),
2095
- // add the slider public API to an accessible parameter when this is unavailable
2096
- scope_Self
2097
- );
2098
- });
2099
- }
2100
- });
2101
- }
2102
-
2103
- // Split out the handle positioning logic so the Move event can use it, too
2104
- function checkHandlePosition(reference, handleNumber, to, lookBackward, lookForward, getValue) {
2105
- var distance;
2106
-
2107
- // For sliders with multiple handles, limit movement to the other handle.
2108
- // Apply the margin option by adding it to the handle positions.
2109
- if (scope_Handles.length > 1 && !options.events.unconstrained) {
2110
- if (lookBackward && handleNumber > 0) {
2111
- distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber - 1], options.margin, 0);
2112
- to = Math.max(to, distance);
2113
- }
2114
-
2115
- if (lookForward && handleNumber < scope_Handles.length - 1) {
2116
- distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber + 1], options.margin, 1);
2117
- to = Math.min(to, distance);
2118
- }
2119
- }
2120
-
2121
- // The limit option has the opposite effect, limiting handles to a
2122
- // maximum distance from another. Limit must be > 0, as otherwise
2123
- // handles would be unmovable.
2124
- if (scope_Handles.length > 1 && options.limit) {
2125
- if (lookBackward && handleNumber > 0) {
2126
- distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber - 1], options.limit, 0);
2127
- to = Math.min(to, distance);
2128
- }
2129
-
2130
- if (lookForward && handleNumber < scope_Handles.length - 1) {
2131
- distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber + 1], options.limit, 1);
2132
- to = Math.max(to, distance);
2133
- }
2134
- }
2135
-
2136
- // The padding option keeps the handles a certain distance from the
2137
- // edges of the slider. Padding must be > 0.
2138
- if (options.padding) {
2139
- if (handleNumber === 0) {
2140
- distance = scope_Spectrum.getAbsoluteDistance(0, options.padding[0], 0);
2141
- to = Math.max(to, distance);
2142
- }
2143
-
2144
- if (handleNumber === scope_Handles.length - 1) {
2145
- distance = scope_Spectrum.getAbsoluteDistance(100, options.padding[1], 1);
2146
- to = Math.min(to, distance);
2147
- }
2148
- }
2149
-
2150
- to = scope_Spectrum.getStep(to);
2151
-
2152
- // Limit percentage to the 0 - 100 range
2153
- to = limit(to);
2154
-
2155
- // Return false if handle can't move
2156
- if (to === reference[handleNumber] && !getValue) {
2157
- return false;
2158
- }
2159
-
2160
- return to;
2161
- }
2162
-
2163
- // Uses slider orientation to create CSS rules. a = base value;
2164
- function inRuleOrder(v, a) {
2165
- var o = options.ort;
2166
- return (o ? a : v) + ", " + (o ? v : a);
2167
- }
2168
-
2169
- // Moves handle(s) by a percentage
2170
- // (bool, % to move, [% where handle started, ...], [index in scope_Handles, ...])
2171
- function moveHandles(upward, proposal, locations, handleNumbers) {
2172
- var proposals = locations.slice();
2173
-
2174
- var b = [!upward, upward];
2175
- var f = [upward, !upward];
2176
-
2177
- // Copy handleNumbers so we don't change the dataset
2178
- handleNumbers = handleNumbers.slice();
2179
-
2180
- // Check to see which handle is 'leading'.
2181
- // If that one can't move the second can't either.
2182
- if (upward) {
2183
- handleNumbers.reverse();
2184
- }
2185
-
2186
- // Step 1: get the maximum percentage that any of the handles can move
2187
- if (handleNumbers.length > 1) {
2188
- handleNumbers.forEach(function(handleNumber, o) {
2189
- var to = checkHandlePosition(
2190
- proposals,
2191
- handleNumber,
2192
- proposals[handleNumber] + proposal,
2193
- b[o],
2194
- f[o],
2195
- false
2196
- );
2197
-
2198
- // Stop if one of the handles can't move.
2199
- if (to === false) {
2200
- proposal = 0;
2201
- } else {
2202
- proposal = to - proposals[handleNumber];
2203
- proposals[handleNumber] = to;
2204
- }
2205
- });
2206
- }
2207
-
2208
- // If using one handle, check backward AND forward
2209
- else {
2210
- b = f = [true];
2211
- }
2212
-
2213
- var state = false;
2214
-
2215
- // Step 2: Try to set the handles with the found percentage
2216
- handleNumbers.forEach(function(handleNumber, o) {
2217
- state = setHandle(handleNumber, locations[handleNumber] + proposal, b[o], f[o]) || state;
2218
- });
2219
-
2220
- // Step 3: If a handle moved, fire events
2221
- if (state) {
2222
- handleNumbers.forEach(function(handleNumber) {
2223
- fireEvent("update", handleNumber);
2224
- fireEvent("slide", handleNumber);
2225
- });
2226
- }
2227
- }
2228
-
2229
- // Takes a base value and an offset. This offset is used for the connect bar size.
2230
- // In the initial design for this feature, the origin element was 1% wide.
2231
- // Unfortunately, a rounding bug in Chrome makes it impossible to implement this feature
2232
- // in this manner: https://bugs.chromium.org/p/chromium/issues/detail?id=798223
2233
- function transformDirection(a, b) {
2234
- return options.dir ? 100 - a - b : a;
2235
- }
2236
-
2237
- // Updates scope_Locations and scope_Values, updates visual state
2238
- function updateHandlePosition(handleNumber, to) {
2239
- // Update locations.
2240
- scope_Locations[handleNumber] = to;
2241
-
2242
- // Convert the value to the slider stepping/range.
2243
- scope_Values[handleNumber] = scope_Spectrum.fromStepping(to);
2244
-
2245
- var translation = 10 * (transformDirection(to, 0) - scope_DirOffset);
2246
- var translateRule = "translate(" + inRuleOrder(translation + "%", "0") + ")";
2247
-
2248
- scope_Handles[handleNumber].style[options.transformRule] = translateRule;
2249
-
2250
- updateConnect(handleNumber);
2251
- updateConnect(handleNumber + 1);
2252
- }
2253
-
2254
- // Handles before the slider middle are stacked later = higher,
2255
- // Handles after the middle later is lower
2256
- // [[7] [8] .......... | .......... [5] [4]
2257
- function setZindex() {
2258
- scope_HandleNumbers.forEach(function(handleNumber) {
2259
- var dir = scope_Locations[handleNumber] > 50 ? -1 : 1;
2260
- var zIndex = 3 + (scope_Handles.length + dir * handleNumber);
2261
- scope_Handles[handleNumber].style.zIndex = zIndex;
2262
- });
2263
- }
2264
-
2265
- // Test suggested values and apply margin, step.
2266
- function setHandle(handleNumber, to, lookBackward, lookForward) {
2267
- to = checkHandlePosition(scope_Locations, handleNumber, to, lookBackward, lookForward, false);
2268
-
2269
- if (to === false) {
2270
- return false;
2271
- }
2272
-
2273
- updateHandlePosition(handleNumber, to);
2274
-
2275
- return true;
2276
- }
2277
-
2278
- // Updates style attribute for connect nodes
2279
- function updateConnect(index) {
2280
- // Skip connects set to false
2281
- if (!scope_Connects[index]) {
2282
- return;
2283
- }
2284
-
2285
- var l = 0;
2286
- var h = 100;
2287
-
2288
- if (index !== 0) {
2289
- l = scope_Locations[index - 1];
2290
- }
2291
-
2292
- if (index !== scope_Connects.length - 1) {
2293
- h = scope_Locations[index];
2294
- }
2295
-
2296
- // We use two rules:
2297
- // 'translate' to change the left/top offset;
2298
- // 'scale' to change the width of the element;
2299
- // As the element has a width of 100%, a translation of 100% is equal to 100% of the parent (.noUi-base)
2300
- var connectWidth = h - l;
2301
- var translateRule = "translate(" + inRuleOrder(transformDirection(l, connectWidth) + "%", "0") + ")";
2302
- var scaleRule = "scale(" + inRuleOrder(connectWidth / 100, "1") + ")";
2303
-
2304
- scope_Connects[index].style[options.transformRule] = translateRule + " " + scaleRule;
2305
- }
2306
-
2307
- // Parses value passed to .set method. Returns current value if not parse-able.
2308
- function resolveToValue(to, handleNumber) {
2309
- // Setting with null indicates an 'ignore'.
2310
- // Inputting 'false' is invalid.
2311
- if (to === null || to === false || to === undefined) {
2312
- return scope_Locations[handleNumber];
2313
- }
2314
-
2315
- // If a formatted number was passed, attempt to decode it.
2316
- if (typeof to === "number") {
2317
- to = String(to);
2318
- }
2319
-
2320
- to = options.format.from(to);
2321
- to = scope_Spectrum.toStepping(to);
2322
-
2323
- // If parsing the number failed, use the current value.
2324
- if (to === false || isNaN(to)) {
2325
- return scope_Locations[handleNumber];
2326
- }
2327
-
2328
- return to;
2329
- }
2330
-
2331
- // Set the slider value.
2332
- function valueSet(input, fireSetEvent) {
2333
- var values = asArray(input);
2334
- var isInit = scope_Locations[0] === undefined;
2335
-
2336
- // Event fires by default
2337
- fireSetEvent = fireSetEvent === undefined ? true : !!fireSetEvent;
2338
-
2339
- // Animation is optional.
2340
- // Make sure the initial values were set before using animated placement.
2341
- if (options.animate && !isInit) {
2342
- addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration);
2343
- }
2344
-
2345
- // First pass, without lookAhead but with lookBackward. Values are set from left to right.
2346
- scope_HandleNumbers.forEach(function(handleNumber) {
2347
- setHandle(handleNumber, resolveToValue(values[handleNumber], handleNumber), true, false);
2348
- });
2349
-
2350
- var i = scope_HandleNumbers.length === 1 ? 0 : 1;
2351
-
2352
- // Secondary passes. Now that all base values are set, apply constraints.
2353
- // Iterate all handles to ensure constraints are applied for the entire slider (Issue #1009)
2354
- for (; i < scope_HandleNumbers.length; ++i) {
2355
- scope_HandleNumbers.forEach(function(handleNumber) {
2356
- setHandle(handleNumber, scope_Locations[handleNumber], true, true);
2357
- });
2358
- }
2359
-
2360
- setZindex();
2361
-
2362
- scope_HandleNumbers.forEach(function(handleNumber) {
2363
- fireEvent("update", handleNumber);
2364
-
2365
- // Fire the event only for handles that received a new value, as per #579
2366
- if (values[handleNumber] !== null && fireSetEvent) {
2367
- fireEvent("set", handleNumber);
2368
- }
2369
- });
2370
- }
2371
-
2372
- // Reset slider to initial values
2373
- function valueReset(fireSetEvent) {
2374
- valueSet(options.start, fireSetEvent);
2375
- }
2376
-
2377
- // Set value for a single handle
2378
- function valueSetHandle(handleNumber, value, fireSetEvent) {
2379
- // Ensure numeric input
2380
- handleNumber = Number(handleNumber);
2381
-
2382
- if (!(handleNumber >= 0 && handleNumber < scope_HandleNumbers.length)) {
2383
- throw new Error("noUiSlider (" + VERSION + "): invalid handle number, got: " + handleNumber);
2384
- }
2385
-
2386
- // Look both backward and forward, since we don't want this handle to "push" other handles (#960);
2387
- setHandle(handleNumber, resolveToValue(value, handleNumber), true, true);
2388
-
2389
- fireEvent("update", handleNumber);
2390
-
2391
- if (fireSetEvent) {
2392
- fireEvent("set", handleNumber);
2393
- }
2394
- }
2395
-
2396
- // Get the slider value.
2397
- function valueGet() {
2398
- var values = scope_Values.map(options.format.to);
2399
-
2400
- // If only one handle is used, return a single value.
2401
- if (values.length === 1) {
2402
- return values[0];
2403
- }
2404
-
2405
- return values;
2406
- }
2407
-
2408
- // Removes classes from the root and empties it.
2409
- function destroy() {
2410
- for (var key in options.cssClasses) {
2411
- if (!options.cssClasses.hasOwnProperty(key)) {
2412
- continue;
2413
- }
2414
- removeClass(scope_Target, options.cssClasses[key]);
2415
- }
2416
-
2417
- while (scope_Target.firstChild) {
2418
- scope_Target.removeChild(scope_Target.firstChild);
2419
- }
2420
-
2421
- delete scope_Target.noUiSlider;
2422
- }
2423
-
2424
- function getNextStepsForHandle(handleNumber) {
2425
- var location = scope_Locations[handleNumber];
2426
- var nearbySteps = scope_Spectrum.getNearbySteps(location);
2427
- var value = scope_Values[handleNumber];
2428
- var increment = nearbySteps.thisStep.step;
2429
- var decrement = null;
2430
-
2431
- // If snapped, directly use defined step value
2432
- if (options.snap) {
2433
- return [
2434
- value - nearbySteps.stepBefore.startValue || null,
2435
- nearbySteps.stepAfter.startValue - value || null
2436
- ];
2437
- }
2438
-
2439
- // If the next value in this step moves into the next step,
2440
- // the increment is the start of the next step - the current value
2441
- if (increment !== false) {
2442
- if (value + increment > nearbySteps.stepAfter.startValue) {
2443
- increment = nearbySteps.stepAfter.startValue - value;
2444
- }
2445
- }
2446
-
2447
- // If the value is beyond the starting point
2448
- if (value > nearbySteps.thisStep.startValue) {
2449
- decrement = nearbySteps.thisStep.step;
2450
- } else if (nearbySteps.stepBefore.step === false) {
2451
- decrement = false;
2452
- }
2453
-
2454
- // If a handle is at the start of a step, it always steps back into the previous step first
2455
- else {
2456
- decrement = value - nearbySteps.stepBefore.highestStep;
2457
- }
2458
-
2459
- // Now, if at the slider edges, there is no in/decrement
2460
- if (location === 100) {
2461
- increment = null;
2462
- } else if (location === 0) {
2463
- decrement = null;
2464
- }
2465
-
2466
- // As per #391, the comparison for the decrement step can have some rounding issues.
2467
- var stepDecimals = scope_Spectrum.countStepDecimals();
2468
-
2469
- // Round per #391
2470
- if (increment !== null && increment !== false) {
2471
- increment = Number(increment.toFixed(stepDecimals));
2472
- }
2473
-
2474
- if (decrement !== null && decrement !== false) {
2475
- decrement = Number(decrement.toFixed(stepDecimals));
2476
- }
2477
-
2478
- return [decrement, increment];
2479
- }
2480
-
2481
- // Get the current step size for the slider.
2482
- function getNextSteps() {
2483
- return scope_HandleNumbers.map(getNextStepsForHandle);
2484
- }
2485
-
2486
- // Updateable: margin, limit, padding, step, range, animate, snap
2487
- function updateOptions(optionsToUpdate, fireSetEvent) {
2488
- // Spectrum is created using the range, snap, direction and step options.
2489
- // 'snap' and 'step' can be updated.
2490
- // If 'snap' and 'step' are not passed, they should remain unchanged.
2491
- var v = valueGet();
2492
-
2493
- var updateAble = [
2494
- "margin",
2495
- "limit",
2496
- "padding",
2497
- "range",
2498
- "animate",
2499
- "snap",
2500
- "step",
2501
- "format",
2502
- "pips",
2503
- "tooltips"
2504
- ];
2505
-
2506
- // Only change options that we're actually passed to update.
2507
- updateAble.forEach(function(name) {
2508
- // Check for undefined. null removes the value.
2509
- if (optionsToUpdate[name] !== undefined) {
2510
- originalOptions[name] = optionsToUpdate[name];
2511
- }
2512
- });
2513
-
2514
- var newOptions = testOptions(originalOptions);
2515
-
2516
- // Load new options into the slider state
2517
- updateAble.forEach(function(name) {
2518
- if (optionsToUpdate[name] !== undefined) {
2519
- options[name] = newOptions[name];
2520
- }
2521
- });
2522
-
2523
- scope_Spectrum = newOptions.spectrum;
2524
-
2525
- // Limit, margin and padding depend on the spectrum but are stored outside of it. (#677)
2526
- options.margin = newOptions.margin;
2527
- options.limit = newOptions.limit;
2528
- options.padding = newOptions.padding;
2529
-
2530
- // Update pips, removes existing.
2531
- if (options.pips) {
2532
- pips(options.pips);
2533
- } else {
2534
- removePips();
2535
- }
2536
-
2537
- // Update tooltips, removes existing.
2538
- if (options.tooltips) {
2539
- tooltips();
2540
- } else {
2541
- removeTooltips();
2542
- }
2543
-
2544
- // Invalidate the current positioning so valueSet forces an update.
2545
- scope_Locations = [];
2546
- valueSet(optionsToUpdate.start || v, fireSetEvent);
2547
- }
2548
-
2549
- // Initialization steps
2550
- function setupSlider() {
2551
- // Create the base element, initialize HTML and set classes.
2552
- // Add handles and connect elements.
2553
- scope_Base = addSlider(scope_Target);
2554
-
2555
- addElements(options.connect, scope_Base);
2556
-
2557
- // Attach user events.
2558
- bindSliderEvents(options.events);
2559
-
2560
- // Use the public value method to set the start values.
2561
- valueSet(options.start);
2562
-
2563
- if (options.pips) {
2564
- pips(options.pips);
2565
- }
2566
-
2567
- if (options.tooltips) {
2568
- tooltips();
2569
- }
2570
-
2571
- aria();
2572
- }
2573
-
2574
- setupSlider();
2575
-
2576
- // noinspection JSUnusedGlobalSymbols
2577
- scope_Self = {
2578
- destroy: destroy,
2579
- steps: getNextSteps,
2580
- on: bindEvent,
2581
- off: removeEvent,
2582
- get: valueGet,
2583
- set: valueSet,
2584
- setHandle: valueSetHandle,
2585
- reset: valueReset,
2586
- // Exposed for unit testing, don't use this in your application.
2587
- __moveHandles: function(a, b, c) {
2588
- moveHandles(a, b, scope_Locations, c);
2589
- },
2590
- options: originalOptions, // Issue #600, #678
2591
- updateOptions: updateOptions,
2592
- target: scope_Target, // Issue #597
2593
- removePips: removePips,
2594
- removeTooltips: removeTooltips,
2595
- getTooltips: function() {
2596
- return scope_Tooltips;
2597
- },
2598
- getOrigins: function() {
2599
- return scope_Handles;
2600
- },
2601
- pips: pips // Issue #594
2602
- };
2603
-
2604
- return scope_Self;
2605
- }
2606
-
2607
- // Run the standard initializer
2608
- function initialize(target, originalOptions) {
2609
- if (!target || !target.nodeName) {
2610
- throw new Error("noUiSlider (" + VERSION + "): create requires a single element, got: " + target);
2611
- }
2612
-
2613
- // Throw an error if the slider was already initialized.
2614
- if (target.noUiSlider) {
2615
- throw new Error("noUiSlider (" + VERSION + "): Slider was already initialized.");
2616
- }
2617
-
2618
- // Test the options and create the slider environment;
2619
- var options = testOptions(originalOptions, target);
2620
- var api = scope(target, options, originalOptions);
2621
-
2622
- target.noUiSlider = api;
2623
-
2624
- return api;
2625
- }
2626
-
2627
- // Use an object instead of a function for future expandability;
2628
- return {
2629
- // Exposed for unit testing, don't use this in your application.
2630
- __spectrum: Spectrum,
2631
- version: VERSION,
2632
- // A reference to the default classes, allows global changes.
2633
- // Use the cssClasses option for changes to one slider.
2634
- cssClasses: cssClasses,
2635
- create: initialize
2636
- };
2637
- });
1
+ /*! nouislider - 14.5.0 - 5/11/2020 */
2
+ (function(factory) {
3
+ if (typeof define === "function" && define.amd) {
4
+ // AMD. Register as an anonymous module.
5
+ define([], factory);
6
+ } else if (typeof exports === "object") {
7
+ // Node/CommonJS
8
+ module.exports = factory();
9
+ } else {
10
+ // Browser globals
11
+ window.noUiSlider = factory();
12
+ }
13
+ })(function() {
14
+ "use strict";
15
+
16
+ var VERSION = "14.5.0";
17
+
18
+ //region Helper Methods
19
+
20
+ function isValidFormatter(entry) {
21
+ return typeof entry === "object" && typeof entry.to === "function" && typeof entry.from === "function";
22
+ }
23
+
24
+ function removeElement(el) {
25
+ el.parentElement.removeChild(el);
26
+ }
27
+
28
+ function isSet(value) {
29
+ return value !== null && value !== undefined;
30
+ }
31
+
32
+ // Bindable version
33
+ function preventDefault(e) {
34
+ e.preventDefault();
35
+ }
36
+
37
+ // Removes duplicates from an array.
38
+ function unique(array) {
39
+ return array.filter(function(a) {
40
+ return !this[a] ? (this[a] = true) : false;
41
+ }, {});
42
+ }
43
+
44
+ // Round a value to the closest 'to'.
45
+ function closest(value, to) {
46
+ return Math.round(value / to) * to;
47
+ }
48
+
49
+ // Current position of an element relative to the document.
50
+ function offset(elem, orientation) {
51
+ var rect = elem.getBoundingClientRect();
52
+ var doc = elem.ownerDocument;
53
+ var docElem = doc.documentElement;
54
+ var pageOffset = getPageOffset(doc);
55
+
56
+ // getBoundingClientRect contains left scroll in Chrome on Android.
57
+ // I haven't found a feature detection that proves this. Worst case
58
+ // scenario on mis-match: the 'tap' feature on horizontal sliders breaks.
59
+ if (/webkit.*Chrome.*Mobile/i.test(navigator.userAgent)) {
60
+ pageOffset.x = 0;
61
+ }
62
+
63
+ return orientation
64
+ ? rect.top + pageOffset.y - docElem.clientTop
65
+ : rect.left + pageOffset.x - docElem.clientLeft;
66
+ }
67
+
68
+ // Checks whether a value is numerical.
69
+ function isNumeric(a) {
70
+ return typeof a === "number" && !isNaN(a) && isFinite(a);
71
+ }
72
+
73
+ // Sets a class and removes it after [duration] ms.
74
+ function addClassFor(element, className, duration) {
75
+ if (duration > 0) {
76
+ addClass(element, className);
77
+ setTimeout(function() {
78
+ removeClass(element, className);
79
+ }, duration);
80
+ }
81
+ }
82
+
83
+ // Limits a value to 0 - 100
84
+ function limit(a) {
85
+ return Math.max(Math.min(a, 100), 0);
86
+ }
87
+
88
+ // Wraps a variable as an array, if it isn't one yet.
89
+ // Note that an input array is returned by reference!
90
+ function asArray(a) {
91
+ return Array.isArray(a) ? a : [a];
92
+ }
93
+
94
+ // Counts decimals
95
+ function countDecimals(numStr) {
96
+ numStr = String(numStr);
97
+ var pieces = numStr.split(".");
98
+ return pieces.length > 1 ? pieces[1].length : 0;
99
+ }
100
+
101
+ // http://youmightnotneedjquery.com/#add_class
102
+ function addClass(el, className) {
103
+ if (el.classList && !/\s/.test(className)) {
104
+ el.classList.add(className);
105
+ } else {
106
+ el.className += " " + className;
107
+ }
108
+ }
109
+
110
+ // http://youmightnotneedjquery.com/#remove_class
111
+ function removeClass(el, className) {
112
+ if (el.classList && !/\s/.test(className)) {
113
+ el.classList.remove(className);
114
+ } else {
115
+ el.className = el.className.replace(
116
+ new RegExp("(^|\\b)" + className.split(" ").join("|") + "(\\b|$)", "gi"),
117
+ " "
118
+ );
119
+ }
120
+ }
121
+
122
+ // https://plainjs.com/javascript/attributes/adding-removing-and-testing-for-classes-9/
123
+ function hasClass(el, className) {
124
+ return el.classList
125
+ ? el.classList.contains(className)
126
+ : new RegExp("\\b" + className + "\\b").test(el.className);
127
+ }
128
+
129
+ // https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY#Notes
130
+ function getPageOffset(doc) {
131
+ var supportPageOffset = window.pageXOffset !== undefined;
132
+ var isCSS1Compat = (doc.compatMode || "") === "CSS1Compat";
133
+ var x = supportPageOffset
134
+ ? window.pageXOffset
135
+ : isCSS1Compat
136
+ ? doc.documentElement.scrollLeft
137
+ : doc.body.scrollLeft;
138
+ var y = supportPageOffset
139
+ ? window.pageYOffset
140
+ : isCSS1Compat
141
+ ? doc.documentElement.scrollTop
142
+ : doc.body.scrollTop;
143
+
144
+ return {
145
+ x: x,
146
+ y: y
147
+ };
148
+ }
149
+
150
+ // we provide a function to compute constants instead
151
+ // of accessing window.* as soon as the module needs it
152
+ // so that we do not compute anything if not needed
153
+ function getActions() {
154
+ // Determine the events to bind. IE11 implements pointerEvents without
155
+ // a prefix, which breaks compatibility with the IE10 implementation.
156
+ return window.navigator.pointerEnabled
157
+ ? {
158
+ start: "pointerdown",
159
+ move: "pointermove",
160
+ end: "pointerup"
161
+ }
162
+ : window.navigator.msPointerEnabled
163
+ ? {
164
+ start: "MSPointerDown",
165
+ move: "MSPointerMove",
166
+ end: "MSPointerUp"
167
+ }
168
+ : {
169
+ start: "mousedown touchstart",
170
+ move: "mousemove touchmove",
171
+ end: "mouseup touchend"
172
+ };
173
+ }
174
+
175
+ // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
176
+ // Issue #785
177
+ function getSupportsPassive() {
178
+ var supportsPassive = false;
179
+
180
+ /* eslint-disable */
181
+ try {
182
+ var opts = Object.defineProperty({}, "passive", {
183
+ get: function() {
184
+ supportsPassive = true;
185
+ }
186
+ });
187
+
188
+ window.addEventListener("test", null, opts);
189
+ } catch (e) {}
190
+ /* eslint-enable */
191
+
192
+ return supportsPassive;
193
+ }
194
+
195
+ function getSupportsTouchActionNone() {
196
+ return window.CSS && CSS.supports && CSS.supports("touch-action", "none");
197
+ }
198
+
199
+ //endregion
200
+
201
+ //region Range Calculation
202
+
203
+ // Determine the size of a sub-range in relation to a full range.
204
+ function subRangeRatio(pa, pb) {
205
+ return 100 / (pb - pa);
206
+ }
207
+
208
+ // (percentage) How many percent is this value of this range?
209
+ function fromPercentage(range, value, startRange) {
210
+ return (value * 100) / (range[startRange + 1] - range[startRange]);
211
+ }
212
+
213
+ // (percentage) Where is this value on this range?
214
+ function toPercentage(range, value) {
215
+ return fromPercentage(range, range[0] < 0 ? value + Math.abs(range[0]) : value - range[0], 0);
216
+ }
217
+
218
+ // (value) How much is this percentage on this range?
219
+ function isPercentage(range, value) {
220
+ return (value * (range[1] - range[0])) / 100 + range[0];
221
+ }
222
+
223
+ function getJ(value, arr) {
224
+ var j = 1;
225
+
226
+ while (value >= arr[j]) {
227
+ j += 1;
228
+ }
229
+
230
+ return j;
231
+ }
232
+
233
+ // (percentage) Input a value, find where, on a scale of 0-100, it applies.
234
+ function toStepping(xVal, xPct, value) {
235
+ if (value >= xVal.slice(-1)[0]) {
236
+ return 100;
237
+ }
238
+
239
+ var j = getJ(value, xVal);
240
+ var va = xVal[j - 1];
241
+ var vb = xVal[j];
242
+ var pa = xPct[j - 1];
243
+ var pb = xPct[j];
244
+
245
+ return pa + toPercentage([va, vb], value) / subRangeRatio(pa, pb);
246
+ }
247
+
248
+ // (value) Input a percentage, find where it is on the specified range.
249
+ function fromStepping(xVal, xPct, value) {
250
+ // There is no range group that fits 100
251
+ if (value >= 100) {
252
+ return xVal.slice(-1)[0];
253
+ }
254
+
255
+ var j = getJ(value, xPct);
256
+ var va = xVal[j - 1];
257
+ var vb = xVal[j];
258
+ var pa = xPct[j - 1];
259
+ var pb = xPct[j];
260
+
261
+ return isPercentage([va, vb], (value - pa) * subRangeRatio(pa, pb));
262
+ }
263
+
264
+ // (percentage) Get the step that applies at a certain value.
265
+ function getStep(xPct, xSteps, snap, value) {
266
+ if (value === 100) {
267
+ return value;
268
+ }
269
+
270
+ var j = getJ(value, xPct);
271
+ var a = xPct[j - 1];
272
+ var b = xPct[j];
273
+
274
+ // If 'snap' is set, steps are used as fixed points on the slider.
275
+ if (snap) {
276
+ // Find the closest position, a or b.
277
+ if (value - a > (b - a) / 2) {
278
+ return b;
279
+ }
280
+
281
+ return a;
282
+ }
283
+
284
+ if (!xSteps[j - 1]) {
285
+ return value;
286
+ }
287
+
288
+ return xPct[j - 1] + closest(value - xPct[j - 1], xSteps[j - 1]);
289
+ }
290
+
291
+ function handleEntryPoint(index, value, that) {
292
+ var percentage;
293
+
294
+ // Wrap numerical input in an array.
295
+ if (typeof value === "number") {
296
+ value = [value];
297
+ }
298
+
299
+ // Reject any invalid input, by testing whether value is an array.
300
+ if (!Array.isArray(value)) {
301
+ throw new Error("noUiSlider (" + VERSION + "): 'range' contains invalid value.");
302
+ }
303
+
304
+ // Covert min/max syntax to 0 and 100.
305
+ if (index === "min") {
306
+ percentage = 0;
307
+ } else if (index === "max") {
308
+ percentage = 100;
309
+ } else {
310
+ percentage = parseFloat(index);
311
+ }
312
+
313
+ // Check for correct input.
314
+ if (!isNumeric(percentage) || !isNumeric(value[0])) {
315
+ throw new Error("noUiSlider (" + VERSION + "): 'range' value isn't numeric.");
316
+ }
317
+
318
+ // Store values.
319
+ that.xPct.push(percentage);
320
+ that.xVal.push(value[0]);
321
+
322
+ // NaN will evaluate to false too, but to keep
323
+ // logging clear, set step explicitly. Make sure
324
+ // not to override the 'step' setting with false.
325
+ if (!percentage) {
326
+ if (!isNaN(value[1])) {
327
+ that.xSteps[0] = value[1];
328
+ }
329
+ } else {
330
+ that.xSteps.push(isNaN(value[1]) ? false : value[1]);
331
+ }
332
+
333
+ that.xHighestCompleteStep.push(0);
334
+ }
335
+
336
+ function handleStepPoint(i, n, that) {
337
+ // Ignore 'false' stepping.
338
+ if (!n) {
339
+ return;
340
+ }
341
+
342
+ // Step over zero-length ranges (#948);
343
+ if (that.xVal[i] === that.xVal[i + 1]) {
344
+ that.xSteps[i] = that.xHighestCompleteStep[i] = that.xVal[i];
345
+
346
+ return;
347
+ }
348
+
349
+ // Factor to range ratio
350
+ that.xSteps[i] =
351
+ fromPercentage([that.xVal[i], that.xVal[i + 1]], n, 0) / subRangeRatio(that.xPct[i], that.xPct[i + 1]);
352
+
353
+ var totalSteps = (that.xVal[i + 1] - that.xVal[i]) / that.xNumSteps[i];
354
+ var highestStep = Math.ceil(Number(totalSteps.toFixed(3)) - 1);
355
+ var step = that.xVal[i] + that.xNumSteps[i] * highestStep;
356
+
357
+ that.xHighestCompleteStep[i] = step;
358
+ }
359
+
360
+ //endregion
361
+
362
+ //region Spectrum
363
+
364
+ function Spectrum(entry, snap, singleStep) {
365
+ this.xPct = [];
366
+ this.xVal = [];
367
+ this.xSteps = [singleStep || false];
368
+ this.xNumSteps = [false];
369
+ this.xHighestCompleteStep = [];
370
+
371
+ this.snap = snap;
372
+
373
+ var index;
374
+ var ordered = []; // [0, 'min'], [1, '50%'], [2, 'max']
375
+
376
+ // Map the object keys to an array.
377
+ for (index in entry) {
378
+ if (entry.hasOwnProperty(index)) {
379
+ ordered.push([entry[index], index]);
380
+ }
381
+ }
382
+
383
+ // Sort all entries by value (numeric sort).
384
+ if (ordered.length && typeof ordered[0][0] === "object") {
385
+ ordered.sort(function(a, b) {
386
+ return a[0][0] - b[0][0];
387
+ });
388
+ } else {
389
+ ordered.sort(function(a, b) {
390
+ return a[0] - b[0];
391
+ });
392
+ }
393
+
394
+ // Convert all entries to subranges.
395
+ for (index = 0; index < ordered.length; index++) {
396
+ handleEntryPoint(ordered[index][1], ordered[index][0], this);
397
+ }
398
+
399
+ // Store the actual step values.
400
+ // xSteps is sorted in the same order as xPct and xVal.
401
+ this.xNumSteps = this.xSteps.slice(0);
402
+
403
+ // Convert all numeric steps to the percentage of the subrange they represent.
404
+ for (index = 0; index < this.xNumSteps.length; index++) {
405
+ handleStepPoint(index, this.xNumSteps[index], this);
406
+ }
407
+ }
408
+
409
+ Spectrum.prototype.getDistance = function(value) {
410
+ var index;
411
+ var distances = [];
412
+
413
+ for (index = 0; index < this.xNumSteps.length - 1; index++) {
414
+ // last "range" can't contain step size as it is purely an endpoint.
415
+ var step = this.xNumSteps[index];
416
+
417
+ if (step && (value / step) % 1 !== 0) {
418
+ throw new Error(
419
+ "noUiSlider (" +
420
+ VERSION +
421
+ "): 'limit', 'margin' and 'padding' of " +
422
+ this.xPct[index] +
423
+ "% range must be divisible by step."
424
+ );
425
+ }
426
+
427
+ // Calculate percentual distance in current range of limit, margin or padding
428
+ distances[index] = fromPercentage(this.xVal, value, index);
429
+ }
430
+
431
+ return distances;
432
+ };
433
+
434
+ // Calculate the percentual distance over the whole scale of ranges.
435
+ // direction: 0 = backwards / 1 = forwards
436
+ Spectrum.prototype.getAbsoluteDistance = function(value, distances, direction) {
437
+ var xPct_index = 0;
438
+
439
+ // Calculate range where to start calculation
440
+ if (value < this.xPct[this.xPct.length - 1]) {
441
+ while (value > this.xPct[xPct_index + 1]) {
442
+ xPct_index++;
443
+ }
444
+ } else if (value === this.xPct[this.xPct.length - 1]) {
445
+ xPct_index = this.xPct.length - 2;
446
+ }
447
+
448
+ // If looking backwards and the value is exactly at a range separator then look one range further
449
+ if (!direction && value === this.xPct[xPct_index + 1]) {
450
+ xPct_index++;
451
+ }
452
+
453
+ var start_factor;
454
+ var rest_factor = 1;
455
+
456
+ var rest_rel_distance = distances[xPct_index];
457
+
458
+ var range_pct = 0;
459
+
460
+ var rel_range_distance = 0;
461
+ var abs_distance_counter = 0;
462
+ var range_counter = 0;
463
+
464
+ // Calculate what part of the start range the value is
465
+ if (direction) {
466
+ start_factor = (value - this.xPct[xPct_index]) / (this.xPct[xPct_index + 1] - this.xPct[xPct_index]);
467
+ } else {
468
+ start_factor = (this.xPct[xPct_index + 1] - value) / (this.xPct[xPct_index + 1] - this.xPct[xPct_index]);
469
+ }
470
+
471
+ // Do until the complete distance across ranges is calculated
472
+ while (rest_rel_distance > 0) {
473
+ // Calculate the percentage of total range
474
+ range_pct = this.xPct[xPct_index + 1 + range_counter] - this.xPct[xPct_index + range_counter];
475
+
476
+ // Detect if the margin, padding or limit is larger then the current range and calculate
477
+ if (distances[xPct_index + range_counter] * rest_factor + 100 - start_factor * 100 > 100) {
478
+ // If larger then take the percentual distance of the whole range
479
+ rel_range_distance = range_pct * start_factor;
480
+ // Rest factor of relative percentual distance still to be calculated
481
+ rest_factor = (rest_rel_distance - 100 * start_factor) / distances[xPct_index + range_counter];
482
+ // Set start factor to 1 as for next range it does not apply.
483
+ start_factor = 1;
484
+ } else {
485
+ // If smaller or equal then take the percentual distance of the calculate percentual part of that range
486
+ rel_range_distance = ((distances[xPct_index + range_counter] * range_pct) / 100) * rest_factor;
487
+ // No rest left as the rest fits in current range
488
+ rest_factor = 0;
489
+ }
490
+
491
+ if (direction) {
492
+ abs_distance_counter = abs_distance_counter - rel_range_distance;
493
+ // Limit range to first range when distance becomes outside of minimum range
494
+ if (this.xPct.length + range_counter >= 1) {
495
+ range_counter--;
496
+ }
497
+ } else {
498
+ abs_distance_counter = abs_distance_counter + rel_range_distance;
499
+ // Limit range to last range when distance becomes outside of maximum range
500
+ if (this.xPct.length - range_counter >= 1) {
501
+ range_counter++;
502
+ }
503
+ }
504
+
505
+ // Rest of relative percentual distance still to be calculated
506
+ rest_rel_distance = distances[xPct_index + range_counter] * rest_factor;
507
+ }
508
+
509
+ return value + abs_distance_counter;
510
+ };
511
+
512
+ Spectrum.prototype.toStepping = function(value) {
513
+ value = toStepping(this.xVal, this.xPct, value);
514
+
515
+ return value;
516
+ };
517
+
518
+ Spectrum.prototype.fromStepping = function(value) {
519
+ return fromStepping(this.xVal, this.xPct, value);
520
+ };
521
+
522
+ Spectrum.prototype.getStep = function(value) {
523
+ value = getStep(this.xPct, this.xSteps, this.snap, value);
524
+
525
+ return value;
526
+ };
527
+
528
+ Spectrum.prototype.getDefaultStep = function(value, isDown, size) {
529
+ var j = getJ(value, this.xPct);
530
+
531
+ // When at the top or stepping down, look at the previous sub-range
532
+ if (value === 100 || (isDown && value === this.xPct[j - 1])) {
533
+ j = Math.max(j - 1, 1);
534
+ }
535
+
536
+ return (this.xVal[j] - this.xVal[j - 1]) / size;
537
+ };
538
+
539
+ Spectrum.prototype.getNearbySteps = function(value) {
540
+ var j = getJ(value, this.xPct);
541
+
542
+ return {
543
+ stepBefore: {
544
+ startValue: this.xVal[j - 2],
545
+ step: this.xNumSteps[j - 2],
546
+ highestStep: this.xHighestCompleteStep[j - 2]
547
+ },
548
+ thisStep: {
549
+ startValue: this.xVal[j - 1],
550
+ step: this.xNumSteps[j - 1],
551
+ highestStep: this.xHighestCompleteStep[j - 1]
552
+ },
553
+ stepAfter: {
554
+ startValue: this.xVal[j],
555
+ step: this.xNumSteps[j],
556
+ highestStep: this.xHighestCompleteStep[j]
557
+ }
558
+ };
559
+ };
560
+
561
+ Spectrum.prototype.countStepDecimals = function() {
562
+ var stepDecimals = this.xNumSteps.map(countDecimals);
563
+ return Math.max.apply(null, stepDecimals);
564
+ };
565
+
566
+ // Outside testing
567
+ Spectrum.prototype.convert = function(value) {
568
+ return this.getStep(this.toStepping(value));
569
+ };
570
+
571
+ //endregion
572
+
573
+ //region Options
574
+
575
+ /* Every input option is tested and parsed. This'll prevent
576
+ endless validation in internal methods. These tests are
577
+ structured with an item for every option available. An
578
+ option can be marked as required by setting the 'r' flag.
579
+ The testing function is provided with three arguments:
580
+ - The provided value for the option;
581
+ - A reference to the options object;
582
+ - The name for the option;
583
+
584
+ The testing function returns false when an error is detected,
585
+ or true when everything is OK. It can also modify the option
586
+ object, to make sure all values can be correctly looped elsewhere. */
587
+
588
+ //region Defaults
589
+
590
+ var defaultFormatter = {
591
+ to: function(value) {
592
+ return value !== undefined && value.toFixed(2);
593
+ },
594
+ from: Number
595
+ };
596
+
597
+ var cssClasses = {
598
+ target: "target",
599
+ base: "base",
600
+ origin: "origin",
601
+ handle: "handle",
602
+ handleLower: "handle-lower",
603
+ handleUpper: "handle-upper",
604
+ touchArea: "touch-area",
605
+ horizontal: "horizontal",
606
+ vertical: "vertical",
607
+ background: "background",
608
+ connect: "connect",
609
+ connects: "connects",
610
+ ltr: "ltr",
611
+ rtl: "rtl",
612
+ textDirectionLtr: "txt-dir-ltr",
613
+ textDirectionRtl: "txt-dir-rtl",
614
+ draggable: "draggable",
615
+ drag: "state-drag",
616
+ tap: "state-tap",
617
+ active: "active",
618
+ tooltip: "tooltip",
619
+ pips: "pips",
620
+ pipsHorizontal: "pips-horizontal",
621
+ pipsVertical: "pips-vertical",
622
+ marker: "marker",
623
+ markerHorizontal: "marker-horizontal",
624
+ markerVertical: "marker-vertical",
625
+ markerNormal: "marker-normal",
626
+ markerLarge: "marker-large",
627
+ markerSub: "marker-sub",
628
+ value: "value",
629
+ valueHorizontal: "value-horizontal",
630
+ valueVertical: "value-vertical",
631
+ valueNormal: "value-normal",
632
+ valueLarge: "value-large",
633
+ valueSub: "value-sub"
634
+ };
635
+
636
+ //endregion
637
+
638
+ function validateFormat(entry) {
639
+ // Any object with a to and from method is supported.
640
+ if (isValidFormatter(entry)) {
641
+ return true;
642
+ }
643
+
644
+ throw new Error("noUiSlider (" + VERSION + "): 'format' requires 'to' and 'from' methods.");
645
+ }
646
+
647
+ function testStep(parsed, entry) {
648
+ if (!isNumeric(entry)) {
649
+ throw new Error("noUiSlider (" + VERSION + "): 'step' is not numeric.");
650
+ }
651
+
652
+ // The step option can still be used to set stepping
653
+ // for linear sliders. Overwritten if set in 'range'.
654
+ parsed.singleStep = entry;
655
+ }
656
+
657
+ function testRange(parsed, entry) {
658
+ // Filter incorrect input.
659
+ if (typeof entry !== "object" || Array.isArray(entry)) {
660
+ throw new Error("noUiSlider (" + VERSION + "): 'range' is not an object.");
661
+ }
662
+
663
+ // Catch missing start or end.
664
+ if (entry.min === undefined || entry.max === undefined) {
665
+ throw new Error("noUiSlider (" + VERSION + "): Missing 'min' or 'max' in 'range'.");
666
+ }
667
+
668
+ // Catch equal start or end.
669
+ if (entry.min === entry.max) {
670
+ throw new Error("noUiSlider (" + VERSION + "): 'range' 'min' and 'max' cannot be equal.");
671
+ }
672
+
673
+ parsed.spectrum = new Spectrum(entry, parsed.snap, parsed.singleStep);
674
+ }
675
+
676
+ function testStart(parsed, entry) {
677
+ entry = asArray(entry);
678
+
679
+ // Validate input. Values aren't tested, as the public .val method
680
+ // will always provide a valid location.
681
+ if (!Array.isArray(entry) || !entry.length) {
682
+ throw new Error("noUiSlider (" + VERSION + "): 'start' option is incorrect.");
683
+ }
684
+
685
+ // Store the number of handles.
686
+ parsed.handles = entry.length;
687
+
688
+ // When the slider is initialized, the .val method will
689
+ // be called with the start options.
690
+ parsed.start = entry;
691
+ }
692
+
693
+ function testSnap(parsed, entry) {
694
+ // Enforce 100% stepping within subranges.
695
+ parsed.snap = entry;
696
+
697
+ if (typeof entry !== "boolean") {
698
+ throw new Error("noUiSlider (" + VERSION + "): 'snap' option must be a boolean.");
699
+ }
700
+ }
701
+
702
+ function testAnimate(parsed, entry) {
703
+ // Enforce 100% stepping within subranges.
704
+ parsed.animate = entry;
705
+
706
+ if (typeof entry !== "boolean") {
707
+ throw new Error("noUiSlider (" + VERSION + "): 'animate' option must be a boolean.");
708
+ }
709
+ }
710
+
711
+ function testAnimationDuration(parsed, entry) {
712
+ parsed.animationDuration = entry;
713
+
714
+ if (typeof entry !== "number") {
715
+ throw new Error("noUiSlider (" + VERSION + "): 'animationDuration' option must be a number.");
716
+ }
717
+ }
718
+
719
+ function testConnect(parsed, entry) {
720
+ var connect = [false];
721
+ var i;
722
+
723
+ // Map legacy options
724
+ if (entry === "lower") {
725
+ entry = [true, false];
726
+ } else if (entry === "upper") {
727
+ entry = [false, true];
728
+ }
729
+
730
+ // Handle boolean options
731
+ if (entry === true || entry === false) {
732
+ for (i = 1; i < parsed.handles; i++) {
733
+ connect.push(entry);
734
+ }
735
+
736
+ connect.push(false);
737
+ }
738
+
739
+ // Reject invalid input
740
+ else if (!Array.isArray(entry) || !entry.length || entry.length !== parsed.handles + 1) {
741
+ throw new Error("noUiSlider (" + VERSION + "): 'connect' option doesn't match handle count.");
742
+ } else {
743
+ connect = entry;
744
+ }
745
+
746
+ parsed.connect = connect;
747
+ }
748
+
749
+ function testOrientation(parsed, entry) {
750
+ // Set orientation to an a numerical value for easy
751
+ // array selection.
752
+ switch (entry) {
753
+ case "horizontal":
754
+ parsed.ort = 0;
755
+ break;
756
+ case "vertical":
757
+ parsed.ort = 1;
758
+ break;
759
+ default:
760
+ throw new Error("noUiSlider (" + VERSION + "): 'orientation' option is invalid.");
761
+ }
762
+ }
763
+
764
+ function testMargin(parsed, entry) {
765
+ if (!isNumeric(entry)) {
766
+ throw new Error("noUiSlider (" + VERSION + "): 'margin' option must be numeric.");
767
+ }
768
+
769
+ // Issue #582
770
+ if (entry === 0) {
771
+ return;
772
+ }
773
+
774
+ parsed.margin = parsed.spectrum.getDistance(entry);
775
+ }
776
+
777
+ function testLimit(parsed, entry) {
778
+ if (!isNumeric(entry)) {
779
+ throw new Error("noUiSlider (" + VERSION + "): 'limit' option must be numeric.");
780
+ }
781
+
782
+ parsed.limit = parsed.spectrum.getDistance(entry);
783
+
784
+ if (!parsed.limit || parsed.handles < 2) {
785
+ throw new Error(
786
+ "noUiSlider (" +
787
+ VERSION +
788
+ "): 'limit' option is only supported on linear sliders with 2 or more handles."
789
+ );
790
+ }
791
+ }
792
+
793
+ function testPadding(parsed, entry) {
794
+ var index;
795
+
796
+ if (!isNumeric(entry) && !Array.isArray(entry)) {
797
+ throw new Error(
798
+ "noUiSlider (" + VERSION + "): 'padding' option must be numeric or array of exactly 2 numbers."
799
+ );
800
+ }
801
+
802
+ if (Array.isArray(entry) && !(entry.length === 2 || isNumeric(entry[0]) || isNumeric(entry[1]))) {
803
+ throw new Error(
804
+ "noUiSlider (" + VERSION + "): 'padding' option must be numeric or array of exactly 2 numbers."
805
+ );
806
+ }
807
+
808
+ if (entry === 0) {
809
+ return;
810
+ }
811
+
812
+ if (!Array.isArray(entry)) {
813
+ entry = [entry, entry];
814
+ }
815
+
816
+ // 'getDistance' returns false for invalid values.
817
+ parsed.padding = [parsed.spectrum.getDistance(entry[0]), parsed.spectrum.getDistance(entry[1])];
818
+
819
+ for (index = 0; index < parsed.spectrum.xNumSteps.length - 1; index++) {
820
+ // last "range" can't contain step size as it is purely an endpoint.
821
+ if (parsed.padding[0][index] < 0 || parsed.padding[1][index] < 0) {
822
+ throw new Error("noUiSlider (" + VERSION + "): 'padding' option must be a positive number(s).");
823
+ }
824
+ }
825
+
826
+ var totalPadding = entry[0] + entry[1];
827
+ var firstValue = parsed.spectrum.xVal[0];
828
+ var lastValue = parsed.spectrum.xVal[parsed.spectrum.xVal.length - 1];
829
+
830
+ if (totalPadding / (lastValue - firstValue) > 1) {
831
+ throw new Error("noUiSlider (" + VERSION + "): 'padding' option must not exceed 100% of the range.");
832
+ }
833
+ }
834
+
835
+ function testDirection(parsed, entry) {
836
+ // Set direction as a numerical value for easy parsing.
837
+ // Invert connection for RTL sliders, so that the proper
838
+ // handles get the connect/background classes.
839
+ switch (entry) {
840
+ case "ltr":
841
+ parsed.dir = 0;
842
+ break;
843
+ case "rtl":
844
+ parsed.dir = 1;
845
+ break;
846
+ default:
847
+ throw new Error("noUiSlider (" + VERSION + "): 'direction' option was not recognized.");
848
+ }
849
+ }
850
+
851
+ function testBehaviour(parsed, entry) {
852
+ // Make sure the input is a string.
853
+ if (typeof entry !== "string") {
854
+ throw new Error("noUiSlider (" + VERSION + "): 'behaviour' must be a string containing options.");
855
+ }
856
+
857
+ // Check if the string contains any keywords.
858
+ // None are required.
859
+ var tap = entry.indexOf("tap") >= 0;
860
+ var drag = entry.indexOf("drag") >= 0;
861
+ var fixed = entry.indexOf("fixed") >= 0;
862
+ var snap = entry.indexOf("snap") >= 0;
863
+ var hover = entry.indexOf("hover") >= 0;
864
+ var unconstrained = entry.indexOf("unconstrained") >= 0;
865
+
866
+ if (fixed) {
867
+ if (parsed.handles !== 2) {
868
+ throw new Error("noUiSlider (" + VERSION + "): 'fixed' behaviour must be used with 2 handles");
869
+ }
870
+
871
+ // Use margin to enforce fixed state
872
+ testMargin(parsed, parsed.start[1] - parsed.start[0]);
873
+ }
874
+
875
+ if (unconstrained && (parsed.margin || parsed.limit)) {
876
+ throw new Error(
877
+ "noUiSlider (" + VERSION + "): 'unconstrained' behaviour cannot be used with margin or limit"
878
+ );
879
+ }
880
+
881
+ parsed.events = {
882
+ tap: tap || snap,
883
+ drag: drag,
884
+ fixed: fixed,
885
+ snap: snap,
886
+ hover: hover,
887
+ unconstrained: unconstrained
888
+ };
889
+ }
890
+
891
+ function testTooltips(parsed, entry) {
892
+ if (entry === false) {
893
+ return;
894
+ }
895
+
896
+ if (entry === true) {
897
+ parsed.tooltips = [];
898
+
899
+ for (var i = 0; i < parsed.handles; i++) {
900
+ parsed.tooltips.push(true);
901
+ }
902
+ } else {
903
+ parsed.tooltips = asArray(entry);
904
+
905
+ if (parsed.tooltips.length !== parsed.handles) {
906
+ throw new Error("noUiSlider (" + VERSION + "): must pass a formatter for all handles.");
907
+ }
908
+
909
+ parsed.tooltips.forEach(function(formatter) {
910
+ if (
911
+ typeof formatter !== "boolean" &&
912
+ (typeof formatter !== "object" || typeof formatter.to !== "function")
913
+ ) {
914
+ throw new Error("noUiSlider (" + VERSION + "): 'tooltips' must be passed a formatter or 'false'.");
915
+ }
916
+ });
917
+ }
918
+ }
919
+
920
+ function testAriaFormat(parsed, entry) {
921
+ parsed.ariaFormat = entry;
922
+ validateFormat(entry);
923
+ }
924
+
925
+ function testFormat(parsed, entry) {
926
+ parsed.format = entry;
927
+ validateFormat(entry);
928
+ }
929
+
930
+ function testKeyboardSupport(parsed, entry) {
931
+ parsed.keyboardSupport = entry;
932
+
933
+ if (typeof entry !== "boolean") {
934
+ throw new Error("noUiSlider (" + VERSION + "): 'keyboardSupport' option must be a boolean.");
935
+ }
936
+ }
937
+
938
+ function testDocumentElement(parsed, entry) {
939
+ // This is an advanced option. Passed values are used without validation.
940
+ parsed.documentElement = entry;
941
+ }
942
+
943
+ function testCssPrefix(parsed, entry) {
944
+ if (typeof entry !== "string" && entry !== false) {
945
+ throw new Error("noUiSlider (" + VERSION + "): 'cssPrefix' must be a string or `false`.");
946
+ }
947
+
948
+ parsed.cssPrefix = entry;
949
+ }
950
+
951
+ function testCssClasses(parsed, entry) {
952
+ if (typeof entry !== "object") {
953
+ throw new Error("noUiSlider (" + VERSION + "): 'cssClasses' must be an object.");
954
+ }
955
+
956
+ if (typeof parsed.cssPrefix === "string") {
957
+ parsed.cssClasses = {};
958
+
959
+ for (var key in entry) {
960
+ if (!entry.hasOwnProperty(key)) {
961
+ continue;
962
+ }
963
+
964
+ parsed.cssClasses[key] = parsed.cssPrefix + entry[key];
965
+ }
966
+ } else {
967
+ parsed.cssClasses = entry;
968
+ }
969
+ }
970
+
971
+ // Test all developer settings and parse to assumption-safe values.
972
+ function testOptions(options) {
973
+ // To prove a fix for #537, freeze options here.
974
+ // If the object is modified, an error will be thrown.
975
+ // Object.freeze(options);
976
+
977
+ var parsed = {
978
+ margin: 0,
979
+ limit: 0,
980
+ padding: 0,
981
+ animate: true,
982
+ animationDuration: 300,
983
+ ariaFormat: defaultFormatter,
984
+ format: defaultFormatter
985
+ };
986
+
987
+ // Tests are executed in the order they are presented here.
988
+ var tests = {
989
+ step: { r: false, t: testStep },
990
+ start: { r: true, t: testStart },
991
+ connect: { r: true, t: testConnect },
992
+ direction: { r: true, t: testDirection },
993
+ snap: { r: false, t: testSnap },
994
+ animate: { r: false, t: testAnimate },
995
+ animationDuration: { r: false, t: testAnimationDuration },
996
+ range: { r: true, t: testRange },
997
+ orientation: { r: false, t: testOrientation },
998
+ margin: { r: false, t: testMargin },
999
+ limit: { r: false, t: testLimit },
1000
+ padding: { r: false, t: testPadding },
1001
+ behaviour: { r: true, t: testBehaviour },
1002
+ ariaFormat: { r: false, t: testAriaFormat },
1003
+ format: { r: false, t: testFormat },
1004
+ tooltips: { r: false, t: testTooltips },
1005
+ keyboardSupport: { r: true, t: testKeyboardSupport },
1006
+ documentElement: { r: false, t: testDocumentElement },
1007
+ cssPrefix: { r: true, t: testCssPrefix },
1008
+ cssClasses: { r: true, t: testCssClasses }
1009
+ };
1010
+
1011
+ var defaults = {
1012
+ connect: false,
1013
+ direction: "ltr",
1014
+ behaviour: "tap",
1015
+ orientation: "horizontal",
1016
+ keyboardSupport: true,
1017
+ cssPrefix: "noUi-",
1018
+ cssClasses: cssClasses
1019
+ };
1020
+
1021
+ // AriaFormat defaults to regular format, if any.
1022
+ if (options.format && !options.ariaFormat) {
1023
+ options.ariaFormat = options.format;
1024
+ }
1025
+
1026
+ // Run all options through a testing mechanism to ensure correct
1027
+ // input. It should be noted that options might get modified to
1028
+ // be handled properly. E.g. wrapping integers in arrays.
1029
+ Object.keys(tests).forEach(function(name) {
1030
+ // If the option isn't set, but it is required, throw an error.
1031
+ if (!isSet(options[name]) && defaults[name] === undefined) {
1032
+ if (tests[name].r) {
1033
+ throw new Error("noUiSlider (" + VERSION + "): '" + name + "' is required.");
1034
+ }
1035
+
1036
+ return true;
1037
+ }
1038
+
1039
+ tests[name].t(parsed, !isSet(options[name]) ? defaults[name] : options[name]);
1040
+ });
1041
+
1042
+ // Forward pips options
1043
+ parsed.pips = options.pips;
1044
+
1045
+ // All recent browsers accept unprefixed transform.
1046
+ // We need -ms- for IE9 and -webkit- for older Android;
1047
+ // Assume use of -webkit- if unprefixed and -ms- are not supported.
1048
+ // https://caniuse.com/#feat=transforms2d
1049
+ var d = document.createElement("div");
1050
+ var msPrefix = d.style.msTransform !== undefined;
1051
+ var noPrefix = d.style.transform !== undefined;
1052
+
1053
+ parsed.transformRule = noPrefix ? "transform" : msPrefix ? "msTransform" : "webkitTransform";
1054
+
1055
+ // Pips don't move, so we can place them using left/top.
1056
+ var styles = [["left", "top"], ["right", "bottom"]];
1057
+
1058
+ parsed.style = styles[parsed.dir][parsed.ort];
1059
+
1060
+ return parsed;
1061
+ }
1062
+
1063
+ //endregion
1064
+
1065
+ function scope(target, options, originalOptions) {
1066
+ var actions = getActions();
1067
+ var supportsTouchActionNone = getSupportsTouchActionNone();
1068
+ var supportsPassive = supportsTouchActionNone && getSupportsPassive();
1069
+
1070
+ // All variables local to 'scope' are prefixed with 'scope_'
1071
+
1072
+ // Slider DOM Nodes
1073
+ var scope_Target = target;
1074
+ var scope_Base;
1075
+ var scope_Handles;
1076
+ var scope_Connects;
1077
+ var scope_Pips;
1078
+ var scope_Tooltips;
1079
+
1080
+ // Slider state values
1081
+ var scope_Spectrum = options.spectrum;
1082
+ var scope_Values = [];
1083
+ var scope_Locations = [];
1084
+ var scope_HandleNumbers = [];
1085
+ var scope_ActiveHandlesCount = 0;
1086
+ var scope_Events = {};
1087
+
1088
+ // Exposed API
1089
+ var scope_Self;
1090
+
1091
+ // Document Nodes
1092
+ var scope_Document = target.ownerDocument;
1093
+ var scope_DocumentElement = options.documentElement || scope_Document.documentElement;
1094
+ var scope_Body = scope_Document.body;
1095
+
1096
+ // Pips constants
1097
+ var PIPS_NONE = -1;
1098
+ var PIPS_NO_VALUE = 0;
1099
+ var PIPS_LARGE_VALUE = 1;
1100
+ var PIPS_SMALL_VALUE = 2;
1101
+
1102
+ // For horizontal sliders in standard ltr documents,
1103
+ // make .noUi-origin overflow to the left so the document doesn't scroll.
1104
+ var scope_DirOffset = scope_Document.dir === "rtl" || options.ort === 1 ? 0 : 100;
1105
+
1106
+ // Creates a node, adds it to target, returns the new node.
1107
+ function addNodeTo(addTarget, className) {
1108
+ var div = scope_Document.createElement("div");
1109
+
1110
+ if (className) {
1111
+ addClass(div, className);
1112
+ }
1113
+
1114
+ addTarget.appendChild(div);
1115
+
1116
+ return div;
1117
+ }
1118
+
1119
+ // Append a origin to the base
1120
+ function addOrigin(base, handleNumber) {
1121
+ var origin = addNodeTo(base, options.cssClasses.origin);
1122
+ var handle = addNodeTo(origin, options.cssClasses.handle);
1123
+
1124
+ addNodeTo(handle, options.cssClasses.touchArea);
1125
+
1126
+ handle.setAttribute("data-handle", handleNumber);
1127
+
1128
+ if (options.keyboardSupport) {
1129
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
1130
+ // 0 = focusable and reachable
1131
+ handle.setAttribute("tabindex", "0");
1132
+ handle.addEventListener("keydown", function(event) {
1133
+ return eventKeydown(event, handleNumber);
1134
+ });
1135
+ }
1136
+
1137
+ handle.setAttribute("role", "slider");
1138
+ handle.setAttribute("aria-orientation", options.ort ? "vertical" : "horizontal");
1139
+
1140
+ if (handleNumber === 0) {
1141
+ addClass(handle, options.cssClasses.handleLower);
1142
+ } else if (handleNumber === options.handles - 1) {
1143
+ addClass(handle, options.cssClasses.handleUpper);
1144
+ }
1145
+
1146
+ return origin;
1147
+ }
1148
+
1149
+ // Insert nodes for connect elements
1150
+ function addConnect(base, add) {
1151
+ if (!add) {
1152
+ return false;
1153
+ }
1154
+
1155
+ return addNodeTo(base, options.cssClasses.connect);
1156
+ }
1157
+
1158
+ // Add handles to the slider base.
1159
+ function addElements(connectOptions, base) {
1160
+ var connectBase = addNodeTo(base, options.cssClasses.connects);
1161
+
1162
+ scope_Handles = [];
1163
+ scope_Connects = [];
1164
+
1165
+ scope_Connects.push(addConnect(connectBase, connectOptions[0]));
1166
+
1167
+ // [::::O====O====O====]
1168
+ // connectOptions = [0, 1, 1, 1]
1169
+
1170
+ for (var i = 0; i < options.handles; i++) {
1171
+ // Keep a list of all added handles.
1172
+ scope_Handles.push(addOrigin(base, i));
1173
+ scope_HandleNumbers[i] = i;
1174
+ scope_Connects.push(addConnect(connectBase, connectOptions[i + 1]));
1175
+ }
1176
+ }
1177
+
1178
+ // Initialize a single slider.
1179
+ function addSlider(addTarget) {
1180
+ // Apply classes and data to the target.
1181
+ addClass(addTarget, options.cssClasses.target);
1182
+
1183
+ if (options.dir === 0) {
1184
+ addClass(addTarget, options.cssClasses.ltr);
1185
+ } else {
1186
+ addClass(addTarget, options.cssClasses.rtl);
1187
+ }
1188
+
1189
+ if (options.ort === 0) {
1190
+ addClass(addTarget, options.cssClasses.horizontal);
1191
+ } else {
1192
+ addClass(addTarget, options.cssClasses.vertical);
1193
+ }
1194
+
1195
+ var textDirection = getComputedStyle(addTarget).direction;
1196
+
1197
+ if (textDirection === "rtl") {
1198
+ addClass(addTarget, options.cssClasses.textDirectionRtl);
1199
+ } else {
1200
+ addClass(addTarget, options.cssClasses.textDirectionLtr);
1201
+ }
1202
+
1203
+ return addNodeTo(addTarget, options.cssClasses.base);
1204
+ }
1205
+
1206
+ function addTooltip(handle, handleNumber) {
1207
+ if (!options.tooltips[handleNumber]) {
1208
+ return false;
1209
+ }
1210
+
1211
+ return addNodeTo(handle.firstChild, options.cssClasses.tooltip);
1212
+ }
1213
+
1214
+ function isSliderDisabled() {
1215
+ return scope_Target.hasAttribute("disabled");
1216
+ }
1217
+
1218
+ // Disable the slider dragging if any handle is disabled
1219
+ function isHandleDisabled(handleNumber) {
1220
+ var handleOrigin = scope_Handles[handleNumber];
1221
+ return handleOrigin.hasAttribute("disabled");
1222
+ }
1223
+
1224
+ function removeTooltips() {
1225
+ if (scope_Tooltips) {
1226
+ removeEvent("update.tooltips");
1227
+ scope_Tooltips.forEach(function(tooltip) {
1228
+ if (tooltip) {
1229
+ removeElement(tooltip);
1230
+ }
1231
+ });
1232
+ scope_Tooltips = null;
1233
+ }
1234
+ }
1235
+
1236
+ // The tooltips option is a shorthand for using the 'update' event.
1237
+ function tooltips() {
1238
+ removeTooltips();
1239
+
1240
+ // Tooltips are added with options.tooltips in original order.
1241
+ scope_Tooltips = scope_Handles.map(addTooltip);
1242
+
1243
+ bindEvent("update.tooltips", function(values, handleNumber, unencoded) {
1244
+ if (!scope_Tooltips[handleNumber]) {
1245
+ return;
1246
+ }
1247
+
1248
+ var formattedValue = values[handleNumber];
1249
+
1250
+ if (options.tooltips[handleNumber] !== true) {
1251
+ formattedValue = options.tooltips[handleNumber].to(unencoded[handleNumber]);
1252
+ }
1253
+
1254
+ scope_Tooltips[handleNumber].innerHTML = formattedValue;
1255
+ });
1256
+ }
1257
+
1258
+ function aria() {
1259
+ bindEvent("update", function(values, handleNumber, unencoded, tap, positions) {
1260
+ // Update Aria Values for all handles, as a change in one changes min and max values for the next.
1261
+ scope_HandleNumbers.forEach(function(index) {
1262
+ var handle = scope_Handles[index];
1263
+
1264
+ var min = checkHandlePosition(scope_Locations, index, 0, true, true, true);
1265
+ var max = checkHandlePosition(scope_Locations, index, 100, true, true, true);
1266
+
1267
+ var now = positions[index];
1268
+
1269
+ // Formatted value for display
1270
+ var text = options.ariaFormat.to(unencoded[index]);
1271
+
1272
+ // Map to slider range values
1273
+ min = scope_Spectrum.fromStepping(min).toFixed(1);
1274
+ max = scope_Spectrum.fromStepping(max).toFixed(1);
1275
+ now = scope_Spectrum.fromStepping(now).toFixed(1);
1276
+
1277
+ handle.children[0].setAttribute("aria-valuemin", min);
1278
+ handle.children[0].setAttribute("aria-valuemax", max);
1279
+ handle.children[0].setAttribute("aria-valuenow", now);
1280
+ handle.children[0].setAttribute("aria-valuetext", text);
1281
+ });
1282
+ });
1283
+ }
1284
+
1285
+ function getGroup(mode, values, stepped) {
1286
+ // Use the range.
1287
+ if (mode === "range" || mode === "steps") {
1288
+ return scope_Spectrum.xVal;
1289
+ }
1290
+
1291
+ if (mode === "count") {
1292
+ if (values < 2) {
1293
+ throw new Error("noUiSlider (" + VERSION + "): 'values' (>= 2) required for mode 'count'.");
1294
+ }
1295
+
1296
+ // Divide 0 - 100 in 'count' parts.
1297
+ var interval = values - 1;
1298
+ var spread = 100 / interval;
1299
+
1300
+ values = [];
1301
+
1302
+ // List these parts and have them handled as 'positions'.
1303
+ while (interval--) {
1304
+ values[interval] = interval * spread;
1305
+ }
1306
+
1307
+ values.push(100);
1308
+
1309
+ mode = "positions";
1310
+ }
1311
+
1312
+ if (mode === "positions") {
1313
+ // Map all percentages to on-range values.
1314
+ return values.map(function(value) {
1315
+ return scope_Spectrum.fromStepping(stepped ? scope_Spectrum.getStep(value) : value);
1316
+ });
1317
+ }
1318
+
1319
+ if (mode === "values") {
1320
+ // If the value must be stepped, it needs to be converted to a percentage first.
1321
+ if (stepped) {
1322
+ return values.map(function(value) {
1323
+ // Convert to percentage, apply step, return to value.
1324
+ return scope_Spectrum.fromStepping(scope_Spectrum.getStep(scope_Spectrum.toStepping(value)));
1325
+ });
1326
+ }
1327
+
1328
+ // Otherwise, we can simply use the values.
1329
+ return values;
1330
+ }
1331
+ }
1332
+
1333
+ function generateSpread(density, mode, group) {
1334
+ function safeIncrement(value, increment) {
1335
+ // Avoid floating point variance by dropping the smallest decimal places.
1336
+ return (value + increment).toFixed(7) / 1;
1337
+ }
1338
+
1339
+ var indexes = {};
1340
+ var firstInRange = scope_Spectrum.xVal[0];
1341
+ var lastInRange = scope_Spectrum.xVal[scope_Spectrum.xVal.length - 1];
1342
+ var ignoreFirst = false;
1343
+ var ignoreLast = false;
1344
+ var prevPct = 0;
1345
+
1346
+ // Create a copy of the group, sort it and filter away all duplicates.
1347
+ group = unique(
1348
+ group.slice().sort(function(a, b) {
1349
+ return a - b;
1350
+ })
1351
+ );
1352
+
1353
+ // Make sure the range starts with the first element.
1354
+ if (group[0] !== firstInRange) {
1355
+ group.unshift(firstInRange);
1356
+ ignoreFirst = true;
1357
+ }
1358
+
1359
+ // Likewise for the last one.
1360
+ if (group[group.length - 1] !== lastInRange) {
1361
+ group.push(lastInRange);
1362
+ ignoreLast = true;
1363
+ }
1364
+
1365
+ group.forEach(function(current, index) {
1366
+ // Get the current step and the lower + upper positions.
1367
+ var step;
1368
+ var i;
1369
+ var q;
1370
+ var low = current;
1371
+ var high = group[index + 1];
1372
+ var newPct;
1373
+ var pctDifference;
1374
+ var pctPos;
1375
+ var type;
1376
+ var steps;
1377
+ var realSteps;
1378
+ var stepSize;
1379
+ var isSteps = mode === "steps";
1380
+
1381
+ // When using 'steps' mode, use the provided steps.
1382
+ // Otherwise, we'll step on to the next subrange.
1383
+ if (isSteps) {
1384
+ step = scope_Spectrum.xNumSteps[index];
1385
+ }
1386
+
1387
+ // Default to a 'full' step.
1388
+ if (!step) {
1389
+ step = high - low;
1390
+ }
1391
+
1392
+ // Low can be 0, so test for false. If high is undefined,
1393
+ // we are at the last subrange. Index 0 is already handled.
1394
+ if (low === false || high === undefined) {
1395
+ return;
1396
+ }
1397
+
1398
+ // Make sure step isn't 0, which would cause an infinite loop (#654)
1399
+ step = Math.max(step, 0.0000001);
1400
+
1401
+ // Find all steps in the subrange.
1402
+ for (i = low; i <= high; i = safeIncrement(i, step)) {
1403
+ // Get the percentage value for the current step,
1404
+ // calculate the size for the subrange.
1405
+ newPct = scope_Spectrum.toStepping(i);
1406
+ pctDifference = newPct - prevPct;
1407
+
1408
+ steps = pctDifference / density;
1409
+ realSteps = Math.round(steps);
1410
+
1411
+ // This ratio represents the amount of percentage-space a point indicates.
1412
+ // For a density 1 the points/percentage = 1. For density 2, that percentage needs to be re-divided.
1413
+ // Round the percentage offset to an even number, then divide by two
1414
+ // to spread the offset on both sides of the range.
1415
+ stepSize = pctDifference / realSteps;
1416
+
1417
+ // Divide all points evenly, adding the correct number to this subrange.
1418
+ // Run up to <= so that 100% gets a point, event if ignoreLast is set.
1419
+ for (q = 1; q <= realSteps; q += 1) {
1420
+ // The ratio between the rounded value and the actual size might be ~1% off.
1421
+ // Correct the percentage offset by the number of points
1422
+ // per subrange. density = 1 will result in 100 points on the
1423
+ // full range, 2 for 50, 4 for 25, etc.
1424
+ pctPos = prevPct + q * stepSize;
1425
+ indexes[pctPos.toFixed(5)] = [scope_Spectrum.fromStepping(pctPos), 0];
1426
+ }
1427
+
1428
+ // Determine the point type.
1429
+ type = group.indexOf(i) > -1 ? PIPS_LARGE_VALUE : isSteps ? PIPS_SMALL_VALUE : PIPS_NO_VALUE;
1430
+
1431
+ // Enforce the 'ignoreFirst' option by overwriting the type for 0.
1432
+ if (!index && ignoreFirst && i !== high) {
1433
+ type = 0;
1434
+ }
1435
+
1436
+ if (!(i === high && ignoreLast)) {
1437
+ // Mark the 'type' of this point. 0 = plain, 1 = real value, 2 = step value.
1438
+ indexes[newPct.toFixed(5)] = [i, type];
1439
+ }
1440
+
1441
+ // Update the percentage count.
1442
+ prevPct = newPct;
1443
+ }
1444
+ });
1445
+
1446
+ return indexes;
1447
+ }
1448
+
1449
+ function addMarking(spread, filterFunc, formatter) {
1450
+ var element = scope_Document.createElement("div");
1451
+
1452
+ var valueSizeClasses = [];
1453
+ valueSizeClasses[PIPS_NO_VALUE] = options.cssClasses.valueNormal;
1454
+ valueSizeClasses[PIPS_LARGE_VALUE] = options.cssClasses.valueLarge;
1455
+ valueSizeClasses[PIPS_SMALL_VALUE] = options.cssClasses.valueSub;
1456
+
1457
+ var markerSizeClasses = [];
1458
+ markerSizeClasses[PIPS_NO_VALUE] = options.cssClasses.markerNormal;
1459
+ markerSizeClasses[PIPS_LARGE_VALUE] = options.cssClasses.markerLarge;
1460
+ markerSizeClasses[PIPS_SMALL_VALUE] = options.cssClasses.markerSub;
1461
+
1462
+ var valueOrientationClasses = [options.cssClasses.valueHorizontal, options.cssClasses.valueVertical];
1463
+ var markerOrientationClasses = [options.cssClasses.markerHorizontal, options.cssClasses.markerVertical];
1464
+
1465
+ addClass(element, options.cssClasses.pips);
1466
+ addClass(element, options.ort === 0 ? options.cssClasses.pipsHorizontal : options.cssClasses.pipsVertical);
1467
+
1468
+ function getClasses(type, source) {
1469
+ var a = source === options.cssClasses.value;
1470
+ var orientationClasses = a ? valueOrientationClasses : markerOrientationClasses;
1471
+ var sizeClasses = a ? valueSizeClasses : markerSizeClasses;
1472
+
1473
+ return source + " " + orientationClasses[options.ort] + " " + sizeClasses[type];
1474
+ }
1475
+
1476
+ function addSpread(offset, value, type) {
1477
+ // Apply the filter function, if it is set.
1478
+ type = filterFunc ? filterFunc(value, type) : type;
1479
+
1480
+ if (type === PIPS_NONE) {
1481
+ return;
1482
+ }
1483
+
1484
+ // Add a marker for every point
1485
+ var node = addNodeTo(element, false);
1486
+ node.className = getClasses(type, options.cssClasses.marker);
1487
+ node.style[options.style] = offset + "%";
1488
+
1489
+ // Values are only appended for points marked '1' or '2'.
1490
+ if (type > PIPS_NO_VALUE) {
1491
+ node = addNodeTo(element, false);
1492
+ node.className = getClasses(type, options.cssClasses.value);
1493
+ node.setAttribute("data-value", value);
1494
+ node.style[options.style] = offset + "%";
1495
+ node.innerHTML = formatter.to(value);
1496
+ }
1497
+ }
1498
+
1499
+ // Append all points.
1500
+ Object.keys(spread).forEach(function(offset) {
1501
+ addSpread(offset, spread[offset][0], spread[offset][1]);
1502
+ });
1503
+
1504
+ return element;
1505
+ }
1506
+
1507
+ function removePips() {
1508
+ if (scope_Pips) {
1509
+ removeElement(scope_Pips);
1510
+ scope_Pips = null;
1511
+ }
1512
+ }
1513
+
1514
+ function pips(grid) {
1515
+ // Fix #669
1516
+ removePips();
1517
+
1518
+ var mode = grid.mode;
1519
+ var density = grid.density || 1;
1520
+ var filter = grid.filter || false;
1521
+ var values = grid.values || false;
1522
+ var stepped = grid.stepped || false;
1523
+ var group = getGroup(mode, values, stepped);
1524
+ var spread = generateSpread(density, mode, group);
1525
+ var format = grid.format || {
1526
+ to: Math.round
1527
+ };
1528
+
1529
+ scope_Pips = scope_Target.appendChild(addMarking(spread, filter, format));
1530
+
1531
+ return scope_Pips;
1532
+ }
1533
+
1534
+ // Shorthand for base dimensions.
1535
+ function baseSize() {
1536
+ var rect = scope_Base.getBoundingClientRect();
1537
+ var alt = "offset" + ["Width", "Height"][options.ort];
1538
+ return options.ort === 0 ? rect.width || scope_Base[alt] : rect.height || scope_Base[alt];
1539
+ }
1540
+
1541
+ // Handler for attaching events trough a proxy.
1542
+ function attachEvent(events, element, callback, data) {
1543
+ // This function can be used to 'filter' events to the slider.
1544
+ // element is a node, not a nodeList
1545
+
1546
+ var method = function(e) {
1547
+ e = fixEvent(e, data.pageOffset, data.target || element);
1548
+
1549
+ // fixEvent returns false if this event has a different target
1550
+ // when handling (multi-) touch events;
1551
+ if (!e) {
1552
+ return false;
1553
+ }
1554
+
1555
+ // doNotReject is passed by all end events to make sure released touches
1556
+ // are not rejected, leaving the slider "stuck" to the cursor;
1557
+ if (isSliderDisabled() && !data.doNotReject) {
1558
+ return false;
1559
+ }
1560
+
1561
+ // Stop if an active 'tap' transition is taking place.
1562
+ if (hasClass(scope_Target, options.cssClasses.tap) && !data.doNotReject) {
1563
+ return false;
1564
+ }
1565
+
1566
+ // Ignore right or middle clicks on start #454
1567
+ if (events === actions.start && e.buttons !== undefined && e.buttons > 1) {
1568
+ return false;
1569
+ }
1570
+
1571
+ // Ignore right or middle clicks on start #454
1572
+ if (data.hover && e.buttons) {
1573
+ return false;
1574
+ }
1575
+
1576
+ // 'supportsPassive' is only true if a browser also supports touch-action: none in CSS.
1577
+ // iOS safari does not, so it doesn't get to benefit from passive scrolling. iOS does support
1578
+ // touch-action: manipulation, but that allows panning, which breaks
1579
+ // sliders after zooming/on non-responsive pages.
1580
+ // See: https://bugs.webkit.org/show_bug.cgi?id=133112
1581
+ if (!supportsPassive) {
1582
+ e.preventDefault();
1583
+ }
1584
+
1585
+ e.calcPoint = e.points[options.ort];
1586
+
1587
+ // Call the event handler with the event [ and additional data ].
1588
+ callback(e, data);
1589
+ };
1590
+
1591
+ var methods = [];
1592
+
1593
+ // Bind a closure on the target for every event type.
1594
+ events.split(" ").forEach(function(eventName) {
1595
+ element.addEventListener(eventName, method, supportsPassive ? { passive: true } : false);
1596
+ methods.push([eventName, method]);
1597
+ });
1598
+
1599
+ return methods;
1600
+ }
1601
+
1602
+ // Provide a clean event with standardized offset values.
1603
+ function fixEvent(e, pageOffset, eventTarget) {
1604
+ // Filter the event to register the type, which can be
1605
+ // touch, mouse or pointer. Offset changes need to be
1606
+ // made on an event specific basis.
1607
+ var touch = e.type.indexOf("touch") === 0;
1608
+ var mouse = e.type.indexOf("mouse") === 0;
1609
+ var pointer = e.type.indexOf("pointer") === 0;
1610
+
1611
+ var x;
1612
+ var y;
1613
+
1614
+ // IE10 implemented pointer events with a prefix;
1615
+ if (e.type.indexOf("MSPointer") === 0) {
1616
+ pointer = true;
1617
+ }
1618
+
1619
+ // The only thing one handle should be concerned about is the touches that originated on top of it.
1620
+ if (touch) {
1621
+ // Returns true if a touch originated on the target.
1622
+ var isTouchOnTarget = function(checkTouch) {
1623
+ return (
1624
+ checkTouch.target === eventTarget ||
1625
+ eventTarget.contains(checkTouch.target) ||
1626
+ (checkTouch.target.shadowRoot && checkTouch.target.shadowRoot.contains(eventTarget))
1627
+ );
1628
+ };
1629
+
1630
+ // In the case of touchstart events, we need to make sure there is still no more than one
1631
+ // touch on the target so we look amongst all touches.
1632
+ if (e.type === "touchstart") {
1633
+ var targetTouches = Array.prototype.filter.call(e.touches, isTouchOnTarget);
1634
+
1635
+ // Do not support more than one touch per handle.
1636
+ if (targetTouches.length > 1) {
1637
+ return false;
1638
+ }
1639
+
1640
+ x = targetTouches[0].pageX;
1641
+ y = targetTouches[0].pageY;
1642
+ } else {
1643
+ // In the other cases, find on changedTouches is enough.
1644
+ var targetTouch = Array.prototype.find.call(e.changedTouches, isTouchOnTarget);
1645
+
1646
+ // Cancel if the target touch has not moved.
1647
+ if (!targetTouch) {
1648
+ return false;
1649
+ }
1650
+
1651
+ x = targetTouch.pageX;
1652
+ y = targetTouch.pageY;
1653
+ }
1654
+ }
1655
+
1656
+ pageOffset = pageOffset || getPageOffset(scope_Document);
1657
+
1658
+ if (mouse || pointer) {
1659
+ x = e.clientX + pageOffset.x;
1660
+ y = e.clientY + pageOffset.y;
1661
+ }
1662
+
1663
+ e.pageOffset = pageOffset;
1664
+ e.points = [x, y];
1665
+ e.cursor = mouse || pointer; // Fix #435
1666
+
1667
+ return e;
1668
+ }
1669
+
1670
+ // Translate a coordinate in the document to a percentage on the slider
1671
+ function calcPointToPercentage(calcPoint) {
1672
+ var location = calcPoint - offset(scope_Base, options.ort);
1673
+ var proposal = (location * 100) / baseSize();
1674
+
1675
+ // Clamp proposal between 0% and 100%
1676
+ // Out-of-bound coordinates may occur when .noUi-base pseudo-elements
1677
+ // are used (e.g. contained handles feature)
1678
+ proposal = limit(proposal);
1679
+
1680
+ return options.dir ? 100 - proposal : proposal;
1681
+ }
1682
+
1683
+ // Find handle closest to a certain percentage on the slider
1684
+ function getClosestHandle(clickedPosition) {
1685
+ var smallestDifference = 100;
1686
+ var handleNumber = false;
1687
+
1688
+ scope_Handles.forEach(function(handle, index) {
1689
+ // Disabled handles are ignored
1690
+ if (isHandleDisabled(index)) {
1691
+ return;
1692
+ }
1693
+
1694
+ var handlePosition = scope_Locations[index];
1695
+ var differenceWithThisHandle = Math.abs(handlePosition - clickedPosition);
1696
+
1697
+ // Initial state
1698
+ var clickAtEdge = differenceWithThisHandle === 100 && smallestDifference === 100;
1699
+
1700
+ // Difference with this handle is smaller than the previously checked handle
1701
+ var isCloser = differenceWithThisHandle < smallestDifference;
1702
+ var isCloserAfter = differenceWithThisHandle <= smallestDifference && clickedPosition > handlePosition;
1703
+
1704
+ if (isCloser || isCloserAfter || clickAtEdge) {
1705
+ handleNumber = index;
1706
+ smallestDifference = differenceWithThisHandle;
1707
+ }
1708
+ });
1709
+
1710
+ return handleNumber;
1711
+ }
1712
+
1713
+ // Fire 'end' when a mouse or pen leaves the document.
1714
+ function documentLeave(event, data) {
1715
+ if (event.type === "mouseout" && event.target.nodeName === "HTML" && event.relatedTarget === null) {
1716
+ eventEnd(event, data);
1717
+ }
1718
+ }
1719
+
1720
+ // Handle movement on document for handle and range drag.
1721
+ function eventMove(event, data) {
1722
+ // Fix #498
1723
+ // Check value of .buttons in 'start' to work around a bug in IE10 mobile (data.buttonsProperty).
1724
+ // https://connect.microsoft.com/IE/feedback/details/927005/mobile-ie10-windows-phone-buttons-property-of-pointermove-event-always-zero
1725
+ // IE9 has .buttons and .which zero on mousemove.
1726
+ // Firefox breaks the spec MDN defines.
1727
+ if (navigator.appVersion.indexOf("MSIE 9") === -1 && event.buttons === 0 && data.buttonsProperty !== 0) {
1728
+ return eventEnd(event, data);
1729
+ }
1730
+
1731
+ // Check if we are moving up or down
1732
+ var movement = (options.dir ? -1 : 1) * (event.calcPoint - data.startCalcPoint);
1733
+
1734
+ // Convert the movement into a percentage of the slider width/height
1735
+ var proposal = (movement * 100) / data.baseSize;
1736
+
1737
+ moveHandles(movement > 0, proposal, data.locations, data.handleNumbers);
1738
+ }
1739
+
1740
+ // Unbind move events on document, call callbacks.
1741
+ function eventEnd(event, data) {
1742
+ // The handle is no longer active, so remove the class.
1743
+ if (data.handle) {
1744
+ removeClass(data.handle, options.cssClasses.active);
1745
+ scope_ActiveHandlesCount -= 1;
1746
+ }
1747
+
1748
+ // Unbind the move and end events, which are added on 'start'.
1749
+ data.listeners.forEach(function(c) {
1750
+ scope_DocumentElement.removeEventListener(c[0], c[1]);
1751
+ });
1752
+
1753
+ if (scope_ActiveHandlesCount === 0) {
1754
+ // Remove dragging class.
1755
+ removeClass(scope_Target, options.cssClasses.drag);
1756
+ setZindex();
1757
+
1758
+ // Remove cursor styles and text-selection events bound to the body.
1759
+ if (event.cursor) {
1760
+ scope_Body.style.cursor = "";
1761
+ scope_Body.removeEventListener("selectstart", preventDefault);
1762
+ }
1763
+ }
1764
+
1765
+ data.handleNumbers.forEach(function(handleNumber) {
1766
+ fireEvent("change", handleNumber);
1767
+ fireEvent("set", handleNumber);
1768
+ fireEvent("end", handleNumber);
1769
+ });
1770
+ }
1771
+
1772
+ // Bind move events on document.
1773
+ function eventStart(event, data) {
1774
+ // Ignore event if any handle is disabled
1775
+ if (data.handleNumbers.some(isHandleDisabled)) {
1776
+ return false;
1777
+ }
1778
+
1779
+ var handle;
1780
+
1781
+ if (data.handleNumbers.length === 1) {
1782
+ var handleOrigin = scope_Handles[data.handleNumbers[0]];
1783
+
1784
+ handle = handleOrigin.children[0];
1785
+ scope_ActiveHandlesCount += 1;
1786
+
1787
+ // Mark the handle as 'active' so it can be styled.
1788
+ addClass(handle, options.cssClasses.active);
1789
+ }
1790
+
1791
+ // A drag should never propagate up to the 'tap' event.
1792
+ event.stopPropagation();
1793
+
1794
+ // Record the event listeners.
1795
+ var listeners = [];
1796
+
1797
+ // Attach the move and end events.
1798
+ var moveEvent = attachEvent(actions.move, scope_DocumentElement, eventMove, {
1799
+ // The event target has changed so we need to propagate the original one so that we keep
1800
+ // relying on it to extract target touches.
1801
+ target: event.target,
1802
+ handle: handle,
1803
+ listeners: listeners,
1804
+ startCalcPoint: event.calcPoint,
1805
+ baseSize: baseSize(),
1806
+ pageOffset: event.pageOffset,
1807
+ handleNumbers: data.handleNumbers,
1808
+ buttonsProperty: event.buttons,
1809
+ locations: scope_Locations.slice()
1810
+ });
1811
+
1812
+ var endEvent = attachEvent(actions.end, scope_DocumentElement, eventEnd, {
1813
+ target: event.target,
1814
+ handle: handle,
1815
+ listeners: listeners,
1816
+ doNotReject: true,
1817
+ handleNumbers: data.handleNumbers
1818
+ });
1819
+
1820
+ var outEvent = attachEvent("mouseout", scope_DocumentElement, documentLeave, {
1821
+ target: event.target,
1822
+ handle: handle,
1823
+ listeners: listeners,
1824
+ doNotReject: true,
1825
+ handleNumbers: data.handleNumbers
1826
+ });
1827
+
1828
+ // We want to make sure we pushed the listeners in the listener list rather than creating
1829
+ // a new one as it has already been passed to the event handlers.
1830
+ listeners.push.apply(listeners, moveEvent.concat(endEvent, outEvent));
1831
+
1832
+ // Text selection isn't an issue on touch devices,
1833
+ // so adding cursor styles can be skipped.
1834
+ if (event.cursor) {
1835
+ // Prevent the 'I' cursor and extend the range-drag cursor.
1836
+ scope_Body.style.cursor = getComputedStyle(event.target).cursor;
1837
+
1838
+ // Mark the target with a dragging state.
1839
+ if (scope_Handles.length > 1) {
1840
+ addClass(scope_Target, options.cssClasses.drag);
1841
+ }
1842
+
1843
+ // Prevent text selection when dragging the handles.
1844
+ // In noUiSlider <= 9.2.0, this was handled by calling preventDefault on mouse/touch start/move,
1845
+ // which is scroll blocking. The selectstart event is supported by FireFox starting from version 52,
1846
+ // meaning the only holdout is iOS Safari. This doesn't matter: text selection isn't triggered there.
1847
+ // The 'cursor' flag is false.
1848
+ // See: http://caniuse.com/#search=selectstart
1849
+ scope_Body.addEventListener("selectstart", preventDefault, false);
1850
+ }
1851
+
1852
+ data.handleNumbers.forEach(function(handleNumber) {
1853
+ fireEvent("start", handleNumber);
1854
+ });
1855
+ }
1856
+
1857
+ // Move closest handle to tapped location.
1858
+ function eventTap(event) {
1859
+ // The tap event shouldn't propagate up
1860
+ event.stopPropagation();
1861
+
1862
+ var proposal = calcPointToPercentage(event.calcPoint);
1863
+ var handleNumber = getClosestHandle(proposal);
1864
+
1865
+ // Tackle the case that all handles are 'disabled'.
1866
+ if (handleNumber === false) {
1867
+ return false;
1868
+ }
1869
+
1870
+ // Flag the slider as it is now in a transitional state.
1871
+ // Transition takes a configurable amount of ms (default 300). Re-enable the slider after that.
1872
+ if (!options.events.snap) {
1873
+ addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration);
1874
+ }
1875
+
1876
+ setHandle(handleNumber, proposal, true, true);
1877
+
1878
+ setZindex();
1879
+
1880
+ fireEvent("slide", handleNumber, true);
1881
+ fireEvent("update", handleNumber, true);
1882
+ fireEvent("change", handleNumber, true);
1883
+ fireEvent("set", handleNumber, true);
1884
+
1885
+ if (options.events.snap) {
1886
+ eventStart(event, { handleNumbers: [handleNumber] });
1887
+ }
1888
+ }
1889
+
1890
+ // Fires a 'hover' event for a hovered mouse/pen position.
1891
+ function eventHover(event) {
1892
+ var proposal = calcPointToPercentage(event.calcPoint);
1893
+
1894
+ var to = scope_Spectrum.getStep(proposal);
1895
+ var value = scope_Spectrum.fromStepping(to);
1896
+
1897
+ Object.keys(scope_Events).forEach(function(targetEvent) {
1898
+ if ("hover" === targetEvent.split(".")[0]) {
1899
+ scope_Events[targetEvent].forEach(function(callback) {
1900
+ callback.call(scope_Self, value);
1901
+ });
1902
+ }
1903
+ });
1904
+ }
1905
+
1906
+ // Handles keydown on focused handles
1907
+ // Don't move the document when pressing arrow keys on focused handles
1908
+ function eventKeydown(event, handleNumber) {
1909
+ if (isSliderDisabled() || isHandleDisabled(handleNumber)) {
1910
+ return false;
1911
+ }
1912
+
1913
+ var horizontalKeys = ["Left", "Right"];
1914
+ var verticalKeys = ["Down", "Up"];
1915
+ var largeStepKeys = ["PageDown", "PageUp"];
1916
+ var edgeKeys = ["Home", "End"];
1917
+
1918
+ if (options.dir && !options.ort) {
1919
+ // On an right-to-left slider, the left and right keys act inverted
1920
+ horizontalKeys.reverse();
1921
+ } else if (options.ort && !options.dir) {
1922
+ // On a top-to-bottom slider, the up and down keys act inverted
1923
+ verticalKeys.reverse();
1924
+ largeStepKeys.reverse();
1925
+ }
1926
+
1927
+ // Strip "Arrow" for IE compatibility. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
1928
+ var key = event.key.replace("Arrow", "");
1929
+
1930
+ var isLargeDown = key === largeStepKeys[0];
1931
+ var isLargeUp = key === largeStepKeys[1];
1932
+ var isDown = key === verticalKeys[0] || key === horizontalKeys[0] || isLargeDown;
1933
+ var isUp = key === verticalKeys[1] || key === horizontalKeys[1] || isLargeUp;
1934
+ var isMin = key === edgeKeys[0];
1935
+ var isMax = key === edgeKeys[1];
1936
+
1937
+ if (!isDown && !isUp && !isMin && !isMax) {
1938
+ return true;
1939
+ }
1940
+
1941
+ event.preventDefault();
1942
+
1943
+ var to;
1944
+
1945
+ if (isUp || isDown) {
1946
+ var multiplier = 5;
1947
+ var direction = isDown ? 0 : 1;
1948
+ var steps = getNextStepsForHandle(handleNumber);
1949
+ var step = steps[direction];
1950
+
1951
+ // At the edge of a slider, do nothing
1952
+ if (step === null) {
1953
+ return false;
1954
+ }
1955
+
1956
+ // No step set, use the default of 10% of the sub-range
1957
+ if (step === false) {
1958
+ step = scope_Spectrum.getDefaultStep(scope_Locations[handleNumber], isDown, 10);
1959
+ }
1960
+
1961
+ if (isLargeUp || isLargeDown) {
1962
+ step *= multiplier;
1963
+ }
1964
+
1965
+ // Step over zero-length ranges (#948);
1966
+ step = Math.max(step, 0.0000001);
1967
+
1968
+ // Decrement for down steps
1969
+ step = (isDown ? -1 : 1) * step;
1970
+
1971
+ to = scope_Values[handleNumber] + step;
1972
+ } else if (isMax) {
1973
+ // End key
1974
+ to = options.spectrum.xVal[options.spectrum.xVal.length - 1];
1975
+ } else {
1976
+ // Home key
1977
+ to = options.spectrum.xVal[0];
1978
+ }
1979
+
1980
+ setHandle(handleNumber, scope_Spectrum.toStepping(to), true, true);
1981
+
1982
+ fireEvent("slide", handleNumber);
1983
+ fireEvent("update", handleNumber);
1984
+ fireEvent("change", handleNumber);
1985
+ fireEvent("set", handleNumber);
1986
+
1987
+ return false;
1988
+ }
1989
+
1990
+ // Attach events to several slider parts.
1991
+ function bindSliderEvents(behaviour) {
1992
+ // Attach the standard drag event to the handles.
1993
+ if (!behaviour.fixed) {
1994
+ scope_Handles.forEach(function(handle, index) {
1995
+ // These events are only bound to the visual handle
1996
+ // element, not the 'real' origin element.
1997
+ attachEvent(actions.start, handle.children[0], eventStart, {
1998
+ handleNumbers: [index]
1999
+ });
2000
+ });
2001
+ }
2002
+
2003
+ // Attach the tap event to the slider base.
2004
+ if (behaviour.tap) {
2005
+ attachEvent(actions.start, scope_Base, eventTap, {});
2006
+ }
2007
+
2008
+ // Fire hover events
2009
+ if (behaviour.hover) {
2010
+ attachEvent(actions.move, scope_Base, eventHover, {
2011
+ hover: true
2012
+ });
2013
+ }
2014
+
2015
+ // Make the range draggable.
2016
+ if (behaviour.drag) {
2017
+ scope_Connects.forEach(function(connect, index) {
2018
+ if (connect === false || index === 0 || index === scope_Connects.length - 1) {
2019
+ return;
2020
+ }
2021
+
2022
+ var handleBefore = scope_Handles[index - 1];
2023
+ var handleAfter = scope_Handles[index];
2024
+ var eventHolders = [connect];
2025
+
2026
+ addClass(connect, options.cssClasses.draggable);
2027
+
2028
+ // When the range is fixed, the entire range can
2029
+ // be dragged by the handles. The handle in the first
2030
+ // origin will propagate the start event upward,
2031
+ // but it needs to be bound manually on the other.
2032
+ if (behaviour.fixed) {
2033
+ eventHolders.push(handleBefore.children[0]);
2034
+ eventHolders.push(handleAfter.children[0]);
2035
+ }
2036
+
2037
+ eventHolders.forEach(function(eventHolder) {
2038
+ attachEvent(actions.start, eventHolder, eventStart, {
2039
+ handles: [handleBefore, handleAfter],
2040
+ handleNumbers: [index - 1, index]
2041
+ });
2042
+ });
2043
+ });
2044
+ }
2045
+ }
2046
+
2047
+ // Attach an event to this slider, possibly including a namespace
2048
+ function bindEvent(namespacedEvent, callback) {
2049
+ scope_Events[namespacedEvent] = scope_Events[namespacedEvent] || [];
2050
+ scope_Events[namespacedEvent].push(callback);
2051
+
2052
+ // If the event bound is 'update,' fire it immediately for all handles.
2053
+ if (namespacedEvent.split(".")[0] === "update") {
2054
+ scope_Handles.forEach(function(a, index) {
2055
+ fireEvent("update", index);
2056
+ });
2057
+ }
2058
+ }
2059
+
2060
+ // Undo attachment of event
2061
+ function removeEvent(namespacedEvent) {
2062
+ var event = namespacedEvent && namespacedEvent.split(".")[0];
2063
+ var namespace = event && namespacedEvent.substring(event.length);
2064
+
2065
+ Object.keys(scope_Events).forEach(function(bind) {
2066
+ var tEvent = bind.split(".")[0];
2067
+ var tNamespace = bind.substring(tEvent.length);
2068
+
2069
+ if ((!event || event === tEvent) && (!namespace || namespace === tNamespace)) {
2070
+ delete scope_Events[bind];
2071
+ }
2072
+ });
2073
+ }
2074
+
2075
+ // External event handling
2076
+ function fireEvent(eventName, handleNumber, tap) {
2077
+ Object.keys(scope_Events).forEach(function(targetEvent) {
2078
+ var eventType = targetEvent.split(".")[0];
2079
+
2080
+ if (eventName === eventType) {
2081
+ scope_Events[targetEvent].forEach(function(callback) {
2082
+ callback.call(
2083
+ // Use the slider public API as the scope ('this')
2084
+ scope_Self,
2085
+ // Return values as array, so arg_1[arg_2] is always valid.
2086
+ scope_Values.map(options.format.to),
2087
+ // Handle index, 0 or 1
2088
+ handleNumber,
2089
+ // Un-formatted slider values
2090
+ scope_Values.slice(),
2091
+ // Event is fired by tap, true or false
2092
+ tap || false,
2093
+ // Left offset of the handle, in relation to the slider
2094
+ scope_Locations.slice(),
2095
+ // add the slider public API to an accessible parameter when this is unavailable
2096
+ scope_Self
2097
+ );
2098
+ });
2099
+ }
2100
+ });
2101
+ }
2102
+
2103
+ // Split out the handle positioning logic so the Move event can use it, too
2104
+ function checkHandlePosition(reference, handleNumber, to, lookBackward, lookForward, getValue) {
2105
+ var distance;
2106
+
2107
+ // For sliders with multiple handles, limit movement to the other handle.
2108
+ // Apply the margin option by adding it to the handle positions.
2109
+ if (scope_Handles.length > 1 && !options.events.unconstrained) {
2110
+ if (lookBackward && handleNumber > 0) {
2111
+ distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber - 1], options.margin, 0);
2112
+ to = Math.max(to, distance);
2113
+ }
2114
+
2115
+ if (lookForward && handleNumber < scope_Handles.length - 1) {
2116
+ distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber + 1], options.margin, 1);
2117
+ to = Math.min(to, distance);
2118
+ }
2119
+ }
2120
+
2121
+ // The limit option has the opposite effect, limiting handles to a
2122
+ // maximum distance from another. Limit must be > 0, as otherwise
2123
+ // handles would be unmovable.
2124
+ if (scope_Handles.length > 1 && options.limit) {
2125
+ if (lookBackward && handleNumber > 0) {
2126
+ distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber - 1], options.limit, 0);
2127
+ to = Math.min(to, distance);
2128
+ }
2129
+
2130
+ if (lookForward && handleNumber < scope_Handles.length - 1) {
2131
+ distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber + 1], options.limit, 1);
2132
+ to = Math.max(to, distance);
2133
+ }
2134
+ }
2135
+
2136
+ // The padding option keeps the handles a certain distance from the
2137
+ // edges of the slider. Padding must be > 0.
2138
+ if (options.padding) {
2139
+ if (handleNumber === 0) {
2140
+ distance = scope_Spectrum.getAbsoluteDistance(0, options.padding[0], 0);
2141
+ to = Math.max(to, distance);
2142
+ }
2143
+
2144
+ if (handleNumber === scope_Handles.length - 1) {
2145
+ distance = scope_Spectrum.getAbsoluteDistance(100, options.padding[1], 1);
2146
+ to = Math.min(to, distance);
2147
+ }
2148
+ }
2149
+
2150
+ to = scope_Spectrum.getStep(to);
2151
+
2152
+ // Limit percentage to the 0 - 100 range
2153
+ to = limit(to);
2154
+
2155
+ // Return false if handle can't move
2156
+ if (to === reference[handleNumber] && !getValue) {
2157
+ return false;
2158
+ }
2159
+
2160
+ return to;
2161
+ }
2162
+
2163
+ // Uses slider orientation to create CSS rules. a = base value;
2164
+ function inRuleOrder(v, a) {
2165
+ var o = options.ort;
2166
+ return (o ? a : v) + ", " + (o ? v : a);
2167
+ }
2168
+
2169
+ // Moves handle(s) by a percentage
2170
+ // (bool, % to move, [% where handle started, ...], [index in scope_Handles, ...])
2171
+ function moveHandles(upward, proposal, locations, handleNumbers) {
2172
+ var proposals = locations.slice();
2173
+
2174
+ var b = [!upward, upward];
2175
+ var f = [upward, !upward];
2176
+
2177
+ // Copy handleNumbers so we don't change the dataset
2178
+ handleNumbers = handleNumbers.slice();
2179
+
2180
+ // Check to see which handle is 'leading'.
2181
+ // If that one can't move the second can't either.
2182
+ if (upward) {
2183
+ handleNumbers.reverse();
2184
+ }
2185
+
2186
+ // Step 1: get the maximum percentage that any of the handles can move
2187
+ if (handleNumbers.length > 1) {
2188
+ handleNumbers.forEach(function(handleNumber, o) {
2189
+ var to = checkHandlePosition(
2190
+ proposals,
2191
+ handleNumber,
2192
+ proposals[handleNumber] + proposal,
2193
+ b[o],
2194
+ f[o],
2195
+ false
2196
+ );
2197
+
2198
+ // Stop if one of the handles can't move.
2199
+ if (to === false) {
2200
+ proposal = 0;
2201
+ } else {
2202
+ proposal = to - proposals[handleNumber];
2203
+ proposals[handleNumber] = to;
2204
+ }
2205
+ });
2206
+ }
2207
+
2208
+ // If using one handle, check backward AND forward
2209
+ else {
2210
+ b = f = [true];
2211
+ }
2212
+
2213
+ var state = false;
2214
+
2215
+ // Step 2: Try to set the handles with the found percentage
2216
+ handleNumbers.forEach(function(handleNumber, o) {
2217
+ state = setHandle(handleNumber, locations[handleNumber] + proposal, b[o], f[o]) || state;
2218
+ });
2219
+
2220
+ // Step 3: If a handle moved, fire events
2221
+ if (state) {
2222
+ handleNumbers.forEach(function(handleNumber) {
2223
+ fireEvent("update", handleNumber);
2224
+ fireEvent("slide", handleNumber);
2225
+ });
2226
+ }
2227
+ }
2228
+
2229
+ // Takes a base value and an offset. This offset is used for the connect bar size.
2230
+ // In the initial design for this feature, the origin element was 1% wide.
2231
+ // Unfortunately, a rounding bug in Chrome makes it impossible to implement this feature
2232
+ // in this manner: https://bugs.chromium.org/p/chromium/issues/detail?id=798223
2233
+ function transformDirection(a, b) {
2234
+ return options.dir ? 100 - a - b : a;
2235
+ }
2236
+
2237
+ // Updates scope_Locations and scope_Values, updates visual state
2238
+ function updateHandlePosition(handleNumber, to) {
2239
+ // Update locations.
2240
+ scope_Locations[handleNumber] = to;
2241
+
2242
+ // Convert the value to the slider stepping/range.
2243
+ scope_Values[handleNumber] = scope_Spectrum.fromStepping(to);
2244
+
2245
+ var translation = 10 * (transformDirection(to, 0) - scope_DirOffset);
2246
+ var translateRule = "translate(" + inRuleOrder(translation + "%", "0") + ")";
2247
+
2248
+ scope_Handles[handleNumber].style[options.transformRule] = translateRule;
2249
+
2250
+ updateConnect(handleNumber);
2251
+ updateConnect(handleNumber + 1);
2252
+ }
2253
+
2254
+ // Handles before the slider middle are stacked later = higher,
2255
+ // Handles after the middle later is lower
2256
+ // [[7] [8] .......... | .......... [5] [4]
2257
+ function setZindex() {
2258
+ scope_HandleNumbers.forEach(function(handleNumber) {
2259
+ var dir = scope_Locations[handleNumber] > 50 ? -1 : 1;
2260
+ var zIndex = 3 + (scope_Handles.length + dir * handleNumber);
2261
+ scope_Handles[handleNumber].style.zIndex = zIndex;
2262
+ });
2263
+ }
2264
+
2265
+ // Test suggested values and apply margin, step.
2266
+ function setHandle(handleNumber, to, lookBackward, lookForward) {
2267
+ to = checkHandlePosition(scope_Locations, handleNumber, to, lookBackward, lookForward, false);
2268
+
2269
+ if (to === false) {
2270
+ return false;
2271
+ }
2272
+
2273
+ updateHandlePosition(handleNumber, to);
2274
+
2275
+ return true;
2276
+ }
2277
+
2278
+ // Updates style attribute for connect nodes
2279
+ function updateConnect(index) {
2280
+ // Skip connects set to false
2281
+ if (!scope_Connects[index]) {
2282
+ return;
2283
+ }
2284
+
2285
+ var l = 0;
2286
+ var h = 100;
2287
+
2288
+ if (index !== 0) {
2289
+ l = scope_Locations[index - 1];
2290
+ }
2291
+
2292
+ if (index !== scope_Connects.length - 1) {
2293
+ h = scope_Locations[index];
2294
+ }
2295
+
2296
+ // We use two rules:
2297
+ // 'translate' to change the left/top offset;
2298
+ // 'scale' to change the width of the element;
2299
+ // As the element has a width of 100%, a translation of 100% is equal to 100% of the parent (.noUi-base)
2300
+ var connectWidth = h - l;
2301
+ var translateRule = "translate(" + inRuleOrder(transformDirection(l, connectWidth) + "%", "0") + ")";
2302
+ var scaleRule = "scale(" + inRuleOrder(connectWidth / 100, "1") + ")";
2303
+
2304
+ scope_Connects[index].style[options.transformRule] = translateRule + " " + scaleRule;
2305
+ }
2306
+
2307
+ // Parses value passed to .set method. Returns current value if not parse-able.
2308
+ function resolveToValue(to, handleNumber) {
2309
+ // Setting with null indicates an 'ignore'.
2310
+ // Inputting 'false' is invalid.
2311
+ if (to === null || to === false || to === undefined) {
2312
+ return scope_Locations[handleNumber];
2313
+ }
2314
+
2315
+ // If a formatted number was passed, attempt to decode it.
2316
+ if (typeof to === "number") {
2317
+ to = String(to);
2318
+ }
2319
+
2320
+ to = options.format.from(to);
2321
+ to = scope_Spectrum.toStepping(to);
2322
+
2323
+ // If parsing the number failed, use the current value.
2324
+ if (to === false || isNaN(to)) {
2325
+ return scope_Locations[handleNumber];
2326
+ }
2327
+
2328
+ return to;
2329
+ }
2330
+
2331
+ // Set the slider value.
2332
+ function valueSet(input, fireSetEvent) {
2333
+ var values = asArray(input);
2334
+ var isInit = scope_Locations[0] === undefined;
2335
+
2336
+ // Event fires by default
2337
+ fireSetEvent = fireSetEvent === undefined ? true : !!fireSetEvent;
2338
+
2339
+ // Animation is optional.
2340
+ // Make sure the initial values were set before using animated placement.
2341
+ if (options.animate && !isInit) {
2342
+ addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration);
2343
+ }
2344
+
2345
+ // First pass, without lookAhead but with lookBackward. Values are set from left to right.
2346
+ scope_HandleNumbers.forEach(function(handleNumber) {
2347
+ setHandle(handleNumber, resolveToValue(values[handleNumber], handleNumber), true, false);
2348
+ });
2349
+
2350
+ var i = scope_HandleNumbers.length === 1 ? 0 : 1;
2351
+
2352
+ // Secondary passes. Now that all base values are set, apply constraints.
2353
+ // Iterate all handles to ensure constraints are applied for the entire slider (Issue #1009)
2354
+ for (; i < scope_HandleNumbers.length; ++i) {
2355
+ scope_HandleNumbers.forEach(function(handleNumber) {
2356
+ setHandle(handleNumber, scope_Locations[handleNumber], true, true);
2357
+ });
2358
+ }
2359
+
2360
+ setZindex();
2361
+
2362
+ scope_HandleNumbers.forEach(function(handleNumber) {
2363
+ fireEvent("update", handleNumber);
2364
+
2365
+ // Fire the event only for handles that received a new value, as per #579
2366
+ if (values[handleNumber] !== null && fireSetEvent) {
2367
+ fireEvent("set", handleNumber);
2368
+ }
2369
+ });
2370
+ }
2371
+
2372
+ // Reset slider to initial values
2373
+ function valueReset(fireSetEvent) {
2374
+ valueSet(options.start, fireSetEvent);
2375
+ }
2376
+
2377
+ // Set value for a single handle
2378
+ function valueSetHandle(handleNumber, value, fireSetEvent) {
2379
+ // Ensure numeric input
2380
+ handleNumber = Number(handleNumber);
2381
+
2382
+ if (!(handleNumber >= 0 && handleNumber < scope_HandleNumbers.length)) {
2383
+ throw new Error("noUiSlider (" + VERSION + "): invalid handle number, got: " + handleNumber);
2384
+ }
2385
+
2386
+ // Look both backward and forward, since we don't want this handle to "push" other handles (#960);
2387
+ setHandle(handleNumber, resolveToValue(value, handleNumber), true, true);
2388
+
2389
+ fireEvent("update", handleNumber);
2390
+
2391
+ if (fireSetEvent) {
2392
+ fireEvent("set", handleNumber);
2393
+ }
2394
+ }
2395
+
2396
+ // Get the slider value.
2397
+ function valueGet() {
2398
+ var values = scope_Values.map(options.format.to);
2399
+
2400
+ // If only one handle is used, return a single value.
2401
+ if (values.length === 1) {
2402
+ return values[0];
2403
+ }
2404
+
2405
+ return values;
2406
+ }
2407
+
2408
+ // Removes classes from the root and empties it.
2409
+ function destroy() {
2410
+ for (var key in options.cssClasses) {
2411
+ if (!options.cssClasses.hasOwnProperty(key)) {
2412
+ continue;
2413
+ }
2414
+ removeClass(scope_Target, options.cssClasses[key]);
2415
+ }
2416
+
2417
+ while (scope_Target.firstChild) {
2418
+ scope_Target.removeChild(scope_Target.firstChild);
2419
+ }
2420
+
2421
+ delete scope_Target.noUiSlider;
2422
+ }
2423
+
2424
+ function getNextStepsForHandle(handleNumber) {
2425
+ var location = scope_Locations[handleNumber];
2426
+ var nearbySteps = scope_Spectrum.getNearbySteps(location);
2427
+ var value = scope_Values[handleNumber];
2428
+ var increment = nearbySteps.thisStep.step;
2429
+ var decrement = null;
2430
+
2431
+ // If snapped, directly use defined step value
2432
+ if (options.snap) {
2433
+ return [
2434
+ value - nearbySteps.stepBefore.startValue || null,
2435
+ nearbySteps.stepAfter.startValue - value || null
2436
+ ];
2437
+ }
2438
+
2439
+ // If the next value in this step moves into the next step,
2440
+ // the increment is the start of the next step - the current value
2441
+ if (increment !== false) {
2442
+ if (value + increment > nearbySteps.stepAfter.startValue) {
2443
+ increment = nearbySteps.stepAfter.startValue - value;
2444
+ }
2445
+ }
2446
+
2447
+ // If the value is beyond the starting point
2448
+ if (value > nearbySteps.thisStep.startValue) {
2449
+ decrement = nearbySteps.thisStep.step;
2450
+ } else if (nearbySteps.stepBefore.step === false) {
2451
+ decrement = false;
2452
+ }
2453
+
2454
+ // If a handle is at the start of a step, it always steps back into the previous step first
2455
+ else {
2456
+ decrement = value - nearbySteps.stepBefore.highestStep;
2457
+ }
2458
+
2459
+ // Now, if at the slider edges, there is no in/decrement
2460
+ if (location === 100) {
2461
+ increment = null;
2462
+ } else if (location === 0) {
2463
+ decrement = null;
2464
+ }
2465
+
2466
+ // As per #391, the comparison for the decrement step can have some rounding issues.
2467
+ var stepDecimals = scope_Spectrum.countStepDecimals();
2468
+
2469
+ // Round per #391
2470
+ if (increment !== null && increment !== false) {
2471
+ increment = Number(increment.toFixed(stepDecimals));
2472
+ }
2473
+
2474
+ if (decrement !== null && decrement !== false) {
2475
+ decrement = Number(decrement.toFixed(stepDecimals));
2476
+ }
2477
+
2478
+ return [decrement, increment];
2479
+ }
2480
+
2481
+ // Get the current step size for the slider.
2482
+ function getNextSteps() {
2483
+ return scope_HandleNumbers.map(getNextStepsForHandle);
2484
+ }
2485
+
2486
+ // Updateable: margin, limit, padding, step, range, animate, snap
2487
+ function updateOptions(optionsToUpdate, fireSetEvent) {
2488
+ // Spectrum is created using the range, snap, direction and step options.
2489
+ // 'snap' and 'step' can be updated.
2490
+ // If 'snap' and 'step' are not passed, they should remain unchanged.
2491
+ var v = valueGet();
2492
+
2493
+ var updateAble = [
2494
+ "margin",
2495
+ "limit",
2496
+ "padding",
2497
+ "range",
2498
+ "animate",
2499
+ "snap",
2500
+ "step",
2501
+ "format",
2502
+ "pips",
2503
+ "tooltips"
2504
+ ];
2505
+
2506
+ // Only change options that we're actually passed to update.
2507
+ updateAble.forEach(function(name) {
2508
+ // Check for undefined. null removes the value.
2509
+ if (optionsToUpdate[name] !== undefined) {
2510
+ originalOptions[name] = optionsToUpdate[name];
2511
+ }
2512
+ });
2513
+
2514
+ var newOptions = testOptions(originalOptions);
2515
+
2516
+ // Load new options into the slider state
2517
+ updateAble.forEach(function(name) {
2518
+ if (optionsToUpdate[name] !== undefined) {
2519
+ options[name] = newOptions[name];
2520
+ }
2521
+ });
2522
+
2523
+ scope_Spectrum = newOptions.spectrum;
2524
+
2525
+ // Limit, margin and padding depend on the spectrum but are stored outside of it. (#677)
2526
+ options.margin = newOptions.margin;
2527
+ options.limit = newOptions.limit;
2528
+ options.padding = newOptions.padding;
2529
+
2530
+ // Update pips, removes existing.
2531
+ if (options.pips) {
2532
+ pips(options.pips);
2533
+ } else {
2534
+ removePips();
2535
+ }
2536
+
2537
+ // Update tooltips, removes existing.
2538
+ if (options.tooltips) {
2539
+ tooltips();
2540
+ } else {
2541
+ removeTooltips();
2542
+ }
2543
+
2544
+ // Invalidate the current positioning so valueSet forces an update.
2545
+ scope_Locations = [];
2546
+ valueSet(optionsToUpdate.start || v, fireSetEvent);
2547
+ }
2548
+
2549
+ // Initialization steps
2550
+ function setupSlider() {
2551
+ // Create the base element, initialize HTML and set classes.
2552
+ // Add handles and connect elements.
2553
+ scope_Base = addSlider(scope_Target);
2554
+
2555
+ addElements(options.connect, scope_Base);
2556
+
2557
+ // Attach user events.
2558
+ bindSliderEvents(options.events);
2559
+
2560
+ // Use the public value method to set the start values.
2561
+ valueSet(options.start);
2562
+
2563
+ if (options.pips) {
2564
+ pips(options.pips);
2565
+ }
2566
+
2567
+ if (options.tooltips) {
2568
+ tooltips();
2569
+ }
2570
+
2571
+ aria();
2572
+ }
2573
+
2574
+ setupSlider();
2575
+
2576
+ // noinspection JSUnusedGlobalSymbols
2577
+ scope_Self = {
2578
+ destroy: destroy,
2579
+ steps: getNextSteps,
2580
+ on: bindEvent,
2581
+ off: removeEvent,
2582
+ get: valueGet,
2583
+ set: valueSet,
2584
+ setHandle: valueSetHandle,
2585
+ reset: valueReset,
2586
+ // Exposed for unit testing, don't use this in your application.
2587
+ __moveHandles: function(a, b, c) {
2588
+ moveHandles(a, b, scope_Locations, c);
2589
+ },
2590
+ options: originalOptions, // Issue #600, #678
2591
+ updateOptions: updateOptions,
2592
+ target: scope_Target, // Issue #597
2593
+ removePips: removePips,
2594
+ removeTooltips: removeTooltips,
2595
+ getTooltips: function() {
2596
+ return scope_Tooltips;
2597
+ },
2598
+ getOrigins: function() {
2599
+ return scope_Handles;
2600
+ },
2601
+ pips: pips // Issue #594
2602
+ };
2603
+
2604
+ return scope_Self;
2605
+ }
2606
+
2607
+ // Run the standard initializer
2608
+ function initialize(target, originalOptions) {
2609
+ if (!target || !target.nodeName) {
2610
+ throw new Error("noUiSlider (" + VERSION + "): create requires a single element, got: " + target);
2611
+ }
2612
+
2613
+ // Throw an error if the slider was already initialized.
2614
+ if (target.noUiSlider) {
2615
+ throw new Error("noUiSlider (" + VERSION + "): Slider was already initialized.");
2616
+ }
2617
+
2618
+ // Test the options and create the slider environment;
2619
+ var options = testOptions(originalOptions, target);
2620
+ var api = scope(target, options, originalOptions);
2621
+
2622
+ target.noUiSlider = api;
2623
+
2624
+ return api;
2625
+ }
2626
+
2627
+ // Use an object instead of a function for future expandability;
2628
+ return {
2629
+ // Exposed for unit testing, don't use this in your application.
2630
+ __spectrum: Spectrum,
2631
+ version: VERSION,
2632
+ // A reference to the default classes, allows global changes.
2633
+ // Use the cssClasses option for changes to one slider.
2634
+ cssClasses: cssClasses,
2635
+ create: initialize
2636
+ };
2637
+ });