ng5-slider.js 130 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272
  1. import { Subject } from 'rxjs/Subject';
  2. import 'rxjs/Subscription';
  3. import { Renderer2, Directive, ElementRef, HostBinding, Component, ViewChild, HostListener, Input, EventEmitter, Output, ContentChild, ChangeDetectorRef, forwardRef, NgZone, NgModule } from '@angular/core';
  4. import { throttleTime, tap, distinctUntilChanged, filter } from 'rxjs/operators';
  5. import detectPassiveEvents from 'detect-passive-events';
  6. import { NG_VALUE_ACCESSOR } from '@angular/forms';
  7. import { CommonModule } from '@angular/common';
  8. /**
  9. * @fileoverview added by tsickle
  10. * @suppress {checkTypes} checked by tsc
  11. */
  12. /** @enum {number} */
  13. const PointerType = {
  14. /** Low pointer */
  15. Min: 0,
  16. /** High pointer */
  17. Max: 1,
  18. };
  19. PointerType[PointerType.Min] = "Min";
  20. PointerType[PointerType.Max] = "Max";
  21. /**
  22. * @fileoverview added by tsickle
  23. * @suppress {checkTypes} checked by tsc
  24. */
  25. /** @enum {number} */
  26. const LabelType = {
  27. /** Label above low pointer */
  28. Low: 0,
  29. /** Label above high pointer */
  30. High: 1,
  31. /** Label for minimum slider value */
  32. Floor: 2,
  33. /** Label for maximum slider value */
  34. Ceil: 3,
  35. /** Label below legend tick */
  36. TickValue: 4,
  37. };
  38. LabelType[LabelType.Low] = "Low";
  39. LabelType[LabelType.High] = "High";
  40. LabelType[LabelType.Floor] = "Floor";
  41. LabelType[LabelType.Ceil] = "Ceil";
  42. LabelType[LabelType.TickValue] = "TickValue";
  43. /**
  44. * Custom step definition
  45. *
  46. * This can be used to specify custom values and legend values for slider ticks
  47. * @record
  48. */
  49. /**
  50. * Slider options
  51. */
  52. class Options {
  53. constructor() {
  54. /**
  55. * Minimum value for a slider.
  56. * Not applicable when using stepsArray.
  57. */
  58. this.floor = 0;
  59. /**
  60. * Maximum value for a slider.
  61. * Not applicable when using stepsArray.
  62. */
  63. this.ceil = null;
  64. /**
  65. * Step between each value.
  66. * Not applicable when using stepsArray.
  67. */
  68. this.step = 1;
  69. /**
  70. * The minimum range authorized on the slider.
  71. * Applies to range slider only.
  72. * When using stepsArray, expressed as index into stepsArray.
  73. */
  74. this.minRange = null;
  75. /**
  76. * The maximum range authorized on the slider.
  77. * Applies to range slider only.
  78. * When using stepsArray, expressed as index into stepsArray.
  79. */
  80. this.maxRange = null;
  81. /**
  82. * Set to true to have a push behavior. When the min handle goes above the max,
  83. * the max is moved as well (and vice-versa). The range between min and max is
  84. * defined by the step option (defaults to 1) and can also be overriden by
  85. * the minRange option. Applies to range slider only.
  86. */
  87. this.pushRange = false;
  88. /**
  89. * The minimum value authorized on the slider.
  90. * When using stepsArray, expressed as index into stepsArray.
  91. */
  92. this.minLimit = null;
  93. /**
  94. * The maximum value authorized on the slider.
  95. * When using stepsArray, expressed as index into stepsArray.
  96. */
  97. this.maxLimit = null;
  98. /**
  99. * Custom translate function. Use this if you want to translate values displayed
  100. * on the slider.
  101. */
  102. this.translate = null;
  103. /**
  104. * Custom function for combining overlapping labels in range slider.
  105. * It takes the min and max values (already translated with translate fuction)
  106. * and should return how these two values should be combined.
  107. * If not provided, the default function will join the two values with
  108. * ' - ' as separator.
  109. */
  110. this.combineLabels = null;
  111. /**
  112. * Use to display legend under ticks (thus, it needs to be used along with
  113. * showTicks or showTicksValues). The function will be called with each tick
  114. * value and returned content will be displayed under the tick as a legend.
  115. * If the returned value is null, then no legend is displayed under
  116. * the corresponding tick.You can also directly provide the legend values
  117. * in the stepsArray option.
  118. */
  119. this.getLegend = null;
  120. /**
  121. * If you want to display a slider with non linear/number steps.
  122. * Just pass an array with each slider value and that's it; the floor, ceil and step settings
  123. * of the slider will be computed automatically.
  124. * By default, the value model and valueHigh model values will be the value of the selected item
  125. * in the stepsArray.
  126. * They can also be bound to the index of the selected item by setting the bindIndexForStepsArray
  127. * option to true.
  128. */
  129. this.stepsArray = null;
  130. /**
  131. * Set to true to bind the index of the selected item to value model and valueHigh model.
  132. */
  133. this.bindIndexForStepsArray = false;
  134. /**
  135. * When set to true and using a range slider, the range can be dragged by the selection bar.
  136. * Applies to range slider only.
  137. */
  138. this.draggableRange = false;
  139. /**
  140. * Same as draggableRange but the slider range can't be changed.
  141. * Applies to range slider only.
  142. */
  143. this.draggableRangeOnly = false;
  144. /**
  145. * Set to true to always show the selection bar before the slider handle.
  146. */
  147. this.showSelectionBar = false;
  148. /**
  149. * Set to true to always show the selection bar after the slider handle.
  150. */
  151. this.showSelectionBarEnd = false;
  152. /**
  153. * Set a number to draw the selection bar between this value and the slider handle.
  154. * When using stepsArray, expressed as index into stepsArray.
  155. */
  156. this.showSelectionBarFromValue = null;
  157. /**
  158. * Only for range slider. Set to true to visualize in different colour the areas
  159. * on the left/right (top/bottom for vertical range slider) of selection bar between the handles.
  160. */
  161. this.showOuterSelectionBars = false;
  162. /**
  163. * Set to true to hide pointer labels
  164. */
  165. this.hidePointerLabels = false;
  166. /**
  167. * Set to true to hide min / max labels
  168. */
  169. this.hideLimitLabels = false;
  170. /**
  171. * Set to false to disable the auto-hiding behavior of the limit labels.
  172. */
  173. this.autoHideLimitLabels = true;
  174. /**
  175. * Set to true to make the slider read-only.
  176. */
  177. this.readOnly = false;
  178. /**
  179. * Set to true to disable the slider.
  180. */
  181. this.disabled = false;
  182. /**
  183. * Throttle interval for mouse events in milliseconds.
  184. * This is provided to avoid a flood of events when moving the slider with mouse.
  185. */
  186. this.mouseEventsInterval = 50;
  187. /**
  188. * Throttle interval for touch events in milliseconds.
  189. * This is provided to avoid a flood of events when moving the slider with touch gesture.
  190. */
  191. this.touchEventsInterval = 50;
  192. /**
  193. * Throttle interval for input changes (changes to bindings or reactive form inputs)
  194. * This is provided to avoid a flood of events on frequent input binding changes affecting performance.
  195. */
  196. this.inputEventsInterval = 100;
  197. /**
  198. * Throttle interval for output changes (signalling changes to output bindings and user callbacks)
  199. * This is provided to avoid a flood of outgoing events affecting Angular app performance.
  200. */
  201. this.outputEventsInterval = 100;
  202. /**
  203. * Set to true to display a tick for each step of the slider.
  204. */
  205. this.showTicks = false;
  206. /**
  207. * Set to true to display a tick and the step value for each step of the slider..
  208. */
  209. this.showTicksValues = false;
  210. /* The step between each tick to display. If not set, the step value is used.
  211. Not used when ticksArray is specified. */
  212. this.tickStep = null;
  213. /* The step between displaying each tick step value. */
  214. this.tickValueStep = 1;
  215. /**
  216. * Use to display ticks at specific positions.
  217. * The array contains the index of the ticks that should be displayed.
  218. * For example, [0, 1, 5] will display a tick for the first, second and sixth values.
  219. */
  220. this.ticksArray = null;
  221. /**
  222. * Used to display a tooltip when a tick is hovered.
  223. * Set to a function that returns the tooltip content for a given value.
  224. */
  225. this.ticksTooltip = null;
  226. /**
  227. * Same as ticksTooltip but for ticks values.
  228. */
  229. this.ticksValuesTooltip = null;
  230. /**
  231. * Set to true to display the slider vertically.
  232. * The slider will take the full height of its parent.
  233. * Changing this value at runtime is not currently supported.
  234. */
  235. this.vertical = false;
  236. /**
  237. * Function that returns the current color of the selection bar.
  238. * If your color won't change, don't use this option but set it through CSS.
  239. * If the returned color depends on a model value (either value or valueHigh),
  240. * you should use the argument passed to the function.
  241. * Indeed, when the function is called, there is no certainty that the model
  242. * has already been updated.
  243. */
  244. this.getSelectionBarColor = null;
  245. /**
  246. * Function that returns the color of a tick. showTicks must be enabled.
  247. */
  248. this.getTickColor = null;
  249. /**
  250. * Function that returns the current color of a pointer.
  251. * If your color won't change, don't use this option but set it through CSS.
  252. * If the returned color depends on a model value (either value or valueHigh),
  253. * you should use the argument passed to the function.
  254. * Indeed, when the function is called, there is no certainty that the model has already been updated.
  255. * To handle range slider pointers independently, you should evaluate pointerType within the given
  256. * function where "min" stands for value model and "max" for valueHigh model values.
  257. */
  258. this.getPointerColor = null;
  259. /**
  260. * Handles are focusable (on click or with tab) and can be modified using the following keyboard controls:
  261. * Left/bottom arrows: -1
  262. * Right/top arrows: +1
  263. * Page-down: -10%
  264. * Page-up: +10%
  265. * Home: minimum value
  266. * End: maximum value
  267. */
  268. this.keyboardSupport = true;
  269. /**
  270. * If you display the slider in an element that uses transform: scale(0.5), set the scale value to 2
  271. * so that the slider is rendered properly and the events are handled correctly.
  272. */
  273. this.scale = 1;
  274. /**
  275. * Set to true to force the value to be rounded to the step, even when modified from the outside.
  276. * When set to false, if the model values are modified from outside the slider, they are not rounded
  277. * and can be between two steps.
  278. */
  279. this.enforceStep = true;
  280. /**
  281. * Set to true to force the value to be normalised to allowed range (floor to ceil), even when modified from the outside.
  282. * When set to false, if the model values are modified from outside the slider, and they are outside allowed range,
  283. * the slider may be rendered incorrectly. However, setting this to false may be useful if you want to perform custom normalisation.
  284. */
  285. this.enforceRange = true;
  286. /**
  287. * Set to true to prevent to user from switching the min and max handles. Applies to range slider only.
  288. */
  289. this.noSwitching = false;
  290. /**
  291. * Set to true to only bind events on slider handles.
  292. */
  293. this.onlyBindHandles = false;
  294. /**
  295. * Set to true to show graphs right to left.
  296. * If vertical is true it will be from top to bottom and left / right arrow functions reversed.
  297. */
  298. this.rightToLeft = false;
  299. /**
  300. * Set to true to reverse keyboard navigation:
  301. * Right/top arrows: -1
  302. * Left/bottom arrows: +1
  303. * Page-up: -10%
  304. * Page-down: +10%
  305. * End: minimum value
  306. * Home: maximum value
  307. */
  308. this.reversedControls = false;
  309. /**
  310. * Set to true to keep the slider labels inside the slider bounds.
  311. */
  312. this.boundPointerLabels = true;
  313. /**
  314. * Set to true to use a logarithmic scale to display the slider.
  315. */
  316. this.logScale = false;
  317. /**
  318. * Function that returns the position on the slider for a given value.
  319. * The position must be a percentage between 0 and 1.
  320. * The function should be monotonically increasing or decreasing; otherwise the slider may behave incorrectly.
  321. */
  322. this.customValueToPosition = null;
  323. /**
  324. * Function that returns the value for a given position on the slider.
  325. * The position is a percentage between 0 and 1.
  326. * The function should be monotonically increasing or decreasing; otherwise the slider may behave incorrectly.
  327. */
  328. this.customPositionToValue = null;
  329. /**
  330. * Precision limit for calculated values.
  331. * Values used in calculations will be rounded to this number of significant digits
  332. * to prevent accumulating small floating-point errors.
  333. */
  334. this.precisionLimit = 12;
  335. /**
  336. * Use to display the selection bar as a gradient.
  337. * The given object must contain from and to properties which are colors.
  338. */
  339. this.selectionBarGradient = null;
  340. /**
  341. * Use to add a label directly to the slider for accessibility. Adds the aria-label attribute.
  342. */
  343. this.ariaLabel = null;
  344. /**
  345. * Use instead of ariaLabel to reference the id of an element which will be used to label the slider.
  346. * Adds the aria-labelledby attribute.
  347. */
  348. this.ariaLabelledBy = null;
  349. /**
  350. * Use to add a label directly to the slider range for accessibility. Adds the aria-label attribute.
  351. */
  352. this.ariaLabelHigh = null;
  353. /**
  354. * Use instead of ariaLabelHigh to reference the id of an element which will be used to label the slider range.
  355. * Adds the aria-labelledby attribute.
  356. */
  357. this.ariaLabelledByHigh = null;
  358. /**
  359. * Use to increase rendering performance. If the value is not provided, the slider calculates the with/height of the handle
  360. */
  361. this.handleDimension = null;
  362. /**
  363. * Use to increase rendering performance. If the value is not provided, the slider calculates the with/height of the bar
  364. */
  365. this.barDimension = null;
  366. /**
  367. * Enable/disable CSS animations
  368. */
  369. this.animate = true;
  370. }
  371. }
  372. /**
  373. * @fileoverview added by tsickle
  374. * @suppress {checkTypes} checked by tsc
  375. */
  376. class ChangeContext {
  377. }
  378. /**
  379. * @fileoverview added by tsickle
  380. * @suppress {checkTypes} checked by tsc
  381. */
  382. /**
  383. * Collection of functions to handle conversions/lookups of values
  384. */
  385. class ValueHelper {
  386. /**
  387. * @param {?} value
  388. * @return {?}
  389. */
  390. static isNullOrUndefined(value) {
  391. return value === undefined || value === null;
  392. }
  393. /**
  394. * @param {?} val
  395. * @param {?} minVal
  396. * @param {?} maxVal
  397. * @return {?}
  398. */
  399. static linearValueToPosition(val, minVal, maxVal) {
  400. const /** @type {?} */ range = maxVal - minVal;
  401. return (val - minVal) / range;
  402. }
  403. /**
  404. * @param {?} val
  405. * @param {?} minVal
  406. * @param {?} maxVal
  407. * @return {?}
  408. */
  409. static logValueToPosition(val, minVal, maxVal) {
  410. val = Math.log(val);
  411. minVal = Math.log(minVal);
  412. maxVal = Math.log(maxVal);
  413. const /** @type {?} */ range = maxVal - minVal;
  414. return (val - minVal) / range;
  415. }
  416. /**
  417. * @param {?} percent
  418. * @param {?} minVal
  419. * @param {?} maxVal
  420. * @return {?}
  421. */
  422. static linearPositionToValue(percent, minVal, maxVal) {
  423. return percent * (maxVal - minVal) + minVal;
  424. }
  425. /**
  426. * @param {?} percent
  427. * @param {?} minVal
  428. * @param {?} maxVal
  429. * @return {?}
  430. */
  431. static logPositionToValue(percent, minVal, maxVal) {
  432. minVal = Math.log(minVal);
  433. maxVal = Math.log(maxVal);
  434. const /** @type {?} */ value = percent * (maxVal - minVal) + minVal;
  435. return Math.exp(value);
  436. }
  437. /**
  438. * @param {?} modelValue
  439. * @param {?} stepsArray
  440. * @return {?}
  441. */
  442. static findStepIndex(modelValue, stepsArray) {
  443. const /** @type {?} */ differences = stepsArray.map((step) => Math.abs(modelValue - step.value));
  444. let /** @type {?} */ minDifferenceIndex = 0;
  445. for (let /** @type {?} */ index = 0; index < stepsArray.length; index++) {
  446. if (differences[index] !== differences[minDifferenceIndex] && differences[index] < differences[minDifferenceIndex]) {
  447. minDifferenceIndex = index;
  448. }
  449. }
  450. return minDifferenceIndex;
  451. }
  452. }
  453. /**
  454. * @fileoverview added by tsickle
  455. * @suppress {checkTypes} checked by tsc
  456. */
  457. /**
  458. * Helper with compatibility functions to support different browsers
  459. */
  460. class CompatibilityHelper {
  461. /**
  462. * Workaround for TouchEvent constructor sadly not being available on all browsers (e.g. Firefox, Safari)
  463. * @param {?} event
  464. * @return {?}
  465. */
  466. static isTouchEvent(event) {
  467. if ((/** @type {?} */ (window)).TouchEvent !== undefined) {
  468. return event instanceof TouchEvent;
  469. }
  470. return event.touches !== undefined;
  471. }
  472. /**
  473. * Detect presence of ResizeObserver API
  474. * @return {?}
  475. */
  476. static isResizeObserverAvailable() {
  477. return (/** @type {?} */ (window)).ResizeObserver !== undefined;
  478. }
  479. }
  480. /**
  481. * @fileoverview added by tsickle
  482. * @suppress {checkTypes} checked by tsc
  483. */
  484. /**
  485. * Helper with mathematical functions
  486. */
  487. class MathHelper {
  488. /**
  489. * @param {?} value
  490. * @param {?} precisionLimit
  491. * @return {?}
  492. */
  493. static roundToPrecisionLimit(value, precisionLimit) {
  494. return +(value.toPrecision(precisionLimit));
  495. }
  496. /**
  497. * @param {?} value
  498. * @param {?} floor
  499. * @param {?} ceil
  500. * @return {?}
  501. */
  502. static clampToRange(value, floor, ceil) {
  503. return Math.min(Math.max(value, floor), ceil);
  504. }
  505. }
  506. /**
  507. * @fileoverview added by tsickle
  508. * @suppress {checkTypes} checked by tsc
  509. */
  510. class EventListener {
  511. constructor() {
  512. this.eventName = null;
  513. this.events = null;
  514. this.eventsSubscription = null;
  515. this.teardownCallback = null;
  516. }
  517. }
  518. /**
  519. * @fileoverview added by tsickle
  520. * @suppress {checkTypes} checked by tsc
  521. */
  522. /**
  523. * Helper class to attach event listeners to DOM elements with debounce support using rxjs
  524. */
  525. class EventListenerHelper {
  526. /**
  527. * @param {?} renderer
  528. */
  529. constructor(renderer) {
  530. this.renderer = renderer;
  531. }
  532. /**
  533. * @param {?} nativeElement
  534. * @param {?} eventName
  535. * @param {?} callback
  536. * @param {?=} throttleInterval
  537. * @return {?}
  538. */
  539. attachPassiveEventListener(nativeElement, eventName, callback, throttleInterval) {
  540. // Only use passive event listeners if the browser supports it
  541. if (detectPassiveEvents.hasSupport !== true) {
  542. return this.attachEventListener(nativeElement, eventName, callback, throttleInterval);
  543. }
  544. // Angular doesn't support passive event handlers (yet), so we need to roll our own code using native functions
  545. const /** @type {?} */ listener = new EventListener();
  546. listener.eventName = eventName;
  547. listener.events = new Subject();
  548. const /** @type {?} */ observerCallback = (event) => {
  549. listener.events.next(event);
  550. };
  551. nativeElement.addEventListener(eventName, observerCallback, { passive: true, capture: false });
  552. listener.teardownCallback = () => {
  553. nativeElement.removeEventListener(eventName, observerCallback, { passive: true, capture: false });
  554. };
  555. listener.eventsSubscription = listener.events
  556. .pipe((!ValueHelper.isNullOrUndefined(throttleInterval))
  557. ? throttleTime(throttleInterval, undefined, { leading: true, trailing: true })
  558. : tap(() => { }) // no-op
  559. )
  560. .subscribe((event) => {
  561. callback(event);
  562. });
  563. return listener;
  564. }
  565. /**
  566. * @param {?} eventListener
  567. * @return {?}
  568. */
  569. detachEventListener(eventListener) {
  570. if (!ValueHelper.isNullOrUndefined(eventListener.eventsSubscription)) {
  571. eventListener.eventsSubscription.unsubscribe();
  572. eventListener.eventsSubscription = null;
  573. }
  574. if (!ValueHelper.isNullOrUndefined(eventListener.events)) {
  575. eventListener.events.complete();
  576. eventListener.events = null;
  577. }
  578. if (!ValueHelper.isNullOrUndefined(eventListener.teardownCallback)) {
  579. eventListener.teardownCallback();
  580. eventListener.teardownCallback = null;
  581. }
  582. }
  583. /**
  584. * @param {?} nativeElement
  585. * @param {?} eventName
  586. * @param {?} callback
  587. * @param {?=} throttleInterval
  588. * @return {?}
  589. */
  590. attachEventListener(nativeElement, eventName, callback, throttleInterval) {
  591. const /** @type {?} */ listener = new EventListener();
  592. listener.eventName = eventName;
  593. listener.events = new Subject();
  594. const /** @type {?} */ observerCallback = (event) => {
  595. listener.events.next(event);
  596. };
  597. listener.teardownCallback = this.renderer.listen(nativeElement, eventName, observerCallback);
  598. listener.eventsSubscription = listener.events
  599. .pipe((!ValueHelper.isNullOrUndefined(throttleInterval))
  600. ? throttleTime(throttleInterval, undefined, { leading: true, trailing: true })
  601. : tap(() => { }) // no-op
  602. )
  603. .subscribe((event) => { callback(event); });
  604. return listener;
  605. }
  606. }
  607. /**
  608. * @fileoverview added by tsickle
  609. * @suppress {checkTypes} checked by tsc
  610. */
  611. class SliderElementDirective {
  612. /**
  613. * @param {?} elemRef
  614. * @param {?} renderer
  615. */
  616. constructor(elemRef, renderer) {
  617. this.elemRef = elemRef;
  618. this.renderer = renderer;
  619. this._position = 0;
  620. this._dimension = 0;
  621. this._alwaysHide = false;
  622. this._vertical = false;
  623. this._scale = 1;
  624. this.opacity = 1;
  625. this.visibility = 'visible';
  626. this.left = '';
  627. this.bottom = '';
  628. this.height = '';
  629. this.width = '';
  630. this.eventListeners = [];
  631. this.eventListenerHelper = new EventListenerHelper(this.renderer);
  632. }
  633. /**
  634. * @return {?}
  635. */
  636. get position() {
  637. return this._position;
  638. }
  639. /**
  640. * @return {?}
  641. */
  642. get dimension() {
  643. return this._dimension;
  644. }
  645. /**
  646. * @return {?}
  647. */
  648. get alwaysHide() {
  649. return this._alwaysHide;
  650. }
  651. /**
  652. * @return {?}
  653. */
  654. get vertical() {
  655. return this._vertical;
  656. }
  657. /**
  658. * @return {?}
  659. */
  660. get scale() {
  661. return this._scale;
  662. }
  663. /**
  664. * @param {?} hide
  665. * @return {?}
  666. */
  667. setAlwaysHide(hide) {
  668. this._alwaysHide = hide;
  669. if (hide) {
  670. this.visibility = 'hidden';
  671. }
  672. else {
  673. this.visibility = 'visible';
  674. }
  675. }
  676. /**
  677. * @return {?}
  678. */
  679. hide() {
  680. this.opacity = 0;
  681. }
  682. /**
  683. * @return {?}
  684. */
  685. show() {
  686. if (this.alwaysHide) {
  687. return;
  688. }
  689. this.opacity = 1;
  690. }
  691. /**
  692. * @return {?}
  693. */
  694. isVisible() {
  695. if (this.alwaysHide) {
  696. return false;
  697. }
  698. return this.opacity !== 0;
  699. }
  700. /**
  701. * @param {?} vertical
  702. * @return {?}
  703. */
  704. setVertical(vertical) {
  705. this._vertical = vertical;
  706. if (this._vertical) {
  707. this.left = '';
  708. this.width = '';
  709. }
  710. else {
  711. this.bottom = '';
  712. this.height = '';
  713. }
  714. }
  715. /**
  716. * @param {?} scale
  717. * @return {?}
  718. */
  719. setScale(scale) {
  720. this._scale = scale;
  721. }
  722. /**
  723. * @param {?} pos
  724. * @return {?}
  725. */
  726. setPosition(pos) {
  727. this._position = pos;
  728. if (this._vertical) {
  729. this.bottom = Math.round(pos) + 'px';
  730. }
  731. else {
  732. this.left = Math.round(pos) + 'px';
  733. }
  734. }
  735. /**
  736. * @return {?}
  737. */
  738. calculateDimension() {
  739. const /** @type {?} */ val = this.getBoundingClientRect();
  740. if (this.vertical) {
  741. this._dimension = (val.bottom - val.top) * this.scale;
  742. }
  743. else {
  744. this._dimension = (val.right - val.left) * this.scale;
  745. }
  746. }
  747. /**
  748. * @param {?} dim
  749. * @return {?}
  750. */
  751. setDimension(dim) {
  752. this._dimension = dim;
  753. if (this._vertical) {
  754. this.height = Math.round(dim) + 'px';
  755. }
  756. else {
  757. this.width = Math.round(dim) + 'px';
  758. }
  759. }
  760. /**
  761. * @return {?}
  762. */
  763. getBoundingClientRect() {
  764. return this.elemRef.nativeElement.getBoundingClientRect();
  765. }
  766. /**
  767. * @param {?} eventName
  768. * @param {?} callback
  769. * @param {?=} debounceInterval
  770. * @return {?}
  771. */
  772. on(eventName, callback, debounceInterval) {
  773. const /** @type {?} */ listener = this.eventListenerHelper.attachEventListener(this.elemRef.nativeElement, eventName, callback, debounceInterval);
  774. this.eventListeners.push(listener);
  775. }
  776. /**
  777. * @param {?} eventName
  778. * @param {?} callback
  779. * @param {?=} debounceInterval
  780. * @return {?}
  781. */
  782. onPassive(eventName, callback, debounceInterval) {
  783. const /** @type {?} */ listener = this.eventListenerHelper.attachPassiveEventListener(this.elemRef.nativeElement, eventName, callback, debounceInterval);
  784. this.eventListeners.push(listener);
  785. }
  786. /**
  787. * @param {?=} eventName
  788. * @return {?}
  789. */
  790. off(eventName) {
  791. let /** @type {?} */ listenersToKeep;
  792. let /** @type {?} */ listenersToRemove;
  793. if (!ValueHelper.isNullOrUndefined(eventName)) {
  794. listenersToKeep = this.eventListeners.filter((event) => event.eventName !== eventName);
  795. listenersToRemove = this.eventListeners.filter((event) => event.eventName === eventName);
  796. }
  797. else {
  798. listenersToKeep = [];
  799. listenersToRemove = this.eventListeners;
  800. }
  801. for (const /** @type {?} */ listener of listenersToRemove) {
  802. this.eventListenerHelper.detachEventListener(listener);
  803. }
  804. this.eventListeners = listenersToKeep;
  805. }
  806. }
  807. SliderElementDirective.decorators = [
  808. { type: Directive, args: [{
  809. selector: '[ng5SliderElement]'
  810. },] },
  811. ];
  812. /** @nocollapse */
  813. SliderElementDirective.ctorParameters = () => [
  814. { type: ElementRef, },
  815. { type: Renderer2, },
  816. ];
  817. SliderElementDirective.propDecorators = {
  818. "opacity": [{ type: HostBinding, args: ['style.opacity',] },],
  819. "visibility": [{ type: HostBinding, args: ['style.visibility',] },],
  820. "left": [{ type: HostBinding, args: ['style.left',] },],
  821. "bottom": [{ type: HostBinding, args: ['style.bottom',] },],
  822. "height": [{ type: HostBinding, args: ['style.height',] },],
  823. "width": [{ type: HostBinding, args: ['style.width',] },],
  824. };
  825. /**
  826. * @fileoverview added by tsickle
  827. * @suppress {checkTypes} checked by tsc
  828. */
  829. class SliderHandleDirective extends SliderElementDirective {
  830. /**
  831. * @param {?} elemRef
  832. * @param {?} renderer
  833. */
  834. constructor(elemRef, renderer) {
  835. super(elemRef, renderer);
  836. this.active = false;
  837. this.role = '';
  838. this.tabindex = '';
  839. this.ariaOrientation = '';
  840. this.ariaLabel = '';
  841. this.ariaLabelledBy = '';
  842. this.ariaValueNow = '';
  843. this.ariaValueText = '';
  844. this.ariaValueMin = '';
  845. this.ariaValueMax = '';
  846. }
  847. /**
  848. * @return {?}
  849. */
  850. focus() {
  851. this.elemRef.nativeElement.focus();
  852. }
  853. }
  854. SliderHandleDirective.decorators = [
  855. { type: Directive, args: [{
  856. selector: '[ng5SliderHandle]'
  857. },] },
  858. ];
  859. /** @nocollapse */
  860. SliderHandleDirective.ctorParameters = () => [
  861. { type: ElementRef, },
  862. { type: Renderer2, },
  863. ];
  864. SliderHandleDirective.propDecorators = {
  865. "active": [{ type: HostBinding, args: ['class.ng5-slider-active',] },],
  866. "role": [{ type: HostBinding, args: ['attr.role',] },],
  867. "tabindex": [{ type: HostBinding, args: ['attr.tabindex',] },],
  868. "ariaOrientation": [{ type: HostBinding, args: ['attr.aria-orientation',] },],
  869. "ariaLabel": [{ type: HostBinding, args: ['attr.aria-label',] },],
  870. "ariaLabelledBy": [{ type: HostBinding, args: ['attr.aria-labelledby',] },],
  871. "ariaValueNow": [{ type: HostBinding, args: ['attr.aria-valuenow',] },],
  872. "ariaValueText": [{ type: HostBinding, args: ['attr.aria-valuetext',] },],
  873. "ariaValueMin": [{ type: HostBinding, args: ['attr.aria-valuemin',] },],
  874. "ariaValueMax": [{ type: HostBinding, args: ['attr.aria-valuemax',] },],
  875. };
  876. /**
  877. * @fileoverview added by tsickle
  878. * @suppress {checkTypes} checked by tsc
  879. */
  880. class SliderLabelDirective extends SliderElementDirective {
  881. /**
  882. * @param {?} elemRef
  883. * @param {?} renderer
  884. */
  885. constructor(elemRef, renderer) {
  886. super(elemRef, renderer);
  887. this._value = null;
  888. }
  889. /**
  890. * @return {?}
  891. */
  892. get value() {
  893. return this._value;
  894. }
  895. /**
  896. * @param {?} value
  897. * @return {?}
  898. */
  899. setValue(value) {
  900. let /** @type {?} */ recalculateDimension = false;
  901. if (!this.alwaysHide &&
  902. (ValueHelper.isNullOrUndefined(this.value) ||
  903. this.value.length !== value.length ||
  904. (this.value.length > 0 && this.dimension === 0))) {
  905. recalculateDimension = true;
  906. }
  907. this._value = value;
  908. this.elemRef.nativeElement.innerHTML = value;
  909. // Update dimension only when length of the label have changed
  910. if (recalculateDimension) {
  911. this.calculateDimension();
  912. }
  913. }
  914. }
  915. SliderLabelDirective.decorators = [
  916. { type: Directive, args: [{
  917. selector: '[ng5SliderLabel]'
  918. },] },
  919. ];
  920. /** @nocollapse */
  921. SliderLabelDirective.ctorParameters = () => [
  922. { type: ElementRef, },
  923. { type: Renderer2, },
  924. ];
  925. /**
  926. * @fileoverview added by tsickle
  927. * @suppress {checkTypes} checked by tsc
  928. */
  929. class Tick {
  930. constructor() {
  931. this.selected = false;
  932. this.style = {};
  933. this.tooltip = null;
  934. this.tooltipPlacement = null;
  935. this.value = null;
  936. this.valueTooltip = null;
  937. this.valueTooltipPlacement = null;
  938. this.legend = null;
  939. }
  940. }
  941. class Dragging {
  942. constructor() {
  943. this.active = false;
  944. this.value = 0;
  945. this.difference = 0;
  946. this.position = 0;
  947. this.lowLimit = 0;
  948. this.highLimit = 0;
  949. }
  950. }
  951. class ModelValues {
  952. /**
  953. * @param {?=} x
  954. * @param {?=} y
  955. * @return {?}
  956. */
  957. static compare(x, y) {
  958. if (ValueHelper.isNullOrUndefined(x) && ValueHelper.isNullOrUndefined(y)) {
  959. return false;
  960. }
  961. if (ValueHelper.isNullOrUndefined(x) !== ValueHelper.isNullOrUndefined(y)) {
  962. return false;
  963. }
  964. return x.value === y.value && x.highValue === y.highValue;
  965. }
  966. }
  967. class ModelChange extends ModelValues {
  968. /**
  969. * @param {?=} x
  970. * @param {?=} y
  971. * @return {?}
  972. */
  973. static compare(x, y) {
  974. if (ValueHelper.isNullOrUndefined(x) && ValueHelper.isNullOrUndefined(y)) {
  975. return false;
  976. }
  977. if (ValueHelper.isNullOrUndefined(x) !== ValueHelper.isNullOrUndefined(y)) {
  978. return false;
  979. }
  980. return x.value === y.value &&
  981. x.highValue === y.highValue &&
  982. x.forceChange === y.forceChange;
  983. }
  984. }
  985. const NG5_SLIDER_CONTROL_VALUE_ACCESSOR = {
  986. provide: NG_VALUE_ACCESSOR,
  987. /* tslint:disable-next-line: no-use-before-declare */
  988. useExisting: forwardRef(() => SliderComponent),
  989. multi: true,
  990. };
  991. class SliderComponent {
  992. /**
  993. * @param {?} renderer
  994. * @param {?} elementRef
  995. * @param {?} changeDetectionRef
  996. * @param {?} zone
  997. */
  998. constructor(renderer, elementRef, changeDetectionRef, zone) {
  999. this.renderer = renderer;
  1000. this.elementRef = elementRef;
  1001. this.changeDetectionRef = changeDetectionRef;
  1002. this.zone = zone;
  1003. // Model for low value of slider. For simple slider, this is the only input. For range slider, this is the low value.
  1004. this.value = null;
  1005. // Output for low value slider to support two-way bindings
  1006. this.valueChange = new EventEmitter();
  1007. // Model for high value of slider. Not used in simple slider. For range slider, this is the high value.
  1008. this.highValue = null;
  1009. // Output for high value slider to support two-way bindings
  1010. this.highValueChange = new EventEmitter();
  1011. // An object with all the other options of the slider.
  1012. // Each option can be updated at runtime and the slider will automatically be re-rendered.
  1013. this.options = new Options();
  1014. // Event emitted when user starts interaction with the slider
  1015. this.userChangeStart = new EventEmitter();
  1016. // Event emitted on each change coming from user interaction
  1017. this.userChange = new EventEmitter();
  1018. // Event emitted when user finishes interaction with the slider
  1019. this.userChangeEnd = new EventEmitter();
  1020. this.initHasRun = false;
  1021. this.inputModelChangeSubject = new Subject();
  1022. this.inputModelChangeSubscription = null;
  1023. this.outputModelChangeSubject = new Subject();
  1024. this.outputModelChangeSubscription = null;
  1025. this.viewLowValue = null;
  1026. this.viewHighValue = null;
  1027. this.viewOptions = new Options();
  1028. this.handleHalfDimension = 0;
  1029. this.maxHandlePosition = 0;
  1030. this.currentTrackingPointer = null;
  1031. this.currentFocusPointer = null;
  1032. this.firstKeyDown = false;
  1033. this.touchId = null;
  1034. this.dragging = new Dragging();
  1035. // Host element class bindings
  1036. this.sliderElementVerticalClass = false;
  1037. this.sliderElementAnimateClass = false;
  1038. this.sliderElementDisabledAttr = null;
  1039. this.barStyle = {};
  1040. this.minPointerStyle = {};
  1041. this.maxPointerStyle = {};
  1042. this.fullBarTransparentClass = false;
  1043. this.selectionBarDraggableClass = false;
  1044. this.ticksUnderValuesClass = false;
  1045. this.intermediateTicks = false;
  1046. this.ticks = [];
  1047. this.eventListenerHelper = null;
  1048. this.onMoveEventListener = null;
  1049. this.onEndEventListener = null;
  1050. this.resizeObserver = null;
  1051. this.onTouchedCallback = null;
  1052. this.onChangeCallback = null;
  1053. this.eventListenerHelper = new EventListenerHelper(this.renderer);
  1054. }
  1055. /**
  1056. * @param {?} manualRefresh
  1057. * @return {?}
  1058. */
  1059. set manualRefresh(manualRefresh) {
  1060. this.unsubscribeManualRefresh();
  1061. this.manualRefreshSubscription = manualRefresh.subscribe(() => {
  1062. setTimeout(() => this.calculateViewDimensionsAndDetectChanges());
  1063. });
  1064. }
  1065. /**
  1066. * @param {?} triggerFocus
  1067. * @return {?}
  1068. */
  1069. set triggerFocus(triggerFocus) {
  1070. this.unsubscribeTriggerFocus();
  1071. this.triggerFocusSubscription = triggerFocus.subscribe((pointerType) => {
  1072. this.focusPointer(pointerType);
  1073. });
  1074. }
  1075. /**
  1076. * @return {?}
  1077. */
  1078. get range() {
  1079. return !ValueHelper.isNullOrUndefined(this.value) && !ValueHelper.isNullOrUndefined(this.highValue);
  1080. }
  1081. /**
  1082. * @return {?}
  1083. */
  1084. get showTicks() {
  1085. return this.viewOptions.showTicks;
  1086. }
  1087. /**
  1088. * @return {?}
  1089. */
  1090. ngOnInit() {
  1091. this.viewOptions = new Options();
  1092. Object.assign(this.viewOptions, this.options);
  1093. // We need to run these two things first, before the rest of the init in ngAfterViewInit(),
  1094. // because these two settings are set through @HostBinding and Angular change detection
  1095. // mechanism doesn't like them changing in ngAfterViewInit()
  1096. this.updateDisabledState();
  1097. this.updateVerticalState();
  1098. }
  1099. /**
  1100. * @return {?}
  1101. */
  1102. ngAfterViewInit() {
  1103. this.applyOptions();
  1104. this.subscribeInputModelChangeSubject(this.viewOptions.inputEventsInterval);
  1105. this.subscribeOutputModelChangeSubject(this.viewOptions.outputEventsInterval);
  1106. // Once we apply options, we need to normalise model values for the first time
  1107. this.renormaliseModelValues();
  1108. this.viewLowValue = this.modelValueToViewValue(this.value);
  1109. if (this.range) {
  1110. this.viewHighValue = this.modelValueToViewValue(this.highValue);
  1111. }
  1112. else {
  1113. this.viewHighValue = null;
  1114. }
  1115. this.updateVerticalState(); // need to run this again to cover changes to slider elements
  1116. this.manageElementsStyle();
  1117. this.updateDisabledState();
  1118. this.calculateViewDimensions();
  1119. this.addAccessibility();
  1120. this.updateCeilLabel();
  1121. this.updateFloorLabel();
  1122. this.initHandles();
  1123. this.manageEventsBindings();
  1124. this.subscribeResizeObserver();
  1125. this.initHasRun = true;
  1126. // Run change detection manually to resolve some issues when init procedure changes values used in the view
  1127. this.changeDetectionRef.detectChanges();
  1128. }
  1129. /**
  1130. * @param {?} changes
  1131. * @return {?}
  1132. */
  1133. ngOnChanges(changes) {
  1134. // Always apply options first
  1135. if (!ValueHelper.isNullOrUndefined(changes["options"])) {
  1136. this.onChangeOptions();
  1137. }
  1138. // Then value changes
  1139. if (!ValueHelper.isNullOrUndefined(changes["value"]) ||
  1140. !ValueHelper.isNullOrUndefined(changes["highValue"])) {
  1141. this.inputModelChangeSubject.next({
  1142. value: this.value,
  1143. highValue: this.highValue,
  1144. forceChange: false,
  1145. internalChange: false
  1146. });
  1147. }
  1148. }
  1149. /**
  1150. * @return {?}
  1151. */
  1152. ngOnDestroy() {
  1153. this.unbindEvents();
  1154. this.unsubscribeResizeObserver();
  1155. this.unsubscribeInputModelChangeSubject();
  1156. this.unsubscribeOutputModelChangeSubject();
  1157. this.unsubscribeManualRefresh();
  1158. this.unsubscribeTriggerFocus();
  1159. }
  1160. /**
  1161. * @param {?} obj
  1162. * @return {?}
  1163. */
  1164. writeValue(obj) {
  1165. if (obj instanceof Array) {
  1166. this.value = obj[0];
  1167. this.highValue = obj[1];
  1168. }
  1169. else {
  1170. this.value = obj;
  1171. }
  1172. // ngOnChanges() is not called in this instance, so we need to communicate the change manually
  1173. this.inputModelChangeSubject.next({
  1174. value: this.value,
  1175. highValue: this.highValue,
  1176. forceChange: false,
  1177. internalChange: false
  1178. });
  1179. }
  1180. /**
  1181. * @param {?} onChangeCallback
  1182. * @return {?}
  1183. */
  1184. registerOnChange(onChangeCallback) {
  1185. this.onChangeCallback = onChangeCallback;
  1186. }
  1187. /**
  1188. * @param {?} onTouchedCallback
  1189. * @return {?}
  1190. */
  1191. registerOnTouched(onTouchedCallback) {
  1192. this.onTouchedCallback = onTouchedCallback;
  1193. }
  1194. /**
  1195. * @param {?} isDisabled
  1196. * @return {?}
  1197. */
  1198. setDisabledState(isDisabled) {
  1199. this.viewOptions.disabled = isDisabled;
  1200. this.updateDisabledState();
  1201. }
  1202. /**
  1203. * @param {?} event
  1204. * @return {?}
  1205. */
  1206. onResize(event) {
  1207. this.calculateViewDimensionsAndDetectChanges();
  1208. }
  1209. /**
  1210. * @param {?=} interval
  1211. * @return {?}
  1212. */
  1213. subscribeInputModelChangeSubject(interval) {
  1214. this.inputModelChangeSubscription = this.inputModelChangeSubject
  1215. .pipe(distinctUntilChanged(ModelChange.compare),
  1216. // Hack to reset the status of the distinctUntilChanged() - if a "fake" event comes through with forceChange=true,
  1217. // we forcefully by-pass distinctUntilChanged(), but otherwise drop the event
  1218. filter((modelChange) => !modelChange.forceChange && !modelChange.internalChange), (!ValueHelper.isNullOrUndefined(interval))
  1219. ? throttleTime(interval, undefined, { leading: true, trailing: true })
  1220. : tap(() => { }) // no-op
  1221. )
  1222. .subscribe((modelChange) => this.applyInputModelChange(modelChange));
  1223. }
  1224. /**
  1225. * @param {?=} interval
  1226. * @return {?}
  1227. */
  1228. subscribeOutputModelChangeSubject(interval) {
  1229. this.outputModelChangeSubscription = this.outputModelChangeSubject
  1230. .pipe(distinctUntilChanged(ModelChange.compare), (!ValueHelper.isNullOrUndefined(interval))
  1231. ? throttleTime(interval, undefined, { leading: true, trailing: true })
  1232. : tap(() => { }) // no-op
  1233. )
  1234. .subscribe((modelChange) => this.publishOutputModelChange(modelChange));
  1235. }
  1236. /**
  1237. * @return {?}
  1238. */
  1239. subscribeResizeObserver() {
  1240. if (CompatibilityHelper.isResizeObserverAvailable()) {
  1241. this.resizeObserver = new ResizeObserver(() => this.calculateViewDimensionsAndDetectChanges());
  1242. this.resizeObserver.observe(this.elementRef.nativeElement);
  1243. }
  1244. }
  1245. /**
  1246. * @return {?}
  1247. */
  1248. unsubscribeResizeObserver() {
  1249. if (CompatibilityHelper.isResizeObserverAvailable() && this.resizeObserver !== null) {
  1250. this.resizeObserver.disconnect();
  1251. this.resizeObserver = null;
  1252. }
  1253. }
  1254. /**
  1255. * @return {?}
  1256. */
  1257. unsubscribeOnMove() {
  1258. if (!ValueHelper.isNullOrUndefined(this.onMoveEventListener)) {
  1259. this.eventListenerHelper.detachEventListener(this.onMoveEventListener);
  1260. this.onMoveEventListener = null;
  1261. }
  1262. }
  1263. /**
  1264. * @return {?}
  1265. */
  1266. unsubscribeOnEnd() {
  1267. if (!ValueHelper.isNullOrUndefined(this.onEndEventListener)) {
  1268. this.eventListenerHelper.detachEventListener(this.onEndEventListener);
  1269. this.onEndEventListener = null;
  1270. }
  1271. }
  1272. /**
  1273. * @return {?}
  1274. */
  1275. unsubscribeInputModelChangeSubject() {
  1276. if (!ValueHelper.isNullOrUndefined(this.inputModelChangeSubscription)) {
  1277. this.inputModelChangeSubscription.unsubscribe();
  1278. this.inputModelChangeSubscription = null;
  1279. }
  1280. }
  1281. /**
  1282. * @return {?}
  1283. */
  1284. unsubscribeOutputModelChangeSubject() {
  1285. if (!ValueHelper.isNullOrUndefined(this.outputModelChangeSubscription)) {
  1286. this.outputModelChangeSubscription.unsubscribe();
  1287. this.outputModelChangeSubscription = null;
  1288. }
  1289. }
  1290. /**
  1291. * @return {?}
  1292. */
  1293. unsubscribeManualRefresh() {
  1294. if (!ValueHelper.isNullOrUndefined(this.manualRefreshSubscription)) {
  1295. this.manualRefreshSubscription.unsubscribe();
  1296. this.manualRefreshSubscription = null;
  1297. }
  1298. }
  1299. /**
  1300. * @return {?}
  1301. */
  1302. unsubscribeTriggerFocus() {
  1303. if (!ValueHelper.isNullOrUndefined(this.triggerFocusSubscription)) {
  1304. this.triggerFocusSubscription.unsubscribe();
  1305. this.triggerFocusSubscription = null;
  1306. }
  1307. }
  1308. /**
  1309. * @param {?} pointerType
  1310. * @return {?}
  1311. */
  1312. getPointerElement(pointerType) {
  1313. if (pointerType === PointerType.Min) {
  1314. return this.minHandleElement;
  1315. }
  1316. else if (pointerType === PointerType.Max) {
  1317. return this.maxHandleElement;
  1318. }
  1319. return null;
  1320. }
  1321. /**
  1322. * @return {?}
  1323. */
  1324. getCurrentTrackingValue() {
  1325. if (this.currentTrackingPointer === PointerType.Min) {
  1326. return this.viewLowValue;
  1327. }
  1328. else if (this.currentTrackingPointer === PointerType.Max) {
  1329. return this.viewHighValue;
  1330. }
  1331. return null;
  1332. }
  1333. /**
  1334. * @param {?} modelValue
  1335. * @return {?}
  1336. */
  1337. modelValueToViewValue(modelValue) {
  1338. if (ValueHelper.isNullOrUndefined(modelValue)) {
  1339. return NaN;
  1340. }
  1341. if (!ValueHelper.isNullOrUndefined(this.viewOptions.stepsArray) && !this.viewOptions.bindIndexForStepsArray) {
  1342. return ValueHelper.findStepIndex(+modelValue, this.viewOptions.stepsArray);
  1343. }
  1344. return +modelValue;
  1345. }
  1346. /**
  1347. * @param {?} viewValue
  1348. * @return {?}
  1349. */
  1350. viewValueToModelValue(viewValue) {
  1351. if (!ValueHelper.isNullOrUndefined(this.viewOptions.stepsArray) && !this.viewOptions.bindIndexForStepsArray) {
  1352. return this.getStepValue(viewValue);
  1353. }
  1354. return viewValue;
  1355. }
  1356. /**
  1357. * @param {?} sliderValue
  1358. * @return {?}
  1359. */
  1360. getStepValue(sliderValue) {
  1361. const /** @type {?} */ step = this.viewOptions.stepsArray[sliderValue];
  1362. return (!ValueHelper.isNullOrUndefined(step)) ? step.value : NaN;
  1363. }
  1364. /**
  1365. * @return {?}
  1366. */
  1367. applyViewChange() {
  1368. this.value = this.viewValueToModelValue(this.viewLowValue);
  1369. if (this.range) {
  1370. this.highValue = this.viewValueToModelValue(this.viewHighValue);
  1371. }
  1372. this.outputModelChangeSubject.next({
  1373. value: this.value,
  1374. highValue: this.highValue,
  1375. userEventInitiated: true,
  1376. forceChange: false
  1377. });
  1378. // At this point all changes are applied and outputs are emitted, so we should be done.
  1379. // However, input changes are communicated in different stream and we need to be ready to
  1380. // act on the next input change even if it is exactly the same as last input change.
  1381. // Therefore, we send a special event to reset the stream.
  1382. this.inputModelChangeSubject.next({
  1383. value: this.value,
  1384. highValue: this.highValue,
  1385. forceChange: false,
  1386. internalChange: true
  1387. });
  1388. }
  1389. /**
  1390. * @param {?} modelChange
  1391. * @return {?}
  1392. */
  1393. applyInputModelChange(modelChange) {
  1394. const /** @type {?} */ normalisedModelChange = this.normaliseModelValues(modelChange);
  1395. // If normalised model change is different, apply the change to the model values
  1396. const /** @type {?} */ normalisationChange = !ModelValues.compare(modelChange, normalisedModelChange);
  1397. if (normalisationChange) {
  1398. this.value = normalisedModelChange.value;
  1399. this.highValue = normalisedModelChange.highValue;
  1400. }
  1401. this.viewLowValue = this.modelValueToViewValue(normalisedModelChange.value);
  1402. if (this.range) {
  1403. this.viewHighValue = this.modelValueToViewValue(normalisedModelChange.highValue);
  1404. }
  1405. else {
  1406. this.viewHighValue = null;
  1407. }
  1408. this.updateLowHandle(this.valueToPosition(this.viewLowValue));
  1409. if (this.range) {
  1410. this.updateHighHandle(this.valueToPosition(this.viewHighValue));
  1411. }
  1412. this.updateSelectionBar();
  1413. this.updateTicksScale();
  1414. this.updateAriaAttributes();
  1415. if (this.range) {
  1416. this.updateCombinedLabel();
  1417. }
  1418. // At the end, we need to communicate the model change to the outputs as well
  1419. // Normalisation changes are also always forced out to ensure that subscribers always end up in correct state
  1420. this.outputModelChangeSubject.next({
  1421. value: normalisedModelChange.value,
  1422. highValue: normalisedModelChange.highValue,
  1423. forceChange: normalisationChange,
  1424. userEventInitiated: false
  1425. });
  1426. }
  1427. /**
  1428. * @param {?} modelChange
  1429. * @return {?}
  1430. */
  1431. publishOutputModelChange(modelChange) {
  1432. const /** @type {?} */ emitOutputs = () => {
  1433. this.valueChange.emit(modelChange.value);
  1434. if (this.range) {
  1435. this.highValueChange.emit(modelChange.highValue);
  1436. }
  1437. if (!ValueHelper.isNullOrUndefined(this.onChangeCallback)) {
  1438. if (this.range) {
  1439. this.onChangeCallback([modelChange.value, modelChange.highValue]);
  1440. }
  1441. else {
  1442. this.onChangeCallback(modelChange.value);
  1443. }
  1444. }
  1445. if (!ValueHelper.isNullOrUndefined(this.onTouchedCallback)) {
  1446. if (this.range) {
  1447. this.onTouchedCallback([modelChange.value, modelChange.highValue]);
  1448. }
  1449. else {
  1450. this.onTouchedCallback(modelChange.value);
  1451. }
  1452. }
  1453. };
  1454. if (modelChange.userEventInitiated) {
  1455. // If this change was initiated by a user event, we can emit outputs in the same tick
  1456. emitOutputs();
  1457. this.userChange.emit(this.getChangeContext());
  1458. }
  1459. else {
  1460. // But, if the change was initated by something else like a change in input bindings,
  1461. // we need to wait until next tick to emit the outputs to keep Angular change detection happy
  1462. setTimeout(() => { emitOutputs(); });
  1463. }
  1464. }
  1465. /**
  1466. * @param {?} input
  1467. * @return {?}
  1468. */
  1469. normaliseModelValues(input) {
  1470. const /** @type {?} */ normalisedInput = new ModelValues();
  1471. normalisedInput.value = input.value;
  1472. normalisedInput.highValue = input.highValue;
  1473. if (this.viewOptions.enforceStep) {
  1474. normalisedInput.value = this.roundStep(normalisedInput.value);
  1475. if (this.range) {
  1476. normalisedInput.highValue = this.roundStep(normalisedInput.highValue);
  1477. }
  1478. }
  1479. // Don't attempt to normalise further when using steps array (steps may be out of order and that is perfectly fine)
  1480. if (!ValueHelper.isNullOrUndefined(this.viewOptions.stepsArray) || !this.viewOptions.enforceRange) {
  1481. return normalisedInput;
  1482. }
  1483. normalisedInput.value = MathHelper.clampToRange(normalisedInput.value, this.viewOptions.floor, this.viewOptions.ceil);
  1484. if (this.range) {
  1485. normalisedInput.highValue = MathHelper.clampToRange(normalisedInput.highValue, this.viewOptions.floor, this.viewOptions.ceil);
  1486. }
  1487. // Make sure that range slider invariant (value <= highValue) is always satisfied
  1488. if (this.range && input.value > input.highValue) {
  1489. // We know that both values are now clamped correctly, they may just be in the wrong order
  1490. // So the easy solution is to swap them... except swapping is sometimes disabled in options, so we make the two values the same
  1491. if (this.viewOptions.noSwitching) {
  1492. normalisedInput.value = normalisedInput.highValue;
  1493. }
  1494. else {
  1495. const /** @type {?} */ tempValue = input.value;
  1496. normalisedInput.value = input.highValue;
  1497. normalisedInput.highValue = tempValue;
  1498. }
  1499. }
  1500. return normalisedInput;
  1501. }
  1502. /**
  1503. * @return {?}
  1504. */
  1505. renormaliseModelValues() {
  1506. const /** @type {?} */ previousModelValues = {
  1507. value: this.value,
  1508. highValue: this.highValue
  1509. };
  1510. const /** @type {?} */ normalisedModelValues = this.normaliseModelValues(previousModelValues);
  1511. if (!ModelValues.compare(normalisedModelValues, previousModelValues)) {
  1512. this.value = normalisedModelValues.value;
  1513. this.highValue = normalisedModelValues.highValue;
  1514. this.outputModelChangeSubject.next({
  1515. value: this.value,
  1516. highValue: this.highValue,
  1517. forceChange: true,
  1518. userEventInitiated: false
  1519. });
  1520. }
  1521. }
  1522. /**
  1523. * @return {?}
  1524. */
  1525. onChangeOptions() {
  1526. if (!this.initHasRun) {
  1527. return;
  1528. }
  1529. const /** @type {?} */ previousInputEventsInterval = this.viewOptions.inputEventsInterval;
  1530. const /** @type {?} */ previousOutputEventsInterval = this.viewOptions.outputEventsInterval;
  1531. this.applyOptions();
  1532. if (previousInputEventsInterval !== this.viewOptions.inputEventsInterval) {
  1533. this.unsubscribeInputModelChangeSubject();
  1534. this.subscribeInputModelChangeSubject(this.viewOptions.inputEventsInterval);
  1535. }
  1536. if (previousOutputEventsInterval !== this.viewOptions.outputEventsInterval) {
  1537. this.unsubscribeInputModelChangeSubject();
  1538. this.subscribeInputModelChangeSubject(this.viewOptions.outputEventsInterval);
  1539. }
  1540. // With new options, we need to re-normalise model values if necessary
  1541. this.renormaliseModelValues();
  1542. this.viewLowValue = this.modelValueToViewValue(this.value);
  1543. if (this.range) {
  1544. this.viewHighValue = this.modelValueToViewValue(this.highValue);
  1545. }
  1546. else {
  1547. this.viewHighValue = null;
  1548. }
  1549. this.resetSlider();
  1550. }
  1551. /**
  1552. * @return {?}
  1553. */
  1554. applyOptions() {
  1555. this.viewOptions = new Options();
  1556. Object.assign(this.viewOptions, this.options);
  1557. this.viewOptions.draggableRange = this.range && this.viewOptions.draggableRange;
  1558. this.viewOptions.draggableRangeOnly = this.range && this.viewOptions.draggableRangeOnly;
  1559. if (this.viewOptions.draggableRangeOnly) {
  1560. this.viewOptions.draggableRange = true;
  1561. }
  1562. this.viewOptions.showTicks = this.viewOptions.showTicks ||
  1563. this.viewOptions.showTicksValues ||
  1564. !ValueHelper.isNullOrUndefined(this.viewOptions.ticksArray);
  1565. if (this.viewOptions.showTicks &&
  1566. (!ValueHelper.isNullOrUndefined(this.viewOptions.tickStep) || !ValueHelper.isNullOrUndefined(this.viewOptions.ticksArray))) {
  1567. this.intermediateTicks = true;
  1568. }
  1569. this.viewOptions.showSelectionBar = this.viewOptions.showSelectionBar ||
  1570. this.viewOptions.showSelectionBarEnd ||
  1571. !ValueHelper.isNullOrUndefined(this.viewOptions.showSelectionBarFromValue);
  1572. if (!ValueHelper.isNullOrUndefined(this.viewOptions.stepsArray)) {
  1573. this.applyStepsArrayOptions();
  1574. }
  1575. else {
  1576. this.applyFloorCeilOptions();
  1577. }
  1578. if (ValueHelper.isNullOrUndefined(this.viewOptions.combineLabels)) {
  1579. this.viewOptions.combineLabels = (minValue, maxValue) => {
  1580. return minValue + ' - ' + maxValue;
  1581. };
  1582. }
  1583. if (this.viewOptions.logScale && this.viewOptions.floor === 0) {
  1584. throw Error('Can\'t use floor=0 with logarithmic scale');
  1585. }
  1586. }
  1587. /**
  1588. * @return {?}
  1589. */
  1590. applyStepsArrayOptions() {
  1591. this.viewOptions.floor = 0;
  1592. this.viewOptions.ceil = this.viewOptions.stepsArray.length - 1;
  1593. this.viewOptions.step = 1;
  1594. if (ValueHelper.isNullOrUndefined(this.viewOptions.translate)) {
  1595. this.viewOptions.translate = (modelValue) => {
  1596. if (this.viewOptions.bindIndexForStepsArray) {
  1597. return String(this.getStepValue(modelValue));
  1598. }
  1599. return String(modelValue);
  1600. };
  1601. }
  1602. this.viewOptions.getLegend = (index) => {
  1603. const /** @type {?} */ step = this.viewOptions.stepsArray[index];
  1604. return step.legend;
  1605. };
  1606. }
  1607. /**
  1608. * @return {?}
  1609. */
  1610. applyFloorCeilOptions() {
  1611. if (ValueHelper.isNullOrUndefined(this.viewOptions.step)) {
  1612. this.viewOptions.step = 1;
  1613. }
  1614. else {
  1615. this.viewOptions.step = +this.viewOptions.step;
  1616. if (this.viewOptions.step <= 0) {
  1617. this.viewOptions.step = 1;
  1618. }
  1619. }
  1620. if (ValueHelper.isNullOrUndefined(this.viewOptions.ceil) ||
  1621. ValueHelper.isNullOrUndefined(this.viewOptions.floor)) {
  1622. throw Error('floor and ceil options must be supplied');
  1623. }
  1624. this.viewOptions.ceil = +this.viewOptions.ceil;
  1625. this.viewOptions.floor = +this.viewOptions.floor;
  1626. if (ValueHelper.isNullOrUndefined(this.viewOptions.translate)) {
  1627. this.viewOptions.translate = (value) => String(value);
  1628. }
  1629. }
  1630. /**
  1631. * @return {?}
  1632. */
  1633. resetSlider() {
  1634. this.manageElementsStyle();
  1635. this.addAccessibility();
  1636. this.updateCeilLabel();
  1637. this.updateFloorLabel();
  1638. this.unbindEvents();
  1639. this.manageEventsBindings();
  1640. this.updateDisabledState();
  1641. this.calculateViewDimensions();
  1642. this.refocusPointerIfNeeded();
  1643. }
  1644. /**
  1645. * @param {?} pointerType
  1646. * @return {?}
  1647. */
  1648. focusPointer(pointerType) {
  1649. // If not supplied, use min pointer as default
  1650. if (pointerType !== PointerType.Min && pointerType !== PointerType.Max) {
  1651. pointerType = PointerType.Min;
  1652. }
  1653. if (pointerType === PointerType.Min) {
  1654. this.minHandleElement.focus();
  1655. }
  1656. else if (this.range && pointerType === PointerType.Max) {
  1657. this.maxHandleElement.focus();
  1658. }
  1659. }
  1660. /**
  1661. * @return {?}
  1662. */
  1663. refocusPointerIfNeeded() {
  1664. if (!ValueHelper.isNullOrUndefined(this.currentFocusPointer)) {
  1665. this.onPointerFocus(this.currentFocusPointer);
  1666. const /** @type {?} */ element = this.getPointerElement(this.currentFocusPointer);
  1667. element.focus();
  1668. }
  1669. }
  1670. /**
  1671. * @return {?}
  1672. */
  1673. manageElementsStyle() {
  1674. this.updateScale();
  1675. this.floorLabelElement.setAlwaysHide(this.viewOptions.showTicksValues || this.viewOptions.hideLimitLabels);
  1676. this.ceilLabelElement.setAlwaysHide(this.viewOptions.showTicksValues || this.viewOptions.hideLimitLabels);
  1677. const /** @type {?} */ hideLabelsForTicks = this.viewOptions.showTicksValues && !this.intermediateTicks;
  1678. this.minHandleLabelElement.setAlwaysHide(hideLabelsForTicks || this.viewOptions.hidePointerLabels);
  1679. this.maxHandleLabelElement.setAlwaysHide(hideLabelsForTicks || !this.range || this.viewOptions.hidePointerLabels);
  1680. this.combinedLabelElement.setAlwaysHide(hideLabelsForTicks || !this.range || this.viewOptions.hidePointerLabels);
  1681. this.selectionBarElement.setAlwaysHide(!this.range && !this.viewOptions.showSelectionBar);
  1682. this.leftOuterSelectionBarElement.setAlwaysHide(!this.range || !this.viewOptions.showOuterSelectionBars);
  1683. this.rightOuterSelectionBarElement.setAlwaysHide(!this.range || !this.viewOptions.showOuterSelectionBars);
  1684. this.fullBarTransparentClass = this.range && this.viewOptions.showOuterSelectionBars;
  1685. this.selectionBarDraggableClass = this.viewOptions.draggableRange && !this.viewOptions.onlyBindHandles;
  1686. this.ticksUnderValuesClass = this.intermediateTicks && this.options.showTicksValues;
  1687. if (this.sliderElementVerticalClass !== this.viewOptions.vertical) {
  1688. this.updateVerticalState();
  1689. // The above change in host component class will not be applied until the end of this cycle
  1690. // However, functions calculating the slider position expect the slider to be already styled as vertical
  1691. // So as a workaround, we need to reset the slider once again to compute the correct values
  1692. setTimeout(() => { this.resetSlider(); });
  1693. }
  1694. // Changing animate class may interfere with slider reset/initialisation, so we should set it separately,
  1695. // after all is properly set up
  1696. if (this.sliderElementAnimateClass !== this.viewOptions.animate) {
  1697. setTimeout(() => { this.sliderElementAnimateClass = this.viewOptions.animate; });
  1698. }
  1699. }
  1700. /**
  1701. * @return {?}
  1702. */
  1703. manageEventsBindings() {
  1704. if (this.viewOptions.disabled || this.viewOptions.readOnly) {
  1705. this.unbindEvents();
  1706. }
  1707. else {
  1708. this.bindEvents();
  1709. }
  1710. }
  1711. /**
  1712. * @return {?}
  1713. */
  1714. updateDisabledState() {
  1715. this.sliderElementDisabledAttr = this.viewOptions.disabled ? 'disabled' : null;
  1716. }
  1717. /**
  1718. * @return {?}
  1719. */
  1720. updateVerticalState() {
  1721. this.sliderElementVerticalClass = this.viewOptions.vertical;
  1722. for (const /** @type {?} */ element of this.getAllSliderElements()) {
  1723. // This is also called before ngAfterInit, so need to check that view child bindings work
  1724. if (!ValueHelper.isNullOrUndefined(element)) {
  1725. element.setVertical(this.viewOptions.vertical);
  1726. }
  1727. }
  1728. }
  1729. /**
  1730. * @return {?}
  1731. */
  1732. updateScale() {
  1733. for (const /** @type {?} */ element of this.getAllSliderElements()) {
  1734. element.setScale(this.viewOptions.scale);
  1735. }
  1736. }
  1737. /**
  1738. * @return {?}
  1739. */
  1740. getAllSliderElements() {
  1741. return [this.leftOuterSelectionBarElement,
  1742. this.rightOuterSelectionBarElement,
  1743. this.fullBarElement,
  1744. this.selectionBarElement,
  1745. this.minHandleElement,
  1746. this.maxHandleElement,
  1747. this.floorLabelElement,
  1748. this.ceilLabelElement,
  1749. this.minHandleLabelElement,
  1750. this.maxHandleLabelElement,
  1751. this.combinedLabelElement,
  1752. this.ticksElement
  1753. ];
  1754. }
  1755. /**
  1756. * @return {?}
  1757. */
  1758. initHandles() {
  1759. this.updateLowHandle(this.valueToPosition(this.viewLowValue));
  1760. /*
  1761. the order here is important since the selection bar should be
  1762. updated after the high handle but before the combined label
  1763. */
  1764. if (this.range) {
  1765. this.updateHighHandle(this.valueToPosition(this.viewHighValue));
  1766. }
  1767. this.updateSelectionBar();
  1768. if (this.range) {
  1769. this.updateCombinedLabel();
  1770. }
  1771. this.updateTicksScale();
  1772. }
  1773. /**
  1774. * @return {?}
  1775. */
  1776. addAccessibility() {
  1777. this.updateAriaAttributes();
  1778. this.minHandleElement.role = 'slider';
  1779. if (this.viewOptions.keyboardSupport &&
  1780. !(this.viewOptions.readOnly || this.viewOptions.disabled)) {
  1781. this.minHandleElement.tabindex = '0';
  1782. }
  1783. else {
  1784. this.minHandleElement.tabindex = '';
  1785. }
  1786. if (this.viewOptions.vertical) {
  1787. this.minHandleElement.ariaOrientation = 'vertical';
  1788. }
  1789. if (!ValueHelper.isNullOrUndefined(this.viewOptions.ariaLabel)) {
  1790. this.minHandleElement.ariaLabel = this.viewOptions.ariaLabel;
  1791. }
  1792. else if (!ValueHelper.isNullOrUndefined(this.viewOptions.ariaLabelledBy)) {
  1793. this.minHandleElement.ariaLabelledBy = this.viewOptions.ariaLabelledBy;
  1794. }
  1795. if (this.range) {
  1796. this.maxHandleElement.role = 'slider';
  1797. if (this.viewOptions.keyboardSupport &&
  1798. !(this.viewOptions.readOnly || this.viewOptions.disabled)) {
  1799. this.maxHandleElement.tabindex = '0';
  1800. }
  1801. else {
  1802. this.maxHandleElement.tabindex = '';
  1803. }
  1804. this.maxHandleElement.ariaOrientation = this.viewOptions.vertical ? 'vertical' : 'horizontal';
  1805. if (!ValueHelper.isNullOrUndefined(this.viewOptions.ariaLabelHigh)) {
  1806. this.maxHandleElement.ariaLabel = this.viewOptions.ariaLabelHigh;
  1807. }
  1808. else if (!ValueHelper.isNullOrUndefined(this.viewOptions.ariaLabelledByHigh)) {
  1809. this.maxHandleElement.ariaLabelledBy = this.viewOptions.ariaLabelledByHigh;
  1810. }
  1811. }
  1812. }
  1813. /**
  1814. * @return {?}
  1815. */
  1816. updateAriaAttributes() {
  1817. this.minHandleElement.ariaValueNow = (+this.value).toString();
  1818. this.minHandleElement.ariaValueText = this.viewOptions.translate(+this.value, LabelType.Low);
  1819. this.minHandleElement.ariaValueMin = this.viewOptions.floor.toString();
  1820. this.minHandleElement.ariaValueMax = this.viewOptions.ceil.toString();
  1821. if (this.range) {
  1822. this.maxHandleElement.ariaValueNow = (+this.highValue).toString();
  1823. this.maxHandleElement.ariaValueText = this.viewOptions.translate(+this.highValue, LabelType.High);
  1824. this.maxHandleElement.ariaValueMin = this.viewOptions.floor.toString();
  1825. this.maxHandleElement.ariaValueMax = this.viewOptions.ceil.toString();
  1826. }
  1827. }
  1828. /**
  1829. * @return {?}
  1830. */
  1831. calculateViewDimensions() {
  1832. if (!ValueHelper.isNullOrUndefined(this.viewOptions.handleDimension)) {
  1833. this.minHandleElement.setDimension(this.viewOptions.handleDimension);
  1834. }
  1835. else {
  1836. this.minHandleElement.calculateDimension();
  1837. }
  1838. const /** @type {?} */ handleWidth = this.minHandleElement.dimension;
  1839. this.handleHalfDimension = handleWidth / 2;
  1840. if (!ValueHelper.isNullOrUndefined(this.viewOptions.barDimension)) {
  1841. this.fullBarElement.setDimension(this.viewOptions.barDimension);
  1842. }
  1843. else {
  1844. this.fullBarElement.calculateDimension();
  1845. }
  1846. this.maxHandlePosition = this.fullBarElement.dimension - handleWidth;
  1847. if (this.initHasRun) {
  1848. this.updateFloorLabel();
  1849. this.updateCeilLabel();
  1850. this.initHandles();
  1851. }
  1852. }
  1853. /**
  1854. * @return {?}
  1855. */
  1856. calculateViewDimensionsAndDetectChanges() {
  1857. this.calculateViewDimensions();
  1858. this.changeDetectionRef.detectChanges();
  1859. }
  1860. /**
  1861. * @return {?}
  1862. */
  1863. updateTicksScale() {
  1864. if (!this.viewOptions.showTicks) {
  1865. return;
  1866. }
  1867. const /** @type {?} */ ticksArray = !ValueHelper.isNullOrUndefined(this.viewOptions.ticksArray)
  1868. ? this.viewOptions.ticksArray
  1869. : this.getTicksArray();
  1870. const /** @type {?} */ translate = this.viewOptions.vertical ? 'translateY' : 'translateX';
  1871. if (this.viewOptions.rightToLeft) {
  1872. ticksArray.reverse();
  1873. }
  1874. const /** @type {?} */ newTicks = ticksArray.map((value) => {
  1875. let /** @type {?} */ position = this.valueToPosition(value);
  1876. if (this.viewOptions.vertical) {
  1877. position = this.maxHandlePosition - position;
  1878. }
  1879. const /** @type {?} */ translation = translate + '(' + Math.round(position) + 'px)';
  1880. const /** @type {?} */ tick = new Tick();
  1881. tick.selected = this.isTickSelected(value);
  1882. tick.style = {
  1883. '-webkit-transform': translation,
  1884. '-moz-transform': translation,
  1885. '-o-transform': translation,
  1886. '-ms-transform': translation,
  1887. transform: translation,
  1888. };
  1889. if (tick.selected && !ValueHelper.isNullOrUndefined(this.viewOptions.getSelectionBarColor)) {
  1890. tick.style['background-color'] = this.getSelectionBarColor();
  1891. }
  1892. if (!tick.selected && !ValueHelper.isNullOrUndefined(this.viewOptions.getTickColor)) {
  1893. tick.style['background-color'] = this.getTickColor(value);
  1894. }
  1895. if (!ValueHelper.isNullOrUndefined(this.viewOptions.ticksTooltip)) {
  1896. tick.tooltip = this.viewOptions.ticksTooltip(value);
  1897. tick.tooltipPlacement = this.viewOptions.vertical ? 'right' : 'top';
  1898. }
  1899. if (this.viewOptions.showTicksValues && (value % this.viewOptions.tickValueStep === 0)) {
  1900. tick.value = this.getDisplayValue(value, LabelType.TickValue);
  1901. if (!ValueHelper.isNullOrUndefined(this.viewOptions.ticksValuesTooltip)) {
  1902. tick.valueTooltip = this.viewOptions.ticksValuesTooltip(value);
  1903. tick.valueTooltipPlacement = this.viewOptions.vertical
  1904. ? 'right'
  1905. : 'top';
  1906. }
  1907. }
  1908. if (!ValueHelper.isNullOrUndefined(this.viewOptions.getLegend)) {
  1909. const /** @type {?} */ legend = this.viewOptions.getLegend(value);
  1910. if (!ValueHelper.isNullOrUndefined(legend)) {
  1911. tick.legend = legend;
  1912. }
  1913. }
  1914. return tick;
  1915. });
  1916. // We should avoid re-creating the ticks array if possible
  1917. // This both improves performance and makes CSS animations work correctly
  1918. if (!ValueHelper.isNullOrUndefined(this.ticks) && this.ticks.length === newTicks.length) {
  1919. for (let /** @type {?} */ i = 0; i < newTicks.length; ++i) {
  1920. Object.assign(this.ticks[i], newTicks[i]);
  1921. }
  1922. }
  1923. else {
  1924. this.ticks = newTicks;
  1925. }
  1926. this.changeDetectionRef.detectChanges();
  1927. }
  1928. /**
  1929. * @return {?}
  1930. */
  1931. getTicksArray() {
  1932. const /** @type {?} */ step = (!ValueHelper.isNullOrUndefined(this.viewOptions.tickStep)) ? this.viewOptions.tickStep : this.viewOptions.step;
  1933. const /** @type {?} */ ticksArray = [];
  1934. for (let /** @type {?} */ value = this.viewOptions.floor; value <= this.viewOptions.ceil; value += step) {
  1935. ticksArray.push(value);
  1936. }
  1937. return ticksArray;
  1938. }
  1939. /**
  1940. * @param {?} value
  1941. * @return {?}
  1942. */
  1943. isTickSelected(value) {
  1944. if (!this.range) {
  1945. if (!ValueHelper.isNullOrUndefined(this.viewOptions.showSelectionBarFromValue)) {
  1946. const /** @type {?} */ center = this.viewOptions.showSelectionBarFromValue;
  1947. if (this.viewLowValue > center &&
  1948. value >= center &&
  1949. value <= this.viewLowValue) {
  1950. return true;
  1951. }
  1952. else if (this.viewLowValue < center &&
  1953. value <= center &&
  1954. value >= this.viewLowValue) {
  1955. return true;
  1956. }
  1957. }
  1958. else if (this.viewOptions.showSelectionBarEnd) {
  1959. if (value >= this.viewLowValue) {
  1960. return true;
  1961. }
  1962. }
  1963. else if (this.viewOptions.showSelectionBar && value <= this.viewLowValue) {
  1964. return true;
  1965. }
  1966. }
  1967. if (this.range && value >= this.viewLowValue && value <= this.viewHighValue) {
  1968. return true;
  1969. }
  1970. return false;
  1971. }
  1972. /**
  1973. * @return {?}
  1974. */
  1975. updateFloorLabel() {
  1976. if (!this.floorLabelElement.alwaysHide) {
  1977. this.floorLabelElement.setValue(this.getDisplayValue(this.viewOptions.floor, LabelType.Floor));
  1978. this.floorLabelElement.calculateDimension();
  1979. const /** @type {?} */ position = this.viewOptions.rightToLeft
  1980. ? this.fullBarElement.dimension - this.floorLabelElement.dimension
  1981. : 0;
  1982. this.floorLabelElement.setPosition(position);
  1983. }
  1984. }
  1985. /**
  1986. * @return {?}
  1987. */
  1988. updateCeilLabel() {
  1989. if (!this.ceilLabelElement.alwaysHide) {
  1990. this.ceilLabelElement.setValue(this.getDisplayValue(this.viewOptions.ceil, LabelType.Ceil));
  1991. this.ceilLabelElement.calculateDimension();
  1992. const /** @type {?} */ position = this.viewOptions.rightToLeft
  1993. ? 0
  1994. : this.fullBarElement.dimension - this.ceilLabelElement.dimension;
  1995. this.ceilLabelElement.setPosition(position);
  1996. }
  1997. }
  1998. /**
  1999. * @param {?} which
  2000. * @param {?} newPos
  2001. * @return {?}
  2002. */
  2003. updateHandles(which, newPos) {
  2004. if (which === PointerType.Min) {
  2005. this.updateLowHandle(newPos);
  2006. }
  2007. else if (which === PointerType.Max) {
  2008. this.updateHighHandle(newPos);
  2009. }
  2010. this.updateSelectionBar();
  2011. this.updateTicksScale();
  2012. if (this.range) {
  2013. this.updateCombinedLabel();
  2014. }
  2015. }
  2016. /**
  2017. * @param {?} labelType
  2018. * @param {?} newPos
  2019. * @return {?}
  2020. */
  2021. getHandleLabelPos(labelType, newPos) {
  2022. const /** @type {?} */ labelDimension = (labelType === PointerType.Min)
  2023. ? this.minHandleLabelElement.dimension
  2024. : this.maxHandleLabelElement.dimension;
  2025. const /** @type {?} */ nearHandlePos = newPos - labelDimension / 2 + this.handleHalfDimension;
  2026. const /** @type {?} */ endOfBarPos = this.fullBarElement.dimension - labelDimension;
  2027. if (!this.viewOptions.boundPointerLabels) {
  2028. return nearHandlePos;
  2029. }
  2030. if ((this.viewOptions.rightToLeft && labelType === PointerType.Min) ||
  2031. (!this.viewOptions.rightToLeft && labelType === PointerType.Max)) {
  2032. return Math.min(nearHandlePos, endOfBarPos);
  2033. }
  2034. else {
  2035. return Math.min(Math.max(nearHandlePos, 0), endOfBarPos);
  2036. }
  2037. }
  2038. /**
  2039. * @param {?} newPos
  2040. * @return {?}
  2041. */
  2042. updateLowHandle(newPos) {
  2043. this.minHandleElement.setPosition(newPos);
  2044. this.minHandleLabelElement.setValue(this.getDisplayValue(this.viewLowValue, LabelType.Low));
  2045. this.minHandleLabelElement.setPosition(this.getHandleLabelPos(PointerType.Min, newPos));
  2046. if (!ValueHelper.isNullOrUndefined(this.viewOptions.getPointerColor)) {
  2047. this.minPointerStyle = {
  2048. backgroundColor: this.getPointerColor(PointerType.Min),
  2049. };
  2050. }
  2051. if (this.viewOptions.autoHideLimitLabels) {
  2052. this.updateFloorAndCeilLabelsVisibility();
  2053. }
  2054. }
  2055. /**
  2056. * @param {?} newPos
  2057. * @return {?}
  2058. */
  2059. updateHighHandle(newPos) {
  2060. this.maxHandleElement.setPosition(newPos);
  2061. this.maxHandleLabelElement.setValue(this.getDisplayValue(this.viewHighValue, LabelType.High));
  2062. this.maxHandleLabelElement.setPosition(this.getHandleLabelPos(PointerType.Max, newPos));
  2063. if (!ValueHelper.isNullOrUndefined(this.viewOptions.getPointerColor)) {
  2064. this.maxPointerStyle = {
  2065. backgroundColor: this.getPointerColor(PointerType.Max),
  2066. };
  2067. }
  2068. if (this.viewOptions.autoHideLimitLabels) {
  2069. this.updateFloorAndCeilLabelsVisibility();
  2070. }
  2071. }
  2072. /**
  2073. * @return {?}
  2074. */
  2075. updateFloorAndCeilLabelsVisibility() {
  2076. // Show based only on hideLimitLabels if pointer labels are hidden
  2077. if (this.viewOptions.hidePointerLabels) {
  2078. return;
  2079. }
  2080. let /** @type {?} */ floorLabelHidden = false;
  2081. let /** @type {?} */ ceilLabelHidden = false;
  2082. const /** @type {?} */ isMinLabelAtFloor = this.isLabelBelowFloorLabel(this.minHandleLabelElement);
  2083. const /** @type {?} */ isMinLabelAtCeil = this.isLabelAboveCeilLabel(this.minHandleLabelElement);
  2084. const /** @type {?} */ isMaxLabelAtCeil = this.isLabelAboveCeilLabel(this.maxHandleLabelElement);
  2085. const /** @type {?} */ isCombinedLabelAtFloor = this.isLabelBelowFloorLabel(this.combinedLabelElement);
  2086. const /** @type {?} */ isCombinedLabelAtCeil = this.isLabelAboveCeilLabel(this.combinedLabelElement);
  2087. if (isMinLabelAtFloor) {
  2088. floorLabelHidden = true;
  2089. this.floorLabelElement.hide();
  2090. }
  2091. else {
  2092. floorLabelHidden = false;
  2093. this.floorLabelElement.show();
  2094. }
  2095. if (isMinLabelAtCeil) {
  2096. ceilLabelHidden = true;
  2097. this.ceilLabelElement.hide();
  2098. }
  2099. else {
  2100. ceilLabelHidden = false;
  2101. this.ceilLabelElement.show();
  2102. }
  2103. if (this.range) {
  2104. const /** @type {?} */ hideCeil = this.combinedLabelElement.isVisible() ? isCombinedLabelAtCeil : isMaxLabelAtCeil;
  2105. const /** @type {?} */ hideFloor = this.combinedLabelElement.isVisible() ? isCombinedLabelAtFloor : isMinLabelAtFloor;
  2106. if (hideCeil) {
  2107. this.ceilLabelElement.hide();
  2108. }
  2109. else if (!ceilLabelHidden) {
  2110. this.ceilLabelElement.show();
  2111. }
  2112. // Hide or show floor label
  2113. if (hideFloor) {
  2114. this.floorLabelElement.hide();
  2115. }
  2116. else if (!floorLabelHidden) {
  2117. this.floorLabelElement.show();
  2118. }
  2119. }
  2120. }
  2121. /**
  2122. * @param {?} label
  2123. * @return {?}
  2124. */
  2125. isLabelBelowFloorLabel(label) {
  2126. const /** @type {?} */ pos = label.position;
  2127. const /** @type {?} */ dim = label.dimension;
  2128. const /** @type {?} */ floorPos = this.floorLabelElement.position;
  2129. const /** @type {?} */ floorDim = this.floorLabelElement.dimension;
  2130. return this.viewOptions.rightToLeft
  2131. ? pos + dim >= floorPos - 2
  2132. : pos <= floorPos + floorDim + 2;
  2133. }
  2134. /**
  2135. * @param {?} label
  2136. * @return {?}
  2137. */
  2138. isLabelAboveCeilLabel(label) {
  2139. const /** @type {?} */ pos = label.position;
  2140. const /** @type {?} */ dim = label.dimension;
  2141. const /** @type {?} */ ceilPos = this.ceilLabelElement.position;
  2142. const /** @type {?} */ ceilDim = this.ceilLabelElement.dimension;
  2143. return this.viewOptions.rightToLeft
  2144. ? pos <= ceilPos + ceilDim + 2
  2145. : pos + dim >= ceilPos - 2;
  2146. }
  2147. /**
  2148. * @return {?}
  2149. */
  2150. updateSelectionBar() {
  2151. let /** @type {?} */ position = 0;
  2152. let /** @type {?} */ dimension = 0;
  2153. const /** @type {?} */ isSelectionBarFromRight = this.viewOptions.rightToLeft
  2154. ? !this.viewOptions.showSelectionBarEnd
  2155. : this.viewOptions.showSelectionBarEnd;
  2156. const /** @type {?} */ positionForRange = this.viewOptions.rightToLeft
  2157. ? this.maxHandleElement.position + this.handleHalfDimension
  2158. : this.minHandleElement.position + this.handleHalfDimension;
  2159. if (this.range) {
  2160. dimension = Math.abs(this.maxHandleElement.position - this.minHandleElement.position);
  2161. position = positionForRange;
  2162. }
  2163. else {
  2164. if (!ValueHelper.isNullOrUndefined(this.viewOptions.showSelectionBarFromValue)) {
  2165. const /** @type {?} */ center = this.viewOptions.showSelectionBarFromValue;
  2166. const /** @type {?} */ centerPosition = this.valueToPosition(center);
  2167. const /** @type {?} */ isModelGreaterThanCenter = this.viewOptions.rightToLeft
  2168. ? this.viewLowValue <= center
  2169. : this.viewLowValue > center;
  2170. if (isModelGreaterThanCenter) {
  2171. dimension = this.minHandleElement.position - centerPosition;
  2172. position = centerPosition + this.handleHalfDimension;
  2173. }
  2174. else {
  2175. dimension = centerPosition - this.minHandleElement.position;
  2176. position = this.minHandleElement.position + this.handleHalfDimension;
  2177. }
  2178. }
  2179. else if (isSelectionBarFromRight) {
  2180. dimension = Math.ceil(Math.abs(this.maxHandlePosition - this.minHandleElement.position) + this.handleHalfDimension);
  2181. position = Math.floor(this.minHandleElement.position + this.handleHalfDimension);
  2182. }
  2183. else {
  2184. dimension = this.minHandleElement.position + this.handleHalfDimension;
  2185. position = 0;
  2186. }
  2187. }
  2188. this.selectionBarElement.setDimension(dimension);
  2189. this.selectionBarElement.setPosition(position);
  2190. if (this.range && this.viewOptions.showOuterSelectionBars) {
  2191. if (this.viewOptions.rightToLeft) {
  2192. this.rightOuterSelectionBarElement.setDimension(position);
  2193. this.rightOuterSelectionBarElement.setPosition(0);
  2194. this.fullBarElement.calculateDimension();
  2195. this.leftOuterSelectionBarElement.setDimension(this.fullBarElement.dimension - (position + dimension));
  2196. this.leftOuterSelectionBarElement.setPosition(position + dimension);
  2197. }
  2198. else {
  2199. this.leftOuterSelectionBarElement.setDimension(position);
  2200. this.leftOuterSelectionBarElement.setPosition(0);
  2201. this.fullBarElement.calculateDimension();
  2202. this.rightOuterSelectionBarElement.setDimension(this.fullBarElement.dimension - (position + dimension));
  2203. this.rightOuterSelectionBarElement.setPosition(position + dimension);
  2204. }
  2205. }
  2206. if (!ValueHelper.isNullOrUndefined(this.viewOptions.getSelectionBarColor)) {
  2207. const /** @type {?} */ color = this.getSelectionBarColor();
  2208. this.barStyle = {
  2209. backgroundColor: color,
  2210. };
  2211. }
  2212. else if (!ValueHelper.isNullOrUndefined(this.viewOptions.selectionBarGradient)) {
  2213. const /** @type {?} */ offset = (!ValueHelper.isNullOrUndefined(this.viewOptions.showSelectionBarFromValue))
  2214. ? this.valueToPosition(this.viewOptions.showSelectionBarFromValue)
  2215. : 0;
  2216. const /** @type {?} */ reversed = (offset - position > 0 && !isSelectionBarFromRight) || (offset - position <= 0 && isSelectionBarFromRight);
  2217. const /** @type {?} */ direction = this.viewOptions.vertical
  2218. ? reversed ? 'bottom' : 'top'
  2219. : reversed ? 'left' : 'right';
  2220. this.barStyle = {
  2221. backgroundImage: 'linear-gradient(to ' +
  2222. direction +
  2223. ', ' +
  2224. this.viewOptions.selectionBarGradient.from +
  2225. ' 0%,' +
  2226. this.viewOptions.selectionBarGradient.to +
  2227. ' 100%)',
  2228. };
  2229. if (this.viewOptions.vertical) {
  2230. this.barStyle.backgroundPosition =
  2231. 'center ' +
  2232. (offset +
  2233. dimension +
  2234. position +
  2235. (reversed ? -this.handleHalfDimension : 0)) +
  2236. 'px';
  2237. this.barStyle.backgroundSize =
  2238. '100% ' + (this.fullBarElement.dimension - this.handleHalfDimension) + 'px';
  2239. }
  2240. else {
  2241. this.barStyle.backgroundPosition =
  2242. offset -
  2243. position +
  2244. (reversed ? this.handleHalfDimension : 0) +
  2245. 'px center';
  2246. this.barStyle.backgroundSize =
  2247. this.fullBarElement.dimension - this.handleHalfDimension + 'px 100%';
  2248. }
  2249. }
  2250. }
  2251. /**
  2252. * @return {?}
  2253. */
  2254. getSelectionBarColor() {
  2255. if (this.range) {
  2256. return this.viewOptions.getSelectionBarColor(this.value, this.highValue);
  2257. }
  2258. return this.viewOptions.getSelectionBarColor(this.value);
  2259. }
  2260. /**
  2261. * @param {?} pointerType
  2262. * @return {?}
  2263. */
  2264. getPointerColor(pointerType) {
  2265. if (pointerType === PointerType.Max) {
  2266. return this.viewOptions.getPointerColor(this.highValue, pointerType);
  2267. }
  2268. return this.viewOptions.getPointerColor(this.value, pointerType);
  2269. }
  2270. /**
  2271. * @param {?} value
  2272. * @return {?}
  2273. */
  2274. getTickColor(value) {
  2275. return this.viewOptions.getTickColor(value);
  2276. }
  2277. /**
  2278. * @return {?}
  2279. */
  2280. updateCombinedLabel() {
  2281. let /** @type {?} */ isLabelOverlap = null;
  2282. if (this.viewOptions.rightToLeft) {
  2283. isLabelOverlap =
  2284. this.minHandleLabelElement.position - this.minHandleLabelElement.dimension - 10 <= this.maxHandleLabelElement.position;
  2285. }
  2286. else {
  2287. isLabelOverlap =
  2288. this.minHandleLabelElement.position + this.minHandleLabelElement.dimension + 10 >= this.maxHandleLabelElement.position;
  2289. }
  2290. if (isLabelOverlap) {
  2291. const /** @type {?} */ lowDisplayValue = this.getDisplayValue(this.viewLowValue, LabelType.Low);
  2292. const /** @type {?} */ highDisplayValue = this.getDisplayValue(this.viewHighValue, LabelType.High);
  2293. const /** @type {?} */ combinedLabelValue = this.viewOptions.rightToLeft
  2294. ? this.viewOptions.combineLabels(highDisplayValue, lowDisplayValue)
  2295. : this.viewOptions.combineLabels(lowDisplayValue, highDisplayValue);
  2296. this.combinedLabelElement.setValue(combinedLabelValue);
  2297. const /** @type {?} */ pos = this.viewOptions.boundPointerLabels
  2298. ? Math.min(Math.max(this.selectionBarElement.position +
  2299. this.selectionBarElement.dimension / 2 -
  2300. this.combinedLabelElement.dimension / 2, 0), this.fullBarElement.dimension - this.combinedLabelElement.dimension)
  2301. : this.selectionBarElement.position + this.selectionBarElement.dimension / 2 - this.combinedLabelElement.dimension / 2;
  2302. this.combinedLabelElement.setPosition(pos);
  2303. this.minHandleLabelElement.hide();
  2304. this.maxHandleLabelElement.hide();
  2305. this.combinedLabelElement.show();
  2306. }
  2307. else {
  2308. this.updateHighHandle(this.valueToPosition(this.viewHighValue));
  2309. this.updateLowHandle(this.valueToPosition(this.viewLowValue));
  2310. this.maxHandleLabelElement.show();
  2311. this.minHandleLabelElement.show();
  2312. this.combinedLabelElement.hide();
  2313. }
  2314. if (this.viewOptions.autoHideLimitLabels) {
  2315. this.updateFloorAndCeilLabelsVisibility();
  2316. }
  2317. }
  2318. /**
  2319. * @param {?} value
  2320. * @param {?} which
  2321. * @return {?}
  2322. */
  2323. getDisplayValue(value, which) {
  2324. if (!ValueHelper.isNullOrUndefined(this.viewOptions.stepsArray) && !this.viewOptions.bindIndexForStepsArray) {
  2325. value = this.getStepValue(value);
  2326. }
  2327. return this.viewOptions.translate(value, which);
  2328. }
  2329. /**
  2330. * @param {?} value
  2331. * @param {?=} customStep
  2332. * @return {?}
  2333. */
  2334. roundStep(value, customStep) {
  2335. const /** @type {?} */ step = !ValueHelper.isNullOrUndefined(customStep) ? customStep : this.viewOptions.step;
  2336. let /** @type {?} */ steppedDifference = MathHelper.roundToPrecisionLimit((value - this.viewOptions.floor) / step, this.viewOptions.precisionLimit);
  2337. steppedDifference = Math.round(steppedDifference) * step;
  2338. return MathHelper.roundToPrecisionLimit(this.viewOptions.floor + steppedDifference, this.viewOptions.precisionLimit);
  2339. }
  2340. /**
  2341. * @param {?} val
  2342. * @return {?}
  2343. */
  2344. valueToPosition(val) {
  2345. let /** @type {?} */ fn = ValueHelper.linearValueToPosition;
  2346. if (!ValueHelper.isNullOrUndefined(this.viewOptions.customValueToPosition)) {
  2347. fn = this.viewOptions.customValueToPosition;
  2348. }
  2349. else if (this.viewOptions.logScale) {
  2350. fn = ValueHelper.logValueToPosition;
  2351. }
  2352. val = MathHelper.clampToRange(val, this.viewOptions.floor, this.viewOptions.ceil);
  2353. let /** @type {?} */ percent = fn(val, this.viewOptions.floor, this.viewOptions.ceil);
  2354. if (ValueHelper.isNullOrUndefined(percent)) {
  2355. percent = 0;
  2356. }
  2357. if (this.viewOptions.rightToLeft) {
  2358. percent = 1 - percent;
  2359. }
  2360. return percent * this.maxHandlePosition;
  2361. }
  2362. /**
  2363. * @param {?} position
  2364. * @return {?}
  2365. */
  2366. positionToValue(position) {
  2367. let /** @type {?} */ percent = position / this.maxHandlePosition;
  2368. if (this.viewOptions.rightToLeft) {
  2369. percent = 1 - percent;
  2370. }
  2371. let /** @type {?} */ fn = ValueHelper.linearPositionToValue;
  2372. if (!ValueHelper.isNullOrUndefined(this.viewOptions.customPositionToValue)) {
  2373. fn = this.viewOptions.customPositionToValue;
  2374. }
  2375. else if (this.viewOptions.logScale) {
  2376. fn = ValueHelper.logPositionToValue;
  2377. }
  2378. const /** @type {?} */ value = fn(percent, this.viewOptions.floor, this.viewOptions.ceil);
  2379. return !ValueHelper.isNullOrUndefined(value) ? value : 0;
  2380. }
  2381. /**
  2382. * @param {?} event
  2383. * @param {?=} targetTouchId
  2384. * @return {?}
  2385. */
  2386. getEventXY(event, targetTouchId) {
  2387. if (event instanceof MouseEvent) {
  2388. return this.viewOptions.vertical ? event.clientY : event.clientX;
  2389. }
  2390. let /** @type {?} */ touchIndex = 0;
  2391. const /** @type {?} */ touches = event.touches;
  2392. if (!ValueHelper.isNullOrUndefined(targetTouchId)) {
  2393. for (let /** @type {?} */ i = 0; i < touches.length; i++) {
  2394. if (touches[i].identifier === targetTouchId) {
  2395. touchIndex = i;
  2396. break;
  2397. }
  2398. }
  2399. }
  2400. // Return the target touch or if the target touch was not found in the event
  2401. // returns the coordinates of the first touch
  2402. return this.viewOptions.vertical ? touches[touchIndex].clientY : touches[touchIndex].clientX;
  2403. }
  2404. /**
  2405. * @param {?} event
  2406. * @param {?=} targetTouchId
  2407. * @return {?}
  2408. */
  2409. getEventPosition(event, targetTouchId) {
  2410. const /** @type {?} */ sliderElementBoundingRect = this.elementRef.nativeElement.getBoundingClientRect();
  2411. const /** @type {?} */ sliderPos = this.viewOptions.vertical ?
  2412. sliderElementBoundingRect.bottom : sliderElementBoundingRect.left;
  2413. let /** @type {?} */ eventPos = 0;
  2414. if (this.viewOptions.vertical) {
  2415. eventPos = -this.getEventXY(event, targetTouchId) + sliderPos;
  2416. }
  2417. else {
  2418. eventPos = this.getEventXY(event, targetTouchId) - sliderPos;
  2419. }
  2420. return eventPos * this.viewOptions.scale - this.handleHalfDimension;
  2421. }
  2422. /**
  2423. * @param {?} event
  2424. * @return {?}
  2425. */
  2426. getNearestHandle(event) {
  2427. if (!this.range) {
  2428. return PointerType.Min;
  2429. }
  2430. const /** @type {?} */ position = this.getEventPosition(event);
  2431. const /** @type {?} */ distanceMin = Math.abs(position - this.minHandleElement.position);
  2432. const /** @type {?} */ distanceMax = Math.abs(position - this.maxHandleElement.position);
  2433. if (distanceMin < distanceMax) {
  2434. return PointerType.Min;
  2435. }
  2436. else if (distanceMin > distanceMax) {
  2437. return PointerType.Max;
  2438. }
  2439. else if (!this.viewOptions.rightToLeft) {
  2440. // if event is at the same distance from min/max then if it's at left of minH, we return minH else maxH
  2441. return position < this.minHandleElement.position ? PointerType.Min : PointerType.Max;
  2442. }
  2443. // reverse in rtl
  2444. return position > this.minHandleElement.position ? PointerType.Min : PointerType.Max;
  2445. }
  2446. /**
  2447. * @return {?}
  2448. */
  2449. bindEvents() {
  2450. const /** @type {?} */ draggableRange = this.viewOptions.draggableRange;
  2451. if (!this.viewOptions.onlyBindHandles) {
  2452. this.selectionBarElement.on('mousedown', (event) => this.onBarStart(null, draggableRange, event, true, true, true));
  2453. }
  2454. if (this.viewOptions.draggableRangeOnly) {
  2455. this.minHandleElement.on('mousedown', (event) => this.onBarStart(PointerType.Min, draggableRange, event, true, true));
  2456. this.maxHandleElement.on('mousedown', (event) => this.onBarStart(PointerType.Max, draggableRange, event, true, true));
  2457. }
  2458. else {
  2459. this.minHandleElement.on('mousedown', (event) => this.onStart(PointerType.Min, event, true, true));
  2460. if (this.range) {
  2461. this.maxHandleElement.on('mousedown', (event) => this.onStart(PointerType.Max, event, true, true));
  2462. }
  2463. if (!this.viewOptions.onlyBindHandles) {
  2464. this.fullBarElement.on('mousedown', (event) => this.onStart(null, event, true, true, true));
  2465. this.ticksElement.on('mousedown', (event) => this.onStart(null, event, true, true, true, true));
  2466. }
  2467. }
  2468. if (!this.viewOptions.onlyBindHandles) {
  2469. this.selectionBarElement.onPassive('touchstart', (event) => this.onBarStart(null, draggableRange, event, true, true, true));
  2470. }
  2471. if (this.viewOptions.draggableRangeOnly) {
  2472. this.minHandleElement.onPassive('touchstart', (event) => this.onBarStart(PointerType.Min, draggableRange, event, true, true));
  2473. this.maxHandleElement.onPassive('touchstart', (event) => this.onBarStart(PointerType.Max, draggableRange, event, true, true));
  2474. }
  2475. else {
  2476. this.minHandleElement.onPassive('touchstart', (event) => this.onStart(PointerType.Min, event, true, true));
  2477. if (this.range) {
  2478. this.maxHandleElement.onPassive('touchstart', (event) => this.onStart(PointerType.Max, event, true, true));
  2479. }
  2480. if (!this.viewOptions.onlyBindHandles) {
  2481. this.fullBarElement.onPassive('touchstart', (event) => this.onStart(null, event, true, true, true));
  2482. this.ticksElement.onPassive('touchstart', (event) => this.onStart(null, event, false, false, true, true));
  2483. }
  2484. }
  2485. if (this.viewOptions.keyboardSupport) {
  2486. this.minHandleElement.on('focus', () => this.onPointerFocus(PointerType.Min));
  2487. if (this.range) {
  2488. this.maxHandleElement.on('focus', () => this.onPointerFocus(PointerType.Max));
  2489. }
  2490. }
  2491. }
  2492. /**
  2493. * @return {?}
  2494. */
  2495. unbindEvents() {
  2496. this.unsubscribeOnMove();
  2497. this.unsubscribeOnEnd();
  2498. for (const /** @type {?} */ element of this.getAllSliderElements()) {
  2499. element.off();
  2500. }
  2501. }
  2502. /**
  2503. * @param {?} pointerType
  2504. * @param {?} draggableRange
  2505. * @param {?} event
  2506. * @param {?} bindMove
  2507. * @param {?} bindEnd
  2508. * @param {?=} simulateImmediateMove
  2509. * @param {?=} simulateImmediateEnd
  2510. * @return {?}
  2511. */
  2512. onBarStart(pointerType, draggableRange, event, bindMove, bindEnd, simulateImmediateMove, simulateImmediateEnd) {
  2513. if (draggableRange) {
  2514. this.onDragStart(pointerType, event, bindMove, bindEnd);
  2515. }
  2516. else {
  2517. this.onStart(pointerType, event, bindMove, bindEnd, simulateImmediateMove, simulateImmediateEnd);
  2518. }
  2519. }
  2520. /**
  2521. * @param {?} pointerType
  2522. * @param {?} event
  2523. * @param {?} bindMove
  2524. * @param {?} bindEnd
  2525. * @param {?=} simulateImmediateMove
  2526. * @param {?=} simulateImmediateEnd
  2527. * @return {?}
  2528. */
  2529. onStart(pointerType, event, bindMove, bindEnd, simulateImmediateMove, simulateImmediateEnd) {
  2530. event.stopPropagation();
  2531. // Only call preventDefault() when handling non-passive events (passive events don't need it)
  2532. if (!CompatibilityHelper.isTouchEvent(event) || !detectPassiveEvents.hasSupport) {
  2533. event.preventDefault();
  2534. }
  2535. // We have to do this in case the HTML where the sliders are on
  2536. // have been animated into view.
  2537. this.calculateViewDimensions();
  2538. if (ValueHelper.isNullOrUndefined(pointerType)) {
  2539. pointerType = this.getNearestHandle(event);
  2540. }
  2541. this.currentTrackingPointer = pointerType;
  2542. const /** @type {?} */ pointerElement = this.getPointerElement(pointerType);
  2543. pointerElement.active = true;
  2544. if (this.viewOptions.keyboardSupport) {
  2545. pointerElement.focus();
  2546. }
  2547. if (bindMove) {
  2548. this.unsubscribeOnMove();
  2549. const /** @type {?} */ onMoveCallback = (e) => this.dragging.active ? this.onDragMove(e) : this.onMove(e);
  2550. if (CompatibilityHelper.isTouchEvent(event)) {
  2551. this.onMoveEventListener = this.eventListenerHelper.attachPassiveEventListener(document, 'touchmove', onMoveCallback, this.viewOptions.touchEventsInterval);
  2552. }
  2553. else {
  2554. this.onMoveEventListener = this.eventListenerHelper.attachEventListener(document, 'mousemove', onMoveCallback, this.viewOptions.mouseEventsInterval);
  2555. }
  2556. }
  2557. if (bindEnd) {
  2558. this.unsubscribeOnEnd();
  2559. const /** @type {?} */ onEndCallback = (e) => this.onEnd(e);
  2560. if (CompatibilityHelper.isTouchEvent(event)) {
  2561. this.onEndEventListener = this.eventListenerHelper.attachPassiveEventListener(document, 'touchend', onEndCallback);
  2562. }
  2563. else {
  2564. this.onEndEventListener = this.eventListenerHelper.attachEventListener(document, 'mouseup', onEndCallback);
  2565. }
  2566. }
  2567. this.userChangeStart.emit(this.getChangeContext());
  2568. if (CompatibilityHelper.isTouchEvent(event) && !ValueHelper.isNullOrUndefined((/** @type {?} */ (event)).changedTouches)) {
  2569. // Store the touch identifier
  2570. if (ValueHelper.isNullOrUndefined(this.touchId)) {
  2571. this.touchId = (/** @type {?} */ (event)).changedTouches[0].identifier;
  2572. }
  2573. }
  2574. // Click events, either with mouse or touch gesture are weird. Sometimes they result in full
  2575. // start, move, end sequence, and sometimes, they don't - they only invoke mousedown
  2576. // As a workaround, we simulate the first move event and the end event if it's necessary
  2577. if (simulateImmediateMove) {
  2578. this.onMove(event, true);
  2579. }
  2580. if (simulateImmediateEnd) {
  2581. this.onEnd(event);
  2582. }
  2583. }
  2584. /**
  2585. * @param {?} event
  2586. * @param {?=} fromTick
  2587. * @return {?}
  2588. */
  2589. onMove(event, fromTick) {
  2590. let /** @type {?} */ touchForThisSlider = null;
  2591. if (CompatibilityHelper.isTouchEvent(event)) {
  2592. const /** @type {?} */ changedTouches = (/** @type {?} */ (event)).changedTouches;
  2593. for (let /** @type {?} */ i = 0; i < changedTouches.length; i++) {
  2594. if (changedTouches[i].identifier === this.touchId) {
  2595. touchForThisSlider = changedTouches[i];
  2596. break;
  2597. }
  2598. }
  2599. if (ValueHelper.isNullOrUndefined(touchForThisSlider)) {
  2600. return;
  2601. }
  2602. }
  2603. const /** @type {?} */ newPos = !ValueHelper.isNullOrUndefined(touchForThisSlider)
  2604. ? this.getEventPosition(event, touchForThisSlider.identifier)
  2605. : this.getEventPosition(event);
  2606. let /** @type {?} */ newValue;
  2607. const /** @type {?} */ ceilValue = this.viewOptions.rightToLeft
  2608. ? this.viewOptions.floor
  2609. : this.viewOptions.ceil;
  2610. const /** @type {?} */ floorValue = this.viewOptions.rightToLeft ? this.viewOptions.ceil : this.viewOptions.floor;
  2611. if (newPos <= 0) {
  2612. newValue = floorValue;
  2613. }
  2614. else if (newPos >= this.maxHandlePosition) {
  2615. newValue = ceilValue;
  2616. }
  2617. else {
  2618. newValue = this.positionToValue(newPos);
  2619. if (fromTick && !ValueHelper.isNullOrUndefined(this.viewOptions.tickStep)) {
  2620. newValue = this.roundStep(newValue, this.viewOptions.tickStep);
  2621. }
  2622. else {
  2623. newValue = this.roundStep(newValue);
  2624. }
  2625. }
  2626. this.positionTrackingHandle(newValue);
  2627. }
  2628. /**
  2629. * @param {?} event
  2630. * @return {?}
  2631. */
  2632. onEnd(event) {
  2633. if (CompatibilityHelper.isTouchEvent(event)) {
  2634. const /** @type {?} */ changedTouches = (/** @type {?} */ (event)).changedTouches;
  2635. if (changedTouches[0].identifier !== this.touchId) {
  2636. return;
  2637. }
  2638. }
  2639. this.touchId = null;
  2640. if (!this.viewOptions.keyboardSupport) {
  2641. this.minHandleElement.active = false;
  2642. this.maxHandleElement.active = false;
  2643. this.currentTrackingPointer = null;
  2644. }
  2645. this.dragging.active = false;
  2646. this.unsubscribeOnMove();
  2647. this.unsubscribeOnEnd();
  2648. this.userChangeEnd.emit(this.getChangeContext());
  2649. }
  2650. /**
  2651. * @param {?} pointerType
  2652. * @return {?}
  2653. */
  2654. onPointerFocus(pointerType) {
  2655. const /** @type {?} */ pointerElement = this.getPointerElement(pointerType);
  2656. pointerElement.on('blur', () => this.onPointerBlur(pointerElement));
  2657. pointerElement.on('keydown', (event) => this.onKeyboardEvent(event));
  2658. pointerElement.on('keyup', () => this.onKeyUp());
  2659. pointerElement.active = true;
  2660. this.currentTrackingPointer = pointerType;
  2661. this.currentFocusPointer = pointerType;
  2662. this.firstKeyDown = true;
  2663. }
  2664. /**
  2665. * @return {?}
  2666. */
  2667. onKeyUp() {
  2668. this.firstKeyDown = true;
  2669. this.userChangeEnd.emit(this.getChangeContext());
  2670. }
  2671. /**
  2672. * @param {?} pointer
  2673. * @return {?}
  2674. */
  2675. onPointerBlur(pointer) {
  2676. pointer.off('blur');
  2677. pointer.off('keydown');
  2678. pointer.off('keyup');
  2679. pointer.active = false;
  2680. if (ValueHelper.isNullOrUndefined(this.touchId)) {
  2681. this.currentTrackingPointer = null;
  2682. this.currentFocusPointer = null;
  2683. }
  2684. }
  2685. /**
  2686. * @param {?} currentValue
  2687. * @return {?}
  2688. */
  2689. getKeyActions(currentValue) {
  2690. const /** @type {?} */ valueRange = this.viewOptions.ceil - this.viewOptions.floor;
  2691. let /** @type {?} */ increaseStep = currentValue + this.viewOptions.step;
  2692. let /** @type {?} */ decreaseStep = currentValue - this.viewOptions.step;
  2693. let /** @type {?} */ increasePage = currentValue + valueRange / 10;
  2694. let /** @type {?} */ decreasePage = currentValue - valueRange / 10;
  2695. if (this.viewOptions.reversedControls) {
  2696. increaseStep = currentValue - this.viewOptions.step;
  2697. decreaseStep = currentValue + this.viewOptions.step;
  2698. increasePage = currentValue - valueRange / 10;
  2699. decreasePage = currentValue + valueRange / 10;
  2700. }
  2701. // Left to right default actions
  2702. const /** @type {?} */ actions = {
  2703. UP: increaseStep,
  2704. DOWN: decreaseStep,
  2705. LEFT: decreaseStep,
  2706. RIGHT: increaseStep,
  2707. PAGEUP: increasePage,
  2708. PAGEDOWN: decreasePage,
  2709. HOME: this.viewOptions.reversedControls ? this.viewOptions.ceil : this.viewOptions.floor,
  2710. END: this.viewOptions.reversedControls ? this.viewOptions.floor : this.viewOptions.ceil,
  2711. };
  2712. // right to left means swapping right and left arrows
  2713. if (this.viewOptions.rightToLeft) {
  2714. actions["LEFT"] = increaseStep;
  2715. actions["RIGHT"] = decreaseStep;
  2716. // right to left and vertical means we also swap up and down
  2717. if (this.viewOptions.vertical) {
  2718. actions["UP"] = decreaseStep;
  2719. actions["DOWN"] = increaseStep;
  2720. }
  2721. }
  2722. return actions;
  2723. }
  2724. /**
  2725. * @param {?} event
  2726. * @return {?}
  2727. */
  2728. onKeyboardEvent(event) {
  2729. const /** @type {?} */ currentValue = this.getCurrentTrackingValue();
  2730. const /** @type {?} */ keyCode = !ValueHelper.isNullOrUndefined(event.keyCode)
  2731. ? event.keyCode
  2732. : event.which;
  2733. const /** @type {?} */ keys = {
  2734. 38: 'UP',
  2735. 40: 'DOWN',
  2736. 37: 'LEFT',
  2737. 39: 'RIGHT',
  2738. 33: 'PAGEUP',
  2739. 34: 'PAGEDOWN',
  2740. 36: 'HOME',
  2741. 35: 'END',
  2742. };
  2743. const /** @type {?} */ actions = this.getKeyActions(currentValue);
  2744. const /** @type {?} */ key = keys[keyCode];
  2745. const /** @type {?} */ action = actions[key];
  2746. if (ValueHelper.isNullOrUndefined(action) || ValueHelper.isNullOrUndefined(this.currentTrackingPointer)) {
  2747. return;
  2748. }
  2749. event.preventDefault();
  2750. if (this.firstKeyDown) {
  2751. this.firstKeyDown = false;
  2752. this.userChangeStart.emit(this.getChangeContext());
  2753. }
  2754. const /** @type {?} */ actionValue = MathHelper.clampToRange(action, this.viewOptions.floor, this.viewOptions.ceil);
  2755. const /** @type {?} */ newValue = this.roundStep(actionValue);
  2756. if (!this.viewOptions.draggableRangeOnly) {
  2757. this.positionTrackingHandle(newValue);
  2758. }
  2759. else {
  2760. const /** @type {?} */ difference = this.viewHighValue - this.viewLowValue;
  2761. let /** @type {?} */ newMinValue;
  2762. let /** @type {?} */ newMaxValue;
  2763. if (this.currentTrackingPointer === PointerType.Min) {
  2764. newMinValue = newValue;
  2765. newMaxValue = newValue + difference;
  2766. if (newMaxValue > this.viewOptions.ceil) {
  2767. newMaxValue = this.viewOptions.ceil;
  2768. newMinValue = newMaxValue - difference;
  2769. }
  2770. }
  2771. else if (this.currentTrackingPointer === PointerType.Max) {
  2772. newMaxValue = newValue;
  2773. newMinValue = newValue - difference;
  2774. if (newMinValue < this.viewOptions.floor) {
  2775. newMinValue = this.viewOptions.floor;
  2776. newMaxValue = newMinValue + difference;
  2777. }
  2778. }
  2779. this.positionTrackingBar(newMinValue, newMaxValue);
  2780. }
  2781. }
  2782. /**
  2783. * @param {?} pointerType
  2784. * @param {?} event
  2785. * @param {?} bindMove
  2786. * @param {?} bindEnd
  2787. * @return {?}
  2788. */
  2789. onDragStart(pointerType, event, bindMove, bindEnd) {
  2790. const /** @type {?} */ position = this.getEventPosition(event);
  2791. this.dragging = new Dragging();
  2792. this.dragging.active = true;
  2793. this.dragging.value = this.positionToValue(position);
  2794. this.dragging.difference = this.viewHighValue - this.viewLowValue;
  2795. this.dragging.lowLimit = this.viewOptions.rightToLeft
  2796. ? this.minHandleElement.position - position
  2797. : position - this.minHandleElement.position;
  2798. this.dragging.highLimit = this.viewOptions.rightToLeft
  2799. ? position - this.maxHandleElement.position
  2800. : this.maxHandleElement.position - position;
  2801. this.onStart(pointerType, event, bindMove, bindEnd);
  2802. }
  2803. /**
  2804. * Get min value depending on whether the newPos is outOfBounds above or below the bar and rightToLeft
  2805. * @param {?} newPos
  2806. * @param {?} outOfBounds
  2807. * @param {?} isAbove
  2808. * @return {?}
  2809. */
  2810. getMinValue(newPos, outOfBounds, isAbove) {
  2811. const /** @type {?} */ isRTL = this.viewOptions.rightToLeft;
  2812. let /** @type {?} */ value = null;
  2813. if (outOfBounds) {
  2814. if (isAbove) {
  2815. value = isRTL
  2816. ? this.viewOptions.floor
  2817. : this.viewOptions.ceil - this.dragging.difference;
  2818. }
  2819. else {
  2820. value = isRTL
  2821. ? this.viewOptions.ceil - this.dragging.difference
  2822. : this.viewOptions.floor;
  2823. }
  2824. }
  2825. else {
  2826. value = isRTL
  2827. ? this.positionToValue(newPos + this.dragging.lowLimit)
  2828. : this.positionToValue(newPos - this.dragging.lowLimit);
  2829. }
  2830. return this.roundStep(value);
  2831. }
  2832. /**
  2833. * Get max value depending on whether the newPos is outOfBounds above or below the bar and rightToLeft
  2834. * @param {?} newPos
  2835. * @param {?} outOfBounds
  2836. * @param {?} isAbove
  2837. * @return {?}
  2838. */
  2839. getMaxValue(newPos, outOfBounds, isAbove) {
  2840. const /** @type {?} */ isRTL = this.viewOptions.rightToLeft;
  2841. let /** @type {?} */ value = null;
  2842. if (outOfBounds) {
  2843. if (isAbove) {
  2844. value = isRTL
  2845. ? this.viewOptions.floor + this.dragging.difference
  2846. : this.viewOptions.ceil;
  2847. }
  2848. else {
  2849. value = isRTL
  2850. ? this.viewOptions.ceil
  2851. : this.viewOptions.floor + this.dragging.difference;
  2852. }
  2853. }
  2854. else {
  2855. if (isRTL) {
  2856. value =
  2857. this.positionToValue(newPos + this.dragging.lowLimit) +
  2858. this.dragging.difference;
  2859. }
  2860. else {
  2861. value =
  2862. this.positionToValue(newPos - this.dragging.lowLimit) +
  2863. this.dragging.difference;
  2864. }
  2865. }
  2866. return this.roundStep(value);
  2867. }
  2868. /**
  2869. * @param {?=} event
  2870. * @return {?}
  2871. */
  2872. onDragMove(event) {
  2873. const /** @type {?} */ newPos = this.getEventPosition(event);
  2874. let /** @type {?} */ ceilLimit, /** @type {?} */
  2875. floorLimit, /** @type {?} */
  2876. floorHandleElement, /** @type {?} */
  2877. ceilHandleElement;
  2878. if (this.viewOptions.rightToLeft) {
  2879. ceilLimit = this.dragging.lowLimit;
  2880. floorLimit = this.dragging.highLimit;
  2881. floorHandleElement = this.maxHandleElement;
  2882. ceilHandleElement = this.minHandleElement;
  2883. }
  2884. else {
  2885. ceilLimit = this.dragging.highLimit;
  2886. floorLimit = this.dragging.lowLimit;
  2887. floorHandleElement = this.minHandleElement;
  2888. ceilHandleElement = this.maxHandleElement;
  2889. }
  2890. const /** @type {?} */ isUnderFloorLimit = (newPos <= floorLimit);
  2891. const /** @type {?} */ isOverCeilLimit = (newPos >= this.maxHandlePosition - ceilLimit);
  2892. let /** @type {?} */ newMinValue;
  2893. let /** @type {?} */ newMaxValue;
  2894. if (isUnderFloorLimit) {
  2895. if (floorHandleElement.position === 0) {
  2896. return;
  2897. }
  2898. newMinValue = this.getMinValue(newPos, true, false);
  2899. newMaxValue = this.getMaxValue(newPos, true, false);
  2900. }
  2901. else if (isOverCeilLimit) {
  2902. if (ceilHandleElement.position === this.maxHandlePosition) {
  2903. return;
  2904. }
  2905. newMaxValue = this.getMaxValue(newPos, true, true);
  2906. newMinValue = this.getMinValue(newPos, true, true);
  2907. }
  2908. else {
  2909. newMinValue = this.getMinValue(newPos, false, false);
  2910. newMaxValue = this.getMaxValue(newPos, false, false);
  2911. }
  2912. this.positionTrackingBar(newMinValue, newMaxValue);
  2913. }
  2914. /**
  2915. * @param {?} newMinValue
  2916. * @param {?} newMaxValue
  2917. * @return {?}
  2918. */
  2919. positionTrackingBar(newMinValue, newMaxValue) {
  2920. if (!ValueHelper.isNullOrUndefined(this.viewOptions.minLimit) &&
  2921. newMinValue < this.viewOptions.minLimit) {
  2922. newMinValue = this.viewOptions.minLimit;
  2923. newMaxValue = MathHelper.roundToPrecisionLimit(newMinValue + this.dragging.difference, this.viewOptions.precisionLimit);
  2924. }
  2925. if (!ValueHelper.isNullOrUndefined(this.viewOptions.maxLimit) &&
  2926. newMaxValue > this.viewOptions.maxLimit) {
  2927. newMaxValue = this.viewOptions.maxLimit;
  2928. newMinValue = MathHelper.roundToPrecisionLimit(newMaxValue - this.dragging.difference, this.viewOptions.precisionLimit);
  2929. }
  2930. this.viewLowValue = newMinValue;
  2931. this.viewHighValue = newMaxValue;
  2932. this.applyViewChange();
  2933. this.updateHandles(PointerType.Min, this.valueToPosition(newMinValue));
  2934. this.updateHandles(PointerType.Max, this.valueToPosition(newMaxValue));
  2935. }
  2936. /**
  2937. * @param {?} newValue
  2938. * @return {?}
  2939. */
  2940. positionTrackingHandle(newValue) {
  2941. newValue = this.applyMinMaxLimit(newValue);
  2942. if (this.range) {
  2943. if (this.viewOptions.pushRange) {
  2944. newValue = this.applyPushRange(newValue);
  2945. }
  2946. else {
  2947. if (this.viewOptions.noSwitching) {
  2948. if (this.currentTrackingPointer === PointerType.Min &&
  2949. newValue > this.viewHighValue) {
  2950. newValue = this.applyMinMaxRange(this.viewHighValue);
  2951. }
  2952. else if (this.currentTrackingPointer === PointerType.Max &&
  2953. newValue < this.viewLowValue) {
  2954. newValue = this.applyMinMaxRange(this.viewLowValue);
  2955. }
  2956. }
  2957. newValue = this.applyMinMaxRange(newValue);
  2958. /* This is to check if we need to switch the min and max handles */
  2959. if (this.currentTrackingPointer === PointerType.Min && newValue > this.viewHighValue) {
  2960. this.viewLowValue = this.viewHighValue;
  2961. this.applyViewChange();
  2962. this.updateHandles(PointerType.Min, this.maxHandleElement.position);
  2963. this.updateAriaAttributes();
  2964. this.currentTrackingPointer = PointerType.Max;
  2965. this.minHandleElement.active = false;
  2966. this.maxHandleElement.active = true;
  2967. if (this.viewOptions.keyboardSupport) {
  2968. this.maxHandleElement.focus();
  2969. }
  2970. }
  2971. else if (this.currentTrackingPointer === PointerType.Max &&
  2972. newValue < this.viewLowValue) {
  2973. this.viewHighValue = this.viewLowValue;
  2974. this.applyViewChange();
  2975. this.updateHandles(PointerType.Max, this.minHandleElement.position);
  2976. this.updateAriaAttributes();
  2977. this.currentTrackingPointer = PointerType.Min;
  2978. this.maxHandleElement.active = false;
  2979. this.minHandleElement.active = true;
  2980. if (this.viewOptions.keyboardSupport) {
  2981. this.minHandleElement.focus();
  2982. }
  2983. }
  2984. }
  2985. }
  2986. if (this.getCurrentTrackingValue() !== newValue) {
  2987. if (this.currentTrackingPointer === PointerType.Min) {
  2988. this.viewLowValue = newValue;
  2989. this.applyViewChange();
  2990. }
  2991. else if (this.currentTrackingPointer === PointerType.Max) {
  2992. this.viewHighValue = newValue;
  2993. this.applyViewChange();
  2994. }
  2995. this.updateHandles(this.currentTrackingPointer, this.valueToPosition(newValue));
  2996. this.updateAriaAttributes();
  2997. }
  2998. }
  2999. /**
  3000. * @param {?} newValue
  3001. * @return {?}
  3002. */
  3003. applyMinMaxLimit(newValue) {
  3004. if (!ValueHelper.isNullOrUndefined(this.viewOptions.minLimit) && newValue < this.viewOptions.minLimit) {
  3005. return this.viewOptions.minLimit;
  3006. }
  3007. if (!ValueHelper.isNullOrUndefined(this.viewOptions.maxLimit) && newValue > this.viewOptions.maxLimit) {
  3008. return this.viewOptions.maxLimit;
  3009. }
  3010. return newValue;
  3011. }
  3012. /**
  3013. * @param {?} newValue
  3014. * @return {?}
  3015. */
  3016. applyMinMaxRange(newValue) {
  3017. const /** @type {?} */ oppositeValue = (this.currentTrackingPointer === PointerType.Min)
  3018. ? this.viewHighValue
  3019. : this.viewLowValue;
  3020. const /** @type {?} */ difference = Math.abs(newValue - oppositeValue);
  3021. if (!ValueHelper.isNullOrUndefined(this.viewOptions.minRange)) {
  3022. if (difference < this.viewOptions.minRange) {
  3023. if (this.currentTrackingPointer === PointerType.Min) {
  3024. return MathHelper.roundToPrecisionLimit(this.viewHighValue - this.viewOptions.minRange, this.viewOptions.precisionLimit);
  3025. }
  3026. else if (this.currentTrackingPointer === PointerType.Max) {
  3027. return MathHelper.roundToPrecisionLimit(this.viewLowValue + this.viewOptions.minRange, this.viewOptions.precisionLimit);
  3028. }
  3029. }
  3030. }
  3031. if (!ValueHelper.isNullOrUndefined(this.viewOptions.maxRange)) {
  3032. if (difference > this.viewOptions.maxRange) {
  3033. if (this.currentTrackingPointer === PointerType.Min) {
  3034. return MathHelper.roundToPrecisionLimit(this.viewHighValue - this.viewOptions.maxRange, this.viewOptions.precisionLimit);
  3035. }
  3036. else if (this.currentTrackingPointer === PointerType.Max) {
  3037. return MathHelper.roundToPrecisionLimit(this.viewLowValue + this.viewOptions.maxRange, this.viewOptions.precisionLimit);
  3038. }
  3039. }
  3040. }
  3041. return newValue;
  3042. }
  3043. /**
  3044. * @param {?} newValue
  3045. * @return {?}
  3046. */
  3047. applyPushRange(newValue) {
  3048. const /** @type {?} */ difference = (this.currentTrackingPointer === PointerType.Min)
  3049. ? this.viewHighValue - newValue
  3050. : newValue - this.viewLowValue;
  3051. const /** @type {?} */ minRange = (!ValueHelper.isNullOrUndefined(this.viewOptions.minRange))
  3052. ? this.viewOptions.minRange
  3053. : this.viewOptions.step;
  3054. const /** @type {?} */ maxRange = this.viewOptions.maxRange;
  3055. // if smaller than minRange
  3056. if (difference < minRange) {
  3057. if (this.currentTrackingPointer === PointerType.Min) {
  3058. this.viewHighValue = MathHelper.roundToPrecisionLimit(Math.min(newValue + minRange, this.viewOptions.ceil), this.viewOptions.precisionLimit);
  3059. newValue = MathHelper.roundToPrecisionLimit(this.viewHighValue - minRange, this.viewOptions.precisionLimit);
  3060. this.applyViewChange();
  3061. this.updateHandles(PointerType.Max, this.valueToPosition(this.viewHighValue));
  3062. }
  3063. else if (this.currentTrackingPointer === PointerType.Max) {
  3064. this.viewLowValue = MathHelper.roundToPrecisionLimit(Math.max(newValue - minRange, this.viewOptions.floor), this.viewOptions.precisionLimit);
  3065. newValue = MathHelper.roundToPrecisionLimit(this.viewLowValue + minRange, this.viewOptions.precisionLimit);
  3066. this.applyViewChange();
  3067. this.updateHandles(PointerType.Min, this.valueToPosition(this.viewLowValue));
  3068. }
  3069. this.updateAriaAttributes();
  3070. }
  3071. else if (!ValueHelper.isNullOrUndefined(maxRange) && difference > maxRange) {
  3072. // if greater than maxRange
  3073. if (this.currentTrackingPointer === PointerType.Min) {
  3074. this.viewHighValue = MathHelper.roundToPrecisionLimit(newValue + maxRange, this.viewOptions.precisionLimit);
  3075. this.applyViewChange();
  3076. this.updateHandles(PointerType.Max, this.valueToPosition(this.viewHighValue));
  3077. }
  3078. else if (this.currentTrackingPointer === PointerType.Max) {
  3079. this.viewLowValue = MathHelper.roundToPrecisionLimit(newValue - maxRange, this.viewOptions.precisionLimit);
  3080. this.applyViewChange();
  3081. this.updateHandles(PointerType.Min, this.valueToPosition(this.viewLowValue));
  3082. }
  3083. this.updateAriaAttributes();
  3084. }
  3085. return newValue;
  3086. }
  3087. /**
  3088. * @return {?}
  3089. */
  3090. getChangeContext() {
  3091. const /** @type {?} */ changeContext = new ChangeContext();
  3092. changeContext.pointerType = this.currentTrackingPointer;
  3093. changeContext.value = +this.value;
  3094. if (this.range) {
  3095. changeContext.highValue = +this.highValue;
  3096. }
  3097. return changeContext;
  3098. }
  3099. }
  3100. SliderComponent.decorators = [
  3101. { type: Component, args: [{
  3102. selector: 'ng5-slider',
  3103. template: `<!-- // 0 Left selection bar outside two handles -->
  3104. <span ng5SliderElement #leftOuterSelectionBar class="ng5-slider-span ng5-slider-bar-wrapper ng5-slider-left-out-selection">
  3105. <span class="ng5-slider-span ng5-slider-bar"></span>
  3106. </span>
  3107. <!-- // 1 Right selection bar outside two handles -->
  3108. <span ng5SliderElement #rightOuterSelectionBar class="ng5-slider-span ng5-slider-bar-wrapper ng5-slider-right-out-selection">
  3109. <span class="ng5-slider-span ng5-slider-bar"></span>
  3110. </span>
  3111. <!-- // 2 The whole slider bar -->
  3112. <span ng5SliderElement #fullBar [class.ng5-slider-transparent]="fullBarTransparentClass" class="ng5-slider-span ng5-slider-bar-wrapper ng5-slider-full-bar">
  3113. <span class="ng5-slider-span ng5-slider-bar"></span>
  3114. </span>
  3115. <!-- // 3 Selection bar between two handles -->
  3116. <span ng5SliderElement #selectionBar [class.ng5-slider-draggable]="selectionBarDraggableClass" class="ng5-slider-span ng5-slider-bar-wrapper ng5-slider-selection-bar">
  3117. <span class="ng5-slider-span ng5-slider-bar ng5-slider-selection" [ngStyle]="barStyle"></span>
  3118. </span>
  3119. <!-- // 4 Low slider handle -->
  3120. <span ng5SliderHandle #minHandle class="ng5-slider-span ng5-slider-pointer ng5-slider-pointer-min" [ngStyle]=minPointerStyle></span>
  3121. <!-- // 5 High slider handle -->
  3122. <span ng5SliderHandle #maxHandle [style.display]="range ? 'inherit' : 'none'" class="ng5-slider-span ng5-slider-pointer ng5-slider-pointer-max" [ngStyle]=maxPointerStyle></span>
  3123. <!-- // 6 Floor label -->
  3124. <span ng5SliderLabel #floorLabel class="ng5-slider-span ng5-slider-bubble ng5-slider-limit ng5-slider-floor"></span>
  3125. <!-- // 7 Ceiling label -->
  3126. <span ng5SliderLabel #ceilLabel class="ng5-slider-span ng5-slider-bubble ng5-slider-limit ng5-slider-ceil"></span>
  3127. <!-- // 8 Label above the low slider handle -->
  3128. <span ng5SliderLabel #minHandleLabel class="ng5-slider-span ng5-slider-bubble ng5-slider-model-value"></span>
  3129. <!-- // 9 Label above the high slider handle -->
  3130. <span ng5SliderLabel #maxHandleLabel class="ng5-slider-span ng5-slider-bubble ng5-slider-model-high"></span>
  3131. <!-- // 10 Combined range label when the slider handles are close ex. 15 - 17 -->
  3132. <span ng5SliderLabel #combinedLabel class="ng5-slider-span ng5-slider-bubble ng5-slider-combined"></span>
  3133. <!-- // 11 The ticks -->
  3134. <span ng5SliderElement #ticksElement [hidden]="!showTicks" [class.ng5-slider-ticks-values-under]="ticksUnderValuesClass" class="ng5-slider-ticks">
  3135. <span *ngFor="let t of ticks" class="ng5-slider-tick" [ngClass]="{'ng5-slider-selected': t.selected}" [ngStyle]="t.style">
  3136. <ng5-slider-tooltip-wrapper [template]="tooltipTemplate" [tooltip]="t.tooltip" [placement]="t.tooltipPlacement"></ng5-slider-tooltip-wrapper>
  3137. <ng5-slider-tooltip-wrapper *ngIf="t.value != null" class="ng5-slider-span ng5-slider-tick-value"
  3138. [template]="tooltipTemplate" [tooltip]="t.valueTooltip" [placement]="t.valueTooltipPlacement" [content]="t.value"></ng5-slider-tooltip-wrapper>
  3139. <span *ngIf="t.legend != null" class="ng5-slider-span ng5-slider-tick-legend" [innerHTML]="t.legend"></span>
  3140. </span>
  3141. </span>`,
  3142. styles: [`::ng-deep .ng5-slider{display:inline-block;position:relative;height:4px;width:100%;margin:35px 0 15px;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-ms-touch-action:pan-y;touch-action:pan-y}::ng-deep .ng5-slider.with-legend{margin-bottom:40px}::ng-deep .ng5-slider[disabled]{cursor:not-allowed}::ng-deep .ng5-slider[disabled] .ng5-slider-pointer{cursor:not-allowed;background-color:#d8e0f3}::ng-deep .ng5-slider[disabled] .ng5-slider-draggable{cursor:not-allowed}::ng-deep .ng5-slider[disabled] .ng5-slider-selection{background:#8b91a2}::ng-deep .ng5-slider[disabled] .ng5-slider-tick{cursor:not-allowed}::ng-deep .ng5-slider[disabled] .ng5-slider-tick.ng5-slider-selected{background:#8b91a2}::ng-deep .ng5-slider .ng5-slider-span{white-space:nowrap;position:absolute;display:inline-block}::ng-deep .ng5-slider .ng5-slider-base{width:100%;height:100%;padding:0}::ng-deep .ng5-slider .ng5-slider-bar-wrapper{left:0;-webkit-box-sizing:border-box;box-sizing:border-box;margin-top:-16px;padding-top:16px;width:100%;height:32px;z-index:1}::ng-deep .ng5-slider .ng5-slider-draggable{cursor:move}::ng-deep .ng5-slider .ng5-slider-bar{left:0;width:100%;height:4px;z-index:1;background:#d8e0f3;border-radius:2px}::ng-deep .ng5-slider .ng5-slider-bar-wrapper.ng5-slider-transparent .ng5-slider-bar{background:0 0}::ng-deep .ng5-slider .ng5-slider-bar-wrapper.ng5-slider-left-out-selection .ng5-slider-bar{background:#df002d}::ng-deep .ng5-slider .ng5-slider-bar-wrapper.ng5-slider-right-out-selection .ng5-slider-bar{background:#03a688}::ng-deep .ng5-slider .ng5-slider-selection{z-index:2;background:#0db9f0;border-radius:2px}::ng-deep .ng5-slider .ng5-slider-pointer{cursor:pointer;width:32px;height:32px;top:-14px;background-color:#0db9f0;z-index:3;border-radius:16px}::ng-deep .ng5-slider .ng5-slider-pointer:after{content:'';width:8px;height:8px;position:absolute;top:12px;left:12px;border-radius:4px;background:#fff}::ng-deep .ng5-slider .ng5-slider-pointer:hover:after{background-color:#fff}::ng-deep .ng5-slider .ng5-slider-pointer.ng5-slider-active{z-index:4}::ng-deep .ng5-slider .ng5-slider-pointer.ng5-slider-active:after{background-color:#451aff}::ng-deep .ng5-slider .ng5-slider-bubble{cursor:default;bottom:16px;padding:1px 3px;color:#55637d;font-size:16px}::ng-deep .ng5-slider .ng5-slider-bubble.ng5-slider-limit{color:#55637d}::ng-deep .ng5-slider .ng5-slider-ticks{-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;height:0;position:absolute;left:0;top:-3px;margin:0;z-index:1;list-style:none}::ng-deep .ng5-slider .ng5-slider-ticks-values-under .ng5-slider-tick-value{top:auto;bottom:-36px}::ng-deep .ng5-slider .ng5-slider-tick{text-align:center;cursor:pointer;width:10px;height:10px;background:#d8e0f3;border-radius:50%;position:absolute;top:0;left:0;margin-left:11px}::ng-deep .ng5-slider .ng5-slider-tick.ng5-slider-selected{background:#0db9f0}::ng-deep .ng5-slider .ng5-slider-tick-value{position:absolute;top:-34px;-webkit-transform:translate(-50%,0);transform:translate(-50%,0)}::ng-deep .ng5-slider .ng5-slider-tick-legend{position:absolute;top:24px;-webkit-transform:translate(-50%,0);transform:translate(-50%,0);max-width:50px;white-space:normal}::ng-deep .ng5-slider.vertical{position:relative;width:4px;height:100%;margin:0 20px;padding:0;vertical-align:baseline;-ms-touch-action:pan-x;touch-action:pan-x}::ng-deep .ng5-slider.vertical .ng5-slider-base{width:100%;height:100%;padding:0}::ng-deep .ng5-slider.vertical .ng5-slider-bar-wrapper{top:auto;left:0;margin:0 0 0 -16px;padding:0 0 0 16px;height:100%;width:32px}::ng-deep .ng5-slider.vertical .ng5-slider-bar{bottom:0;left:auto;width:4px;height:100%}::ng-deep .ng5-slider.vertical .ng5-slider-pointer{left:-14px!important;top:auto;bottom:0}::ng-deep .ng5-slider.vertical .ng5-slider-bubble{left:16px!important;bottom:0}::ng-deep .ng5-slider.vertical .ng5-slider-ticks{height:100%;width:0;left:-3px;top:0;z-index:1}::ng-deep .ng5-slider.vertical .ng5-slider-tick{vertical-align:middle;margin-left:auto;margin-top:11px}::ng-deep .ng5-slider.vertical .ng5-slider-tick-value{left:24px;top:auto;-webkit-transform:translate(0,-28%);transform:translate(0,-28%)}::ng-deep .ng5-slider.vertical .ng5-slider-tick-legend{top:auto;right:24px;-webkit-transform:translate(0,-28%);transform:translate(0,-28%);max-width:none;white-space:nowrap}::ng-deep .ng5-slider.vertical .ng5-slider-ticks-values-under .ng5-slider-tick-value{bottom:auto;left:auto;right:24px}::ng-deep .ng5-slider *{-webkit-transition:none;transition:none}::ng-deep .ng5-slider.animate .ng5-slider-bar-wrapper{-webkit-transition:all linear .3s;transition:all linear .3s}::ng-deep .ng5-slider.animate .ng5-slider-selection{-webkit-transition:background-color linear .3s;transition:background-color linear .3s}::ng-deep .ng5-slider.animate .ng5-slider-pointer{-webkit-transition:all linear .3s;transition:all linear .3s}::ng-deep .ng5-slider.animate .ng5-slider-bubble{-webkit-transition:all linear .3s;transition:all linear .3s}::ng-deep .ng5-slider.animate .ng5-slider-bubble.ng5-slider-limit{-webkit-transition:opacity linear .3s;transition:opacity linear .3s}::ng-deep .ng5-slider.animate .ng5-slider-bubble.ng5-slider-combined{-webkit-transition:opacity linear .3s;transition:opacity linear .3s}::ng-deep .ng5-slider.animate .ng5-slider-tick{-webkit-transition:background-color linear .3s;transition:background-color linear .3s}`],
  3143. host: { class: 'ng5-slider' },
  3144. providers: [NG5_SLIDER_CONTROL_VALUE_ACCESSOR]
  3145. },] },
  3146. ];
  3147. /** @nocollapse */
  3148. SliderComponent.ctorParameters = () => [
  3149. { type: Renderer2, },
  3150. { type: ElementRef, },
  3151. { type: ChangeDetectorRef, },
  3152. { type: NgZone, },
  3153. ];
  3154. SliderComponent.propDecorators = {
  3155. "value": [{ type: Input },],
  3156. "valueChange": [{ type: Output },],
  3157. "highValue": [{ type: Input },],
  3158. "highValueChange": [{ type: Output },],
  3159. "options": [{ type: Input },],
  3160. "userChangeStart": [{ type: Output },],
  3161. "userChange": [{ type: Output },],
  3162. "userChangeEnd": [{ type: Output },],
  3163. "manualRefresh": [{ type: Input },],
  3164. "triggerFocus": [{ type: Input },],
  3165. "leftOuterSelectionBarElement": [{ type: ViewChild, args: ['leftOuterSelectionBar', { read: SliderElementDirective },] },],
  3166. "rightOuterSelectionBarElement": [{ type: ViewChild, args: ['rightOuterSelectionBar', { read: SliderElementDirective },] },],
  3167. "fullBarElement": [{ type: ViewChild, args: ['fullBar', { read: SliderElementDirective },] },],
  3168. "selectionBarElement": [{ type: ViewChild, args: ['selectionBar', { read: SliderElementDirective },] },],
  3169. "minHandleElement": [{ type: ViewChild, args: ['minHandle', { read: SliderHandleDirective },] },],
  3170. "maxHandleElement": [{ type: ViewChild, args: ['maxHandle', { read: SliderHandleDirective },] },],
  3171. "floorLabelElement": [{ type: ViewChild, args: ['floorLabel', { read: SliderLabelDirective },] },],
  3172. "ceilLabelElement": [{ type: ViewChild, args: ['ceilLabel', { read: SliderLabelDirective },] },],
  3173. "minHandleLabelElement": [{ type: ViewChild, args: ['minHandleLabel', { read: SliderLabelDirective },] },],
  3174. "maxHandleLabelElement": [{ type: ViewChild, args: ['maxHandleLabel', { read: SliderLabelDirective },] },],
  3175. "combinedLabelElement": [{ type: ViewChild, args: ['combinedLabel', { read: SliderLabelDirective },] },],
  3176. "ticksElement": [{ type: ViewChild, args: ['ticksElement', { read: SliderElementDirective },] },],
  3177. "tooltipTemplate": [{ type: ContentChild, args: ['tooltipTemplate',] },],
  3178. "sliderElementVerticalClass": [{ type: HostBinding, args: ['class.vertical',] },],
  3179. "sliderElementAnimateClass": [{ type: HostBinding, args: ['class.animate',] },],
  3180. "sliderElementDisabledAttr": [{ type: HostBinding, args: ['attr.disabled',] },],
  3181. "onResize": [{ type: HostListener, args: ['window:resize', ['$event'],] },],
  3182. };
  3183. /**
  3184. * @fileoverview added by tsickle
  3185. * @suppress {checkTypes} checked by tsc
  3186. */
  3187. class TooltipWrapperComponent {
  3188. }
  3189. TooltipWrapperComponent.decorators = [
  3190. { type: Component, args: [{
  3191. selector: 'ng5-slider-tooltip-wrapper',
  3192. template: `<ng-container *ngIf="template">
  3193. <ng-template *ngTemplateOutlet="template; context: {tooltip: tooltip, placement: placement, content: content}"></ng-template>
  3194. </ng-container>
  3195. <ng-container *ngIf="!template">
  3196. <div class="ng5-slider-inner-tooltip" [attr.title]="tooltip" [attr.data-tooltip-placement]="placement">
  3197. {{content}}
  3198. </div>
  3199. </ng-container>`,
  3200. styles: [`.ng5-slider-inner-tooltip{height:100%}`]
  3201. },] },
  3202. ];
  3203. /** @nocollapse */
  3204. TooltipWrapperComponent.ctorParameters = () => [];
  3205. TooltipWrapperComponent.propDecorators = {
  3206. "template": [{ type: Input },],
  3207. "tooltip": [{ type: Input },],
  3208. "placement": [{ type: Input },],
  3209. "content": [{ type: Input },],
  3210. };
  3211. /**
  3212. * @fileoverview added by tsickle
  3213. * @suppress {checkTypes} checked by tsc
  3214. */
  3215. /**
  3216. * Ng5Slider module
  3217. *
  3218. * The module exports the slider component
  3219. */
  3220. class Ng5SliderModule {
  3221. }
  3222. Ng5SliderModule.decorators = [
  3223. { type: NgModule, args: [{
  3224. imports: [
  3225. CommonModule
  3226. ],
  3227. declarations: [
  3228. SliderComponent,
  3229. SliderElementDirective,
  3230. SliderHandleDirective,
  3231. SliderLabelDirective,
  3232. TooltipWrapperComponent
  3233. ],
  3234. exports: [
  3235. SliderComponent
  3236. ]
  3237. },] },
  3238. ];
  3239. /** @nocollapse */
  3240. Ng5SliderModule.ctorParameters = () => [];
  3241. /**
  3242. * @fileoverview added by tsickle
  3243. * @suppress {checkTypes} checked by tsc
  3244. */
  3245. /**
  3246. * @fileoverview added by tsickle
  3247. * @suppress {checkTypes} checked by tsc
  3248. */
  3249. /**
  3250. * Generated bundle index. Do not edit.
  3251. */
  3252. export { Ng5SliderModule, ChangeContext, PointerType, LabelType, Options, SliderElementDirective as ɵb, SliderHandleDirective as ɵc, SliderLabelDirective as ɵd, SliderComponent as ɵa, TooltipWrapperComponent as ɵe };
  3253. //# sourceMappingURL=ng5-slider.js.map