@syncfusion/ej2-inputs 30.2.6 → 31.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/ej2-inputs.min.js +2 -2
  2. package/dist/ej2-inputs.umd.min.js +2 -2
  3. package/dist/ej2-inputs.umd.min.js.map +1 -1
  4. package/dist/es6/ej2-inputs.es2015.js +1 -1
  5. package/dist/es6/ej2-inputs.es2015.js.map +1 -1
  6. package/dist/es6/ej2-inputs.es5.js +1 -1
  7. package/dist/es6/ej2-inputs.es5.js.map +1 -1
  8. package/dist/global/ej2-inputs.min.js +2 -2
  9. package/dist/global/ej2-inputs.min.js.map +1 -1
  10. package/dist/global/index.d.ts +1 -1
  11. package/dist/ts/color-picker/color-picker-model.d.ts +186 -0
  12. package/dist/ts/color-picker/color-picker.d.ts +398 -0
  13. package/dist/ts/color-picker/color-picker.ts +2209 -0
  14. package/dist/ts/color-picker/index.d.ts +5 -0
  15. package/dist/ts/color-picker/index.ts +5 -0
  16. package/dist/ts/common/index.d.ts +4 -0
  17. package/dist/ts/common/index.ts +4 -0
  18. package/dist/ts/common/signature-base.d.ts +340 -0
  19. package/dist/ts/common/signature-base.ts +1170 -0
  20. package/dist/ts/form-validator/form-validator-model.d.ts +121 -0
  21. package/dist/ts/form-validator/form-validator.d.ts +312 -0
  22. package/dist/ts/form-validator/form-validator.ts +1068 -0
  23. package/dist/ts/form-validator/index.d.ts +5 -0
  24. package/dist/ts/form-validator/index.ts +5 -0
  25. package/dist/ts/index.d.ts +18 -0
  26. package/dist/ts/index.ts +18 -0
  27. package/dist/ts/input/index.d.ts +4 -0
  28. package/dist/ts/input/index.ts +4 -0
  29. package/dist/ts/input/input.d.ts +345 -0
  30. package/dist/ts/input/input.ts +1277 -0
  31. package/dist/ts/maskedtextbox/base/index.d.ts +4 -0
  32. package/dist/ts/maskedtextbox/base/index.ts +4 -0
  33. package/dist/ts/maskedtextbox/base/mask-base.d.ts +134 -0
  34. package/dist/ts/maskedtextbox/base/mask-base.ts +1207 -0
  35. package/dist/ts/maskedtextbox/index.d.ts +5 -0
  36. package/dist/ts/maskedtextbox/index.ts +5 -0
  37. package/dist/ts/maskedtextbox/maskedtextbox/index.d.ts +5 -0
  38. package/dist/ts/maskedtextbox/maskedtextbox/index.ts +5 -0
  39. package/dist/ts/maskedtextbox/maskedtextbox/maskedtextbox-model.d.ts +167 -0
  40. package/dist/ts/maskedtextbox/maskedtextbox/maskedtextbox.d.ts +307 -0
  41. package/dist/ts/maskedtextbox/maskedtextbox/maskedtextbox.ts +709 -0
  42. package/dist/ts/numerictextbox/index.d.ts +5 -0
  43. package/dist/ts/numerictextbox/index.ts +5 -0
  44. package/dist/ts/numerictextbox/numerictextbox-model.d.ts +228 -0
  45. package/dist/ts/numerictextbox/numerictextbox.d.ts +431 -0
  46. package/dist/ts/numerictextbox/numerictextbox.ts +1672 -0
  47. package/dist/ts/otp-input/index.d.ts +5 -0
  48. package/dist/ts/otp-input/index.ts +5 -0
  49. package/dist/ts/otp-input/otp-input-model.d.ts +165 -0
  50. package/dist/ts/otp-input/otp-input.d.ts +365 -0
  51. package/dist/ts/otp-input/otp-input.ts +924 -0
  52. package/dist/ts/rating/index.d.ts +5 -0
  53. package/dist/ts/rating/index.ts +5 -0
  54. package/dist/ts/rating/rating-model.d.ts +239 -0
  55. package/dist/ts/rating/rating.d.ts +416 -0
  56. package/dist/ts/rating/rating.ts +1101 -0
  57. package/dist/ts/signature/index.d.ts +5 -0
  58. package/dist/ts/signature/index.ts +5 -0
  59. package/dist/ts/signature/signature-model.d.ts +131 -0
  60. package/dist/ts/signature/signature.d.ts +167 -0
  61. package/dist/ts/signature/signature.ts +266 -0
  62. package/dist/ts/slider/index.d.ts +5 -0
  63. package/dist/ts/slider/index.ts +5 -0
  64. package/dist/ts/slider/slider-model.d.ts +401 -0
  65. package/dist/ts/slider/slider.d.ts +721 -0
  66. package/dist/ts/slider/slider.ts +3497 -0
  67. package/dist/ts/smart-textarea/caret-helper.d.ts +17 -0
  68. package/dist/ts/smart-textarea/caret-helper.ts +95 -0
  69. package/dist/ts/smart-textarea/index.d.ts +5 -0
  70. package/dist/ts/smart-textarea/index.ts +5 -0
  71. package/dist/ts/smart-textarea/smart-textarea-model.d.ts +44 -0
  72. package/dist/ts/smart-textarea/smart-textarea.d.ts +80 -0
  73. package/dist/ts/smart-textarea/smart-textarea.ts +518 -0
  74. package/dist/ts/speech-to-text/index.d.ts +5 -0
  75. package/dist/ts/speech-to-text/index.ts +5 -0
  76. package/dist/ts/speech-to-text/speech-to-text-model.d.ts +270 -0
  77. package/dist/ts/speech-to-text/speech-to-text.d.ts +487 -0
  78. package/dist/ts/speech-to-text/speech-to-text.ts +1008 -0
  79. package/dist/ts/textarea/index.d.ts +5 -0
  80. package/dist/ts/textarea/index.ts +5 -0
  81. package/dist/ts/textarea/textarea-model.d.ts +161 -0
  82. package/dist/ts/textarea/textarea.d.ts +237 -0
  83. package/dist/ts/textarea/textarea.ts +812 -0
  84. package/dist/ts/textbox/index.d.ts +5 -0
  85. package/dist/ts/textbox/index.ts +5 -0
  86. package/dist/ts/textbox/textbox-model.d.ts +155 -0
  87. package/dist/ts/textbox/textbox.d.ts +288 -0
  88. package/dist/ts/textbox/textbox.ts +872 -0
  89. package/dist/ts/uploader/index.d.ts +5 -0
  90. package/dist/ts/uploader/index.ts +5 -0
  91. package/dist/ts/uploader/uploader-model.d.ts +555 -0
  92. package/dist/ts/uploader/uploader.d.ts +1216 -0
  93. package/dist/ts/uploader/uploader.ts +4391 -0
  94. package/package.json +62 -12
  95. package/src/input/input.js +1 -1
  96. package/styles/input/_layout.scss +0 -1
  97. package/styles/input/tailwind3.css +0 -1
  98. package/styles/tailwind3-lite.css +0 -1
  99. package/styles/tailwind3.css +0 -1
@@ -0,0 +1,2209 @@
1
+ /* eslint-disable prefer-spread */
2
+ import { BaseEventArgs, Component, EmitType, Event, INotifyPropertyChanged, NotifyPropertyChanges, Property } from '@syncfusion/ej2-base';
3
+ import { Browser, closest, detach, EventHandler, getInstance, select, selectAll, formatUnit } from '@syncfusion/ej2-base';
4
+ import { addClass, attributes, classList, isNullOrUndefined, L10n } from '@syncfusion/ej2-base';
5
+ import { remove, removeClass, rippleEffect } from '@syncfusion/ej2-base';
6
+ import { SplitButton, BeforeOpenCloseMenuEventArgs, getModel } from '@syncfusion/ej2-splitbuttons';
7
+ import { Deferred } from '@syncfusion/ej2-splitbuttons';
8
+ import { Tooltip, TooltipEventArgs, getZindexPartial, Popup, isCollide } from '@syncfusion/ej2-popups';
9
+ import { Input } from './../input/index';
10
+ import { NumericTextBox, NumericTextBoxModel, ChangeEventArgs } from './../numerictextbox/index';
11
+ import { Slider, SliderChangeEventArgs } from './../slider/slider';
12
+ import { ColorPickerModel } from './color-picker-model';
13
+
14
+ /**
15
+ * Defines the ColorPicker Mode
16
+ * ```props
17
+ * Picker :- Specifies that the ColorPicker component should be rendered with the picker mode.
18
+ * Palette :- Specifies that the ColorPicker component should be rendered with the palette mode.
19
+ * ```
20
+ */
21
+ export type ColorPickerMode = 'Picker' | 'Palette';
22
+
23
+ const APPLY: string = 'e-apply';
24
+ const CANCEL: string = 'e-cancel';
25
+ const CURRENT: string = 'e-current';
26
+ const CONTAINER: string = 'e-container';
27
+ const CTRLBTN: string = 'e-ctrl-btn';
28
+ const CTRLSWITCH: string = 'e-switch-ctrl-btn';
29
+ const DISABLED: string = 'e-disabled';
30
+ const FORMATSWITCH: string = 'e-value-switch-btn';
31
+ const HANDLER: string = 'e-handler';
32
+ const HEX: string = 'e-hex';
33
+ const HIDEHEX: string = 'e-hide-hex-value';
34
+ const HIDEOPACITY: string = 'e-hide-opacity';
35
+ const HIDERGBA: string = 'e-hide-switchable-value';
36
+ const HIDEVALUE: string = 'e-hide-value';
37
+ const HIDEVALUESWITCH: string = 'e-hide-valueswitcher';
38
+ const HSVAREA: string = 'e-hsv-color';
39
+ const HSVCONTAINER: string = 'e-hsv-container';
40
+ const INPUTWRAPPER: string = 'e-selected-value';
41
+ const MODESWITCH: string = 'e-mode-switch-btn';
42
+ const NOCOLOR: string = 'e-nocolor-item';
43
+ const OPACITY: string = 'e-opacity-value';
44
+ const PALETTES: string = 'e-palette';
45
+ const PALETTECONTENT: string = 'e-color-palette';
46
+ const PICKERCONTENT: string = 'e-color-picker';
47
+ const PREVIEW: string = 'e-preview-container';
48
+ const PREVIOUS: string = 'e-previous';
49
+ const RTL: string = 'e-rtl';
50
+ const SHOWVALUE: string = 'e-show-value';
51
+ const SELECT: string = 'e-selected';
52
+ const SPLITPREVIEW: string = 'e-split-preview';
53
+ const TILE: string = 'e-tile';
54
+
55
+ const presets: { [key: string]: string[] } = {
56
+ default: ['#000000', '#f44336', '#e91e63', '#9c27b0', '#673ab7', '#2196f3', '#03a9f4', '#00bcd4', '#009688', '#ffeb3b',
57
+ '#ffffff', '#ffebee', '#fce4ec', '#f3e5f5', '#ede7f6', '#e3f2fd', '#e1f5fe', '#e0f7fa', '#e0f2f1', '#fffde7',
58
+ '#f2f2f2', '#ffcdd2', '#f8bbd0', '#e1bee7', '#d1c4e9', '#bbdefb', '#b3e5fc', '#b2ebf2', '#b2dfdb', '#fff9c4',
59
+ '#e6e6e6', '#ef9a9a', '#f48fb1', '#ce93d8', '#b39ddb', '#90caf9', '#81d4fa', '#80deea', '#80cbc4', '#fff59d',
60
+ '#cccccc', '#e57373', '#f06292', '#ba68c8', '#9575cd', '#64b5f6', '#4fc3f7', '#4dd0e1', '#4db6ac', '#fff176',
61
+ '#b3b3b3', '#ef5350', '#ec407a', '#ab47bc', '#7e57c2', '#42a5f5', '#29b6f6', '#26c6da', '#26a69a', '#ffee58',
62
+ '#999999', '#e53935', '#d81b60', '#8e24aa', '#5e35b1', '#1e88e5', '#039be5', '#00acc1', '#00897b', '#fdd835',
63
+ '#808080', '#d32f2f', '#c2185b', '#7b1fa2', '#512da8', '#1976d2', '#0288d1', '#0097a7', '#00796b', '#fbc02d',
64
+ '#666666', '#c62828', '#ad1457', '#6a1b9a', '#4527a0', '#1565c0', '#0277bd', '#00838f', '#00695c', '#f9a825',
65
+ '#4d4d4d', '#b71c1c', '#880e4f', '#4a148c', '#311b92', '#0d47a1', '#01579b', '#006064', '#004d40', '#f57f17']
66
+ };
67
+
68
+ /**
69
+ * ColorPicker component is a user interface to select and adjust color values. It provides supports for various
70
+ * color specification like Red Green Blue, Hue Saturation Value and Hex codes.
71
+ * ```html
72
+ * <input type="color" id="color-picker">
73
+ * ```
74
+ * ```typescript
75
+ * <script>
76
+ * let colorPickerObj: ColorPicker = new ColorPicker(null , "#color-picker");
77
+ * </script>
78
+ * ```
79
+ */
80
+
81
+ @NotifyPropertyChanges
82
+ export class ColorPicker extends Component<HTMLInputElement> implements INotifyPropertyChanged {
83
+ /* Private variables */
84
+ private splitBtn: SplitButton;
85
+ private hueSlider: Slider;
86
+ private opacitySlider: Slider;
87
+ private tooltipEle: HTMLElement;
88
+ private container: HTMLElement;
89
+ private modal: HTMLElement;
90
+ private isRgb: boolean;
91
+ private l10n: L10n;
92
+ private tileRipple: Function;
93
+ private ctrlBtnRipple: Function;
94
+ private clientX: number;
95
+ private clientY: number;
96
+ private rgb: number[];
97
+ private hsv: number[];
98
+ private formElement: HTMLFormElement;
99
+ private initialInputValue: string;
100
+ private recentColors: string[] = [];
101
+ /**
102
+ * It is used to set the color value for ColorPicker. It should be specified as Hex code.
103
+ *
104
+ * @default '#008000ff'
105
+ */
106
+ @Property('#008000ff')
107
+ public value: string;
108
+
109
+ /**
110
+ * This property sets the CSS classes to root element of the ColorPicker
111
+ * which helps to customize the UI styles.
112
+ *
113
+ * @default ''
114
+ */
115
+ @Property('')
116
+ public cssClass: string;
117
+
118
+ /**
119
+ * It is used to enable / disable ColorPicker component. If it is disabled the ColorPicker popup won’t open.
120
+ *
121
+ * @default false
122
+ */
123
+ @Property(false)
124
+ public disabled: boolean;
125
+
126
+ /**
127
+ * It is used to render the ColorPicker with the specified mode.
128
+ *
129
+ * @default 'Picker'
130
+ */
131
+ @Property('Picker')
132
+ public mode: ColorPickerMode;
133
+
134
+ /**
135
+ * It is used to show / hide the mode switcher button of ColorPicker component.
136
+ *
137
+ * @default true
138
+ */
139
+ @Property(true)
140
+ public modeSwitcher: boolean;
141
+
142
+ /**
143
+ * It is used to load custom colors to palette.
144
+ *
145
+ * @default null
146
+ */
147
+ @Property(null)
148
+ public presetColors: { [key: string]: string[] };
149
+
150
+ /**
151
+ * It is used to show / hide the control buttons (apply / cancel) of ColorPicker component.
152
+ *
153
+ * @default true
154
+ */
155
+ @Property(true)
156
+ public showButtons: boolean;
157
+
158
+ /**
159
+ * It is used to render the ColorPicker palette with specified columns.
160
+ *
161
+ * @default 10
162
+ */
163
+ @Property(10)
164
+ public columns: number;
165
+
166
+ /**
167
+ * It is used to render the ColorPicker component as inline.
168
+ *
169
+ * @default false
170
+ */
171
+ @Property(false)
172
+ public inline: boolean;
173
+
174
+ /**
175
+ * It is used to enable / disable the no color option of ColorPicker component.
176
+ *
177
+ * @default false
178
+ */
179
+ @Property(false)
180
+ public noColor: boolean;
181
+
182
+ /**
183
+ * To enable or disable persisting component's state between page reloads and it is extended from component class.
184
+ *
185
+ * @default false
186
+ */
187
+ @Property(false)
188
+ public enablePersistence: boolean;
189
+
190
+ /**
191
+ * It is used to enable / disable the opacity option of ColorPicker component.
192
+ *
193
+ * @default true
194
+ */
195
+ @Property(true)
196
+ public enableOpacity: boolean;
197
+
198
+ /**
199
+ * Specifies the popup element creation on open.
200
+ *
201
+ * @default false
202
+ */
203
+ @Property(false)
204
+ public createPopupOnClick: boolean;
205
+
206
+ /**
207
+ * Specifies to show the recent color options in the color picker in the palate mode.
208
+ * It accepts boolean value to configure recent colors. The default value is false.
209
+ * If this property value is false, then the recent color user interface is not rendered in color picker component.
210
+      * This recent color option is rendered only in the palette mode.
211
+ *
212
+ * @default false
213
+ */
214
+ @Property(false)
215
+ public showRecentColors: boolean;
216
+
217
+ /**
218
+ * Triggers while selecting the color in picker / palette, when showButtons property is enabled.
219
+ *
220
+ * @event select
221
+ * @blazorProperty 'Selected'
222
+ */
223
+ @Event()
224
+ public select: EmitType<ColorPickerEventArgs>;
225
+
226
+ /**
227
+ * Triggers while changing the colors. It will be triggered based on the showButtons property.
228
+ * If the property is false, the event will be triggered while selecting the colors.
229
+ * If the property is true, the event will be triggered while apply the selected color.
230
+ *
231
+ * @event change
232
+ * @blazorProperty 'ValueChange'
233
+ */
234
+ @Event()
235
+ public change: EmitType<ColorPickerEventArgs>;
236
+
237
+ /**
238
+      * Trigger while rendering each palette tile.
239
+ *
240
+      * @event beforeTileRender
241
+ * @blazorProperty 'OnTileRender'
242
+      */
243
+ @Event()
244
+ public beforeTileRender: EmitType<PaletteTileEventArgs>;
245
+
246
+ /**
247
+      * Triggers before opening the ColorPicker popup.
248
+ *
249
+      * @event beforeOpen
250
+ * @blazorProperty 'OnOpen'
251
+      */
252
+ @Event()
253
+ public beforeOpen: EmitType<BeforeOpenCloseEventArgs>;
254
+
255
+ /**
256
+      * Triggers while opening the ColorPicker popup.
257
+ *
258
+      * @event open
259
+ * @blazorProperty 'Opened'
260
+      */
261
+ @Event()
262
+ public open: EmitType<OpenEventArgs>;
263
+
264
+ /**
265
+      * Triggers before closing the ColorPicker popup.
266
+ *
267
+      * @event beforeClose
268
+ * @blazorProperty 'OnClose'
269
+      */
270
+ @Event()
271
+ public beforeClose: EmitType<BeforeOpenCloseEventArgs>;
272
+
273
+ /**
274
+      * Triggers before Switching between ColorPicker mode.
275
+ *
276
+      * @event beforeModeSwitch
277
+ * @blazorProperty 'OnModeSwitch'
278
+      */
279
+ @Event()
280
+ public beforeModeSwitch: EmitType<ModeSwitchEventArgs>;
281
+
282
+ /**
283
+      * Triggers after Switching between ColorPicker mode.
284
+ *
285
+      * @event onModeSwitch
286
+ * @blazorProperty 'ModeSwitched'
287
+      */
288
+ @Event()
289
+ public onModeSwitch: EmitType<ModeSwitchEventArgs>;
290
+
291
+ /**
292
+ * Triggers once the component rendering is completed.
293
+ *
294
+ * @event created
295
+ * @blazorProperty 'Created'
296
+ */
297
+ @Event()
298
+ public created: EmitType<Event>;
299
+
300
+ constructor(options?: ColorPickerModel, element?: string | HTMLInputElement) {
301
+ super(options, <HTMLInputElement | string>element);
302
+ }
303
+
304
+ protected preRender(): void {
305
+ const ele: Element = this.element;
306
+ this.formElement = <HTMLFormElement>closest(this.element, 'form');
307
+ if (this.formElement) {
308
+ EventHandler.add(this.formElement, 'reset', this.formResetHandler, this);
309
+ }
310
+
311
+ const localeText: object = { Apply: 'Apply', Cancel: 'Cancel', ModeSwitcher: 'Switch Mode', RecentColors: 'Recent colors' };
312
+ this.l10n = new L10n('colorpicker', localeText, this.locale);
313
+ if (ele.getAttribute('ejs-for') && !ele.getAttribute('name')) {
314
+ ele.setAttribute('name', ele.id);
315
+ }
316
+ }
317
+
318
+ /**
319
+ * To Initialize the component rendering
320
+ *
321
+ * @private
322
+ * @returns {void}
323
+ */
324
+ public render(): void {
325
+ this.initWrapper();
326
+ if (this.inline) {
327
+ this.createWidget();
328
+ } else {
329
+ this.createSplitBtn();
330
+ }
331
+ if (!this.enableOpacity) {
332
+ addClass([this.container.parentElement], HIDEOPACITY);
333
+ }
334
+ this.renderComplete();
335
+ }
336
+
337
+ private initWrapper(): void {
338
+ const wrapper: HTMLElement = this.createElement('div', { className: 'e-' + this.getModuleName() + '-wrapper' });
339
+ this.element.parentNode.insertBefore(wrapper, this.element);
340
+ wrapper.appendChild(this.element);
341
+ attributes(this.element, { 'tabindex': '-1', 'spellcheck': 'false', 'aria-label': 'colorpicker' });
342
+ this.container = this.createElement('div', { className: CONTAINER });
343
+ this.getWrapper().appendChild(this.container);
344
+ let value: string = this.value ? this.roundValue(this.value).toLowerCase() : '#008000ff';
345
+ if (this.noColor && this.mode === 'Palette' && this.value === '') {
346
+ value = '';
347
+ }
348
+ const slicedValue: string = value.slice(0, 7);
349
+ if (isNullOrUndefined(this.initialInputValue)) {
350
+ this.initialInputValue = slicedValue;
351
+ }
352
+ this.element.value = slicedValue;
353
+ if (this.enableOpacity) {
354
+ this.setProperties({ 'value': value }, true);
355
+ } else {
356
+ this.setProperties({ 'value': slicedValue }, true);
357
+ }
358
+
359
+ if (this.enableRtl) {
360
+ wrapper.classList.add(RTL);
361
+ }
362
+ if (this.cssClass) {
363
+ addClass([wrapper], this.cssClass.replace(/\s+/g, ' ').trim().split(' '));
364
+ }
365
+ this.tileRipple = rippleEffect(this.container, { selector: '.' + TILE });
366
+ this.ctrlBtnRipple = rippleEffect(this.container, { selector: '.e-btn' });
367
+ }
368
+
369
+ private getWrapper(): HTMLElement {
370
+ return this.element.parentElement;
371
+ }
372
+
373
+ private createWidget(): void {
374
+ if (this.mode === 'Palette') {
375
+ this.createPalette();
376
+ if (!this.inline) {
377
+ this.firstPaletteFocus();
378
+ }
379
+ } else {
380
+ this.createPicker();
381
+ if (!this.inline) {
382
+ this.getDragHandler().focus();
383
+ }
384
+ }
385
+ this.isRgb = true;
386
+ this.createInput();
387
+ this.createCtrlBtn();
388
+ if (!this.disabled) {
389
+ this.wireEvents();
390
+ }
391
+ if (this.inline && this.disabled) {
392
+ this.toggleDisabled(true);
393
+ }
394
+ if (Browser.isDevice) {
395
+ this.refreshPopupPos();
396
+ }
397
+ }
398
+
399
+ private createSplitBtn(): void {
400
+ const splitButton: HTMLButtonElement = this.createElement('button', { className: 'e-split-colorpicker' }) as HTMLButtonElement;
401
+ this.getWrapper().appendChild(splitButton);
402
+ this.splitBtn = new SplitButton(
403
+ {
404
+ iconCss: 'e-selected-color',
405
+ target: this.container,
406
+ disabled: this.disabled,
407
+ enableRtl: this.enableRtl,
408
+ createPopupOnClick: this.createPopupOnClick,
409
+ open: this.onOpen.bind(this),
410
+ click: () => {
411
+ const ev: MouseEvent = new MouseEvent('click', { bubbles: true, cancelable: false });
412
+ this.trigger('change', {
413
+ currentValue: { hex: this.value.slice(0, 7), rgba: this.convertToRgbString(this.hexToRgb(this.value)) },
414
+ previousValue: { hex: null, rgba: null }, value: this.value, event: ev
415
+ });
416
+ }
417
+ });
418
+ this.splitBtn.createElement = this.createElement;
419
+ this.splitBtn.appendTo(splitButton);
420
+ this.splitBtn.element.setAttribute('aria-label', 'colorpicker');
421
+ const preview: HTMLElement = this.createElement('span', { className: SPLITPREVIEW });
422
+ select('.e-selected-color', splitButton).appendChild(preview);
423
+ preview.style.backgroundColor = this.convertToRgbString(this.hexToRgb(this.value));
424
+ const popupEle: HTMLElement = this.getPopupEle();
425
+ addClass([popupEle], 'e-colorpicker-popup');
426
+ if (this.cssClass) {
427
+ const classes: string[] = this.cssClass.replace(/\s+/g, ' ').trim().split(' ');
428
+ if (popupEle) {
429
+ addClass([popupEle], classes);
430
+ }
431
+ if (this.splitBtn && this.splitBtn.activeElem && this.splitBtn.activeElem[0]) {
432
+ addClass([this.splitBtn.activeElem[0]], classes);
433
+ }
434
+ if (this.splitBtn && this.splitBtn.activeElem && this.splitBtn.activeElem[1]) {
435
+ addClass([this.splitBtn.activeElem[1]], classes);
436
+ }
437
+ if (this.splitBtn && this.splitBtn.element && this.splitBtn.element.parentElement) {
438
+ addClass([this.splitBtn.element.parentElement], classes);
439
+ }
440
+ }
441
+ if (Browser.isDevice && !this.createPopupOnClick) {
442
+ const popupInst: Popup = this.getPopupInst();
443
+ popupInst.relateTo = document.body;
444
+ popupInst.position = { X: 'center', Y: 'center' };
445
+ popupInst.targetType = 'container';
446
+ popupInst.collision = { X: 'fit', Y: 'fit' };
447
+ popupInst.offsetY = 4;
448
+ popupEle.style.zIndex = getZindexPartial(this.splitBtn.element).toString();
449
+ }
450
+ this.bindCallBackEvent();
451
+ }
452
+
453
+ private onOpen(): void {
454
+ this.trigger('open', <OpenEventArgs>{ element: this.container });
455
+ if (!Browser.isDevice) {
456
+ const popupInst: Popup = this.getPopupInst();
457
+ const collision: string[] = isCollide(popupInst.element);
458
+ if (collision.length > 0) {
459
+ popupInst.collision = { X: 'flip', Y: 'fit' };
460
+ popupInst.position = { X: 'right', Y: 'bottom' };
461
+ popupInst.targetType = 'container';
462
+ }
463
+ }
464
+ }
465
+
466
+ private getPopupInst(): Popup {
467
+ return getInstance(this.getPopupEle(), Popup) as Popup;
468
+ }
469
+
470
+ private bindCallBackEvent() : void {
471
+ this.splitBtn.beforeOpen = (args: BeforeOpenCloseMenuEventArgs): Deferred | void => {
472
+ const callBackPromise: Deferred = new Deferred();
473
+ this.trigger('beforeOpen', args, (observeOpenArgs: BeforeOpenCloseMenuEventArgs) => {
474
+ if (!observeOpenArgs.cancel) {
475
+ const popupEle: HTMLElement = this.getPopupEle();
476
+ popupEle.style.top = formatUnit(0 + pageYOffset);
477
+ popupEle.style.left = formatUnit(0 + pageXOffset);
478
+ popupEle.style.display = 'block';
479
+ this.createWidget();
480
+ popupEle.style.display = '';
481
+ if (Browser.isDevice) {
482
+ if (this.createPopupOnClick) {
483
+ const popupInst: Popup = this.getPopupInst();
484
+ popupInst.relateTo = document.body;
485
+ popupInst.position = { X: 'center', Y: 'center' };
486
+ popupInst.targetType = 'container';
487
+ popupInst.collision = { X: 'fit', Y: 'fit' };
488
+ popupInst.offsetY = 4;
489
+ popupEle.style.zIndex = getZindexPartial(this.splitBtn.element).toString();
490
+ }
491
+ this.modal = this.createElement('div');
492
+ this.modal.className = 'e-' + this.getModuleName() + ' e-modal';
493
+ this.modal.style.display = 'none';
494
+ document.body.insertBefore(this.modal, popupEle);
495
+ document.body.className += ' e-colorpicker-overflow';
496
+ this.modal.style.display = 'block';
497
+ this.modal.style.zIndex = (Number(popupEle.style.zIndex) - 1).toString();
498
+ }
499
+ }
500
+ args.cancel = observeOpenArgs.cancel;
501
+ callBackPromise.resolve(observeOpenArgs);
502
+ });
503
+ return callBackPromise;
504
+ };
505
+ this.splitBtn.beforeClose = (args: BeforeOpenCloseMenuEventArgs): Deferred | void => {
506
+ const callBackPromise: Deferred = new Deferred();
507
+ if (!isNullOrUndefined(args.event)) {
508
+ const beforeCloseArgs: BeforeOpenCloseEventArgs = { element: this.container, event: args.event, cancel: false };
509
+ this.trigger('beforeClose', beforeCloseArgs, (observedCloseArgs: BeforeOpenCloseMenuEventArgs) => {
510
+ if (Browser.isDevice && args.event.target === this.modal) {
511
+ observedCloseArgs.cancel = true;
512
+ }
513
+ if (!observedCloseArgs.cancel) {
514
+ this.onPopupClose();
515
+ if (args.event.type === 'keydown' && (args.event as KeyboardEvent).keyCode === 27) {
516
+ this.splitBtn.element.focus();
517
+ }
518
+ }
519
+ args.cancel = observedCloseArgs.cancel;
520
+ callBackPromise.resolve(observedCloseArgs);
521
+ });
522
+ } else {
523
+ callBackPromise.resolve(args);
524
+ }
525
+ return callBackPromise;
526
+ };
527
+ }
528
+
529
+ private onPopupClose(): void {
530
+ this.unWireEvents();
531
+ this.destroyOtherComp();
532
+ this.container.style.width = '';
533
+ (select('.' + SPLITPREVIEW, this.splitBtn.element) as HTMLElement).style.backgroundColor
534
+ = this.convertToRgbString(this.hexToRgb(this.value));
535
+ this.container.innerHTML = '';
536
+ removeClass([this.container], [PICKERCONTENT, PALETTECONTENT]);
537
+ if (Browser.isDevice && this.modal) {
538
+ removeClass([document.body], 'e-colorpicker-overflow');
539
+ this.modal.style.display = 'none';
540
+ this.modal.outerHTML = '';
541
+ this.modal = null;
542
+ }
543
+ }
544
+
545
+ private createPalette(): void {
546
+ classList(this.container, [PALETTECONTENT], [PICKERCONTENT]);
547
+ if (this.presetColors) {
548
+ const paletteGroup: HTMLElement = this.createElement('div', { className: 'e-custom-palette' });
549
+ this.appendElement(paletteGroup);
550
+ const keys: string[] = Object.keys(this.presetColors as Object);
551
+ if (keys.length === 1) {
552
+ this.appendPalette(this.presetColors[keys[0]], keys[0], paletteGroup);
553
+ } else {
554
+ for (let i: number = 0, len: number = keys.length; i < len; i++) {
555
+ this.appendPalette(this.presetColors[keys[i as number]], keys[i as number], paletteGroup);
556
+ }
557
+ }
558
+ if (selectAll('.e-row', paletteGroup).length > 10) {
559
+ addClass([paletteGroup], 'e-palette-group');
560
+ }
561
+
562
+ } else {
563
+ this.appendPalette(presets.default, 'default');
564
+ }
565
+ if (this.mode === 'Palette' && !this.modeSwitcher && this.noColor) {
566
+ this.setNoColor();
567
+ }
568
+ if (this.showRecentColors && this.recentColors && this.recentColors.length > 0) {
569
+ this.renderRecentColor();
570
+ }
571
+ const width: number = parseInt(getComputedStyle(this.container).borderBottomWidth, 10);
572
+ this.container.style.width = formatUnit((this.container.children[0] as HTMLElement).offsetWidth + width + width);
573
+ this.rgb = this.hexToRgb(this.roundValue(this.value));
574
+ this.hsv = this.rgbToHsv.apply(this, this.rgb);
575
+ }
576
+
577
+ private renderRecentColor(): void {
578
+ const recentClrWpr: HTMLElement = this.container.querySelector('.e-clr-pal-rec-wpr');
579
+ if (recentClrWpr) { detach(recentClrWpr); }
580
+ const recentColorWrapper: HTMLElement = this.createElement('div', { className: 'e-clr-pal-rec-wpr' });
581
+ const refEle: HTMLElement = this.container.querySelector('.e-switch-ctrl-btn');
582
+ if (refEle) {
583
+ this.container.insertBefore(recentColorWrapper, refEle);
584
+ } else {
585
+ this.container.appendChild(recentColorWrapper);
586
+ }
587
+ const recentClrSpan: Element = this.createElement('label', { className: 'e-recent-clr-span' });
588
+ recentClrSpan.textContent = this.l10n.getConstant('RecentColors');
589
+ recentColorWrapper.appendChild(recentClrSpan);
590
+ if (this.recentColors.length > 0) {
591
+ this.recentColors = this.recentColors.filter((item: string, index: number) => this.recentColors.indexOf(item) === index);
592
+ while (this.recentColors.length > 10) {
593
+ this.recentColors.pop();
594
+ }
595
+ this.appendPalette(this.recentColors, 'recent-color', recentColorWrapper);
596
+ }
597
+ }
598
+
599
+ private firstPaletteFocus(): void {
600
+ if (!select('.' + SELECT, this.container.children[0])) {
601
+ selectAll('.' + PALETTES, this.container)[0].focus();
602
+ }
603
+ }
604
+
605
+ private appendPalette(colors: string[], key: string, refEle?: HTMLElement): void {
606
+ const palette: HTMLElement = this.createElement('div', { className: PALETTES, attrs: { 'tabindex': '0', 'role': 'grid' } });
607
+ if (key === 'recent-color') { palette.classList.add('e-recent-palette'); }
608
+ if (refEle) {
609
+ refEle.appendChild(palette);
610
+ } else {
611
+ this.appendElement(palette);
612
+ }
613
+ let row: HTMLElement; let tile: HTMLElement; let roundedColor: string;
614
+ for (let i: number = 0, len: number = colors.length; i < len; i++) {
615
+ if (i === 0 || i % this.columns === 0) {
616
+ row = this.createElement('div', {
617
+ className: 'e-row', attrs: { 'role': 'row' }
618
+ });
619
+ palette.appendChild(row);
620
+ }
621
+ roundedColor = this.roundValue(colors[i as number]).toLowerCase();
622
+ tile = this.createElement('span', {
623
+ className: TILE, attrs: { 'role': 'gridcell', 'aria-label': roundedColor, 'aria-selected': 'false' }
624
+ });
625
+ this.trigger('beforeTileRender', <PaletteTileEventArgs>{ element: tile, presetName: key, value: colors[i as number] });
626
+ row.appendChild(tile);
627
+ if (this.value === roundedColor && key !== 'recent-color') {
628
+ this.addTileSelection(tile);
629
+ palette.focus();
630
+ }
631
+ tile.style.backgroundColor = this.convertToRgbString(this.hexToRgb(roundedColor));
632
+ }
633
+ }
634
+
635
+ private setNoColor(): void {
636
+ const noColorEle: HTMLElement = this.container.querySelector('.e-row').children[0] as HTMLElement;
637
+ noColorEle.classList.add(NOCOLOR);
638
+ if (!this.value) {
639
+ noColorEle.classList.add(SELECT);
640
+ (closest(noColorEle, '.' + PALETTES) as HTMLElement).focus();
641
+ }
642
+ ['aria-selected', 'aria-label'].forEach((attr: string): void => { noColorEle.removeAttribute(attr); });
643
+ noColorEle.style.backgroundColor = '';
644
+ }
645
+
646
+ private appendElement(ele: Element, insertPos: number = 0): void {
647
+ const refEle: Element = this.container.children[insertPos as number];
648
+ if (refEle) {
649
+ this.container.insertBefore(ele, refEle);
650
+ } else {
651
+ this.container.appendChild(ele);
652
+ }
653
+ }
654
+
655
+ private addTileSelection(ele: Element): void {
656
+ if (ele) {
657
+ ele.classList.add(SELECT);
658
+ ele.setAttribute('aria-selected', 'true');
659
+ }
660
+ }
661
+
662
+ private createPicker(): void {
663
+ classList(this.container, [PICKERCONTENT], [PALETTECONTENT]);
664
+ const hsvContainer: HTMLElement = this.createElement('div', { className: HSVCONTAINER });
665
+ this.appendElement(hsvContainer);
666
+ hsvContainer.appendChild(this.createElement('div', { className: HSVAREA }));
667
+ const dragHandler: HTMLElement = this.createElement('span', { className: HANDLER, attrs: { 'tabindex': '0' } });
668
+ hsvContainer.appendChild(dragHandler);
669
+ if (this.value === null || this.value === '') {
670
+ this.value = '#008000ff';
671
+ }
672
+ this.rgb = this.hexToRgb(this.value);
673
+ this.hsv = this.rgbToHsv.apply(this, this.rgb);
674
+ this.setHsvContainerBg();
675
+ this.setHandlerPosition();
676
+ this.createSlider();
677
+ this.createDragTooltip();
678
+ }
679
+
680
+ private setHsvContainerBg(h: number = this.hsv[0]): void {
681
+ this.getHsvContainer().style.backgroundColor = this.convertToRgbString(this.hsvToRgb(h, 100, 100, 1));
682
+ }
683
+
684
+ private getHsvContainer(): HTMLElement {
685
+ return select('.' + HSVCONTAINER, this.container) as HTMLElement;
686
+ }
687
+
688
+ private setHandlerPosition(): void {
689
+ const dragHandler: HTMLElement = this.getDragHandler();
690
+ const hsvArea: HTMLElement = select('.' + HSVAREA, this.container) as HTMLElement;
691
+ if (this.enableRtl) {
692
+ dragHandler.style.left = formatUnit((hsvArea.offsetWidth - dragHandler.offsetWidth / 2.5) * Math.abs(100 - this.hsv[1]) / 100);
693
+ } else {
694
+ dragHandler.style.left = formatUnit((hsvArea.offsetWidth - dragHandler.offsetWidth / 2.5) * this.hsv[1] / 100);
695
+ }
696
+ dragHandler.style.top = formatUnit((hsvArea.offsetHeight - dragHandler.offsetHeight / 2.5) * (100 - this.hsv[2]) / 100);
697
+ }
698
+
699
+ private createSlider(): void {
700
+ const sliderPreviewWrapper: Element = this.createElement('div', { className: 'e-slider-preview' });
701
+ this.appendElement(sliderPreviewWrapper, 1);
702
+ this.createPreview(sliderPreviewWrapper);
703
+ const sliderWrapper: Element = this.createElement('div', { className: 'e-colorpicker-slider' });
704
+ sliderPreviewWrapper.insertBefore(sliderWrapper, sliderPreviewWrapper.children[0]);
705
+ let slider: HTMLElement = this.createElement('div', { className: 'e-hue-slider' });
706
+ sliderWrapper.appendChild(slider);
707
+ this.hueSlider = new Slider(
708
+ {
709
+ value: this.hsv[0],
710
+ min: 0,
711
+ max: 359,
712
+ enableRtl: this.enableRtl,
713
+ enabled: !this.disabled,
714
+ change: this.hueChange.bind(this)
715
+ });
716
+ this.hueSlider.createElement = this.createElement;
717
+ this.hueSlider.appendTo(slider);
718
+ if (this.enableOpacity) {
719
+ slider = this.createElement('div', { className: 'e-opacity-slider' });
720
+ sliderWrapper.appendChild(slider);
721
+ this.createOpacitySlider(slider);
722
+ }
723
+ }
724
+
725
+ private createOpacitySlider(slider: HTMLElement): void {
726
+ this.opacitySlider = new Slider(
727
+ {
728
+ value: this.rgb[3] * 100,
729
+ min: 0,
730
+ max: 100,
731
+ enableRtl: this.enableRtl,
732
+ enabled: !this.disabled,
733
+ change: this.opacityChange.bind(this)
734
+ });
735
+ this.opacitySlider.createElement = this.createElement;
736
+ this.opacitySlider.appendTo(slider);
737
+ const opacityBgTrack: HTMLElement = this.createElement('div', { className: 'e-opacity-empty-track' });
738
+ slider.appendChild(opacityBgTrack);
739
+ this.updateOpacitySliderBg();
740
+ }
741
+
742
+ private updateOpacitySliderBg(): void {
743
+ const direction: string = this.enableRtl ? 'to left' : 'to right';
744
+ const opacityEle: HTMLElement = select('.e-opacity-empty-track', this.opacitySlider.element) as HTMLElement;
745
+ if (opacityEle) {
746
+ opacityEle.style.background =
747
+ 'linear-gradient(' + direction + ', rgba(' + this.rgb.slice(0, 3) + ', 0) 0%, ' +
748
+ this.convertToRgbString(this.rgb.slice(0, 3)) + ' 100%)';
749
+ }
750
+ }
751
+
752
+ private hueChange(args: SliderChangeEventArgs): void {
753
+ this.hsv[0] = args.value as number;
754
+ this.setHsvContainerBg();
755
+ this.convertToOtherFormat();
756
+ }
757
+
758
+ private opacityChange(args: SliderChangeEventArgs): void {
759
+ const value: number = args.value as number;
760
+ const pValue: string = this.rgbToHex(this.rgb);
761
+ this.hsv[3] = value / 100; this.rgb[3] = value / 100;
762
+ const cValue: string = this.rgbToHex(this.rgb);
763
+ this.updateOpacityInput(value);
764
+ const rgb: string = this.convertToRgbString(this.rgb);
765
+ this.updatePreview(rgb);
766
+ this.triggerEvent(cValue, pValue, rgb);
767
+ }
768
+
769
+ private updateOpacityInput(value: number): void {
770
+ if (this.enableOpacity && !this.getWrapper().classList.contains(HIDEVALUE)) {
771
+ const opacityTextBoxInst: NumericTextBox = getInstance(
772
+ select('.' + OPACITY, this.container) as HTMLInputElement, NumericTextBox) as NumericTextBox;
773
+ opacityTextBoxInst.value = value; opacityTextBoxInst.dataBind();
774
+ }
775
+ }
776
+
777
+ private createPreview(parentEle?: Element): void {
778
+ const previewContainer: HTMLElement = this.createElement('div', { className: PREVIEW });
779
+ parentEle.appendChild(previewContainer);
780
+ let preview: HTMLElement = this.createElement('span', { className: 'e-preview ' + CURRENT });
781
+ previewContainer.appendChild(preview);
782
+ const colorValue: string = this.convertToRgbString(this.rgb);
783
+ preview.style.backgroundColor = colorValue;
784
+ preview = this.createElement('span', { className: 'e-preview ' + PREVIOUS });
785
+ previewContainer.appendChild(preview);
786
+ preview.style.backgroundColor = colorValue;
787
+ }
788
+
789
+ private isPicker(): boolean {
790
+ return !this.container.classList.contains(PALETTECONTENT);
791
+ }
792
+
793
+ private getPopupEle(): HTMLElement {
794
+ return this.container.parentElement;
795
+ }
796
+
797
+ private createNumericInput(element: HTMLElement, value: number, label: string, max: number): void {
798
+ const numericInput: NumericTextBox = new NumericTextBox(<NumericTextBoxModel>{
799
+ value: value,
800
+ placeholder: label,
801
+ min: 0,
802
+ max: max,
803
+ format: '###.##',
804
+ showSpinButton: false,
805
+ floatLabelType: 'Always',
806
+ enableRtl: this.enableRtl,
807
+ enabled: !this.disabled,
808
+ readonly: this.isPicker() ? false : true,
809
+ change: (args: ChangeEventArgs) => {
810
+ if (args.event) {
811
+ this.inputHandler(args.event);
812
+ }
813
+ }
814
+ });
815
+ numericInput.createElement = this.createElement;
816
+ numericInput.appendTo(element as HTMLInputElement);
817
+ }
818
+
819
+ private createInput(): void {
820
+ const isPicker: boolean = this.isPicker();
821
+ const wrapper: HTMLElement = this.getWrapper();
822
+ if ((isPicker && !wrapper.classList.contains(HIDEVALUE)) || (!isPicker && wrapper.classList.contains(SHOWVALUE))) {
823
+ const inputWrap: HTMLElement = this.createElement('div', { className: INPUTWRAPPER });
824
+ if (isPicker) {
825
+ this.appendElement(inputWrap, 2);
826
+ } else {
827
+ this.appendElement(inputWrap, 1);
828
+ }
829
+ const container: HTMLElement = this.createElement('div', { className: 'e-input-container' });
830
+ inputWrap.appendChild(container);
831
+ if (!wrapper.classList.contains(HIDEVALUESWITCH)) {
832
+ this.appendValueSwitchBtn(inputWrap);
833
+ }
834
+ if (!wrapper.classList.contains(HIDEHEX)) {
835
+ const hexInput: HTMLInputElement = this.createElement('input', {
836
+ className: HEX,
837
+ attrs: { 'maxlength': '7', 'spellcheck': 'false', 'aria-label': 'HEX' }
838
+ }) as HTMLInputElement;
839
+ container.appendChild(hexInput);
840
+ Input.createInput(
841
+ {
842
+ element: hexInput,
843
+ floatLabelType: 'Always',
844
+ properties: {
845
+ placeholder: 'HEX',
846
+ enableRtl: this.enableRtl,
847
+ enabled: !this.disabled,
848
+ readonly: this.isPicker() ? false : true
849
+ }
850
+ },
851
+ this.createElement);
852
+ Input.setValue(this.value.slice(0, 7), hexInput);
853
+ hexInput.addEventListener('input', this.inputHandler.bind(this));
854
+ }
855
+ if (!wrapper.classList.contains(HIDERGBA)) {
856
+ let label: string;
857
+ let value: number[];
858
+ if (this.isRgb) {
859
+ label = 'RGB';
860
+ value = this.rgb;
861
+ } else {
862
+ label = 'HSV';
863
+ value = this.hsv;
864
+ }
865
+ const clsName: string[] = ['rh', 'gs', 'bv'];
866
+ for (let i: number = 0; i < 3; i++) {
867
+ this.createNumericInput(
868
+ container.appendChild(this.createElement('input', { className: 'e-' + clsName[i as number] + '-value' })),
869
+ value[i as number], label[i as number], 255);
870
+ }
871
+ if (this.enableOpacity) {
872
+ this.appendOpacityValue(container);
873
+ }
874
+ }
875
+ }
876
+ }
877
+
878
+ private appendOpacityValue(container: HTMLElement): void {
879
+ this.createNumericInput(
880
+ container.appendChild(this.createElement('input', { className: OPACITY })), this.rgb[3] * 100, 'A', 100);
881
+ }
882
+
883
+ private appendValueSwitchBtn(targetEle: Element): void {
884
+ const valueSwitchBtn: HTMLElement = this.createElement('button', {
885
+ className: 'e-icons e-css e-btn e-flat e-icon-btn ' + FORMATSWITCH,
886
+ attrs: { 'title': 'Toggle format' }
887
+ });
888
+ targetEle.appendChild(valueSwitchBtn);
889
+ if (this.isPicker() && !this.getWrapper().classList.contains(HIDERGBA)) {
890
+ valueSwitchBtn.addEventListener('click', this.formatSwitchHandler.bind(this));
891
+ }
892
+ }
893
+
894
+ private createCtrlBtn(): void {
895
+ if (this.modeSwitcher || this.showButtons) {
896
+ this.l10n.setLocale(this.locale);
897
+ const btnWrapper: Element = this.createElement('div', { className: CTRLSWITCH });
898
+ this.container.appendChild(btnWrapper);
899
+ if (this.showButtons) {
900
+ const controlBtnWrapper: Element = this.createElement('div', { className: CTRLBTN });
901
+ btnWrapper.appendChild(controlBtnWrapper);
902
+ const apply: string = this.l10n.getConstant('Apply');
903
+ controlBtnWrapper.appendChild(this.createElement('button', {
904
+ innerHTML: apply,
905
+ className: 'e-btn e-css e-flat e-primary e-small ' + APPLY,
906
+ attrs: { 'title': apply }
907
+ }));
908
+ const cancel: string = this.l10n.getConstant('Cancel');
909
+ controlBtnWrapper.appendChild(this.createElement('button', {
910
+ innerHTML: cancel,
911
+ className: 'e-btn e-css e-flat e-small ' + CANCEL,
912
+ attrs: { 'title': cancel }
913
+ }));
914
+ }
915
+ if (this.modeSwitcher) {
916
+ this.appendModeSwitchBtn();
917
+ }
918
+ }
919
+ }
920
+
921
+ private appendModeSwitchBtn(): void {
922
+ const modeSwitcher: HTMLElement = this.createElement('button', {
923
+ className: 'e-icons e-btn e-flat e-icon-btn ' + MODESWITCH, attrs: { title: this.l10n.getConstant('ModeSwitcher') }
924
+ });
925
+ select('.' + CTRLSWITCH, this.container).insertBefore(modeSwitcher, select('.' + CTRLBTN, this.container));
926
+ }
927
+
928
+ private createDragTooltip(): void {
929
+ const tooltip: Tooltip = new Tooltip({
930
+ opensOn: 'Custom',
931
+ showTipPointer: false,
932
+ cssClass: 'e-color-picker-tooltip',
933
+ htmlAttributes: {title: 'tooltip'},
934
+ beforeOpen: (args: TooltipEventArgs) => {
935
+ this.tooltipEle = args.element;
936
+ },
937
+ animation: { open: { effect: 'None' }, close: { effect: 'None' } }
938
+ });
939
+ tooltip.createElement = this.createElement;
940
+ tooltip.appendTo(this.container);
941
+ tooltip.open(this.container);
942
+ this.tooltipEle.style.zIndex = getZindexPartial(this.tooltipEle).toString();
943
+ this.tooltipEle.setAttribute('aria-label', 'colorpicker-tooltip');
944
+ select('.e-tip-content', this.tooltipEle).appendChild(this.createElement('div', { className: 'e-tip-transparent' }));
945
+ }
946
+
947
+ private getTooltipInst(): Tooltip {
948
+ return getInstance(this.container, Tooltip) as Tooltip;
949
+ }
950
+
951
+ private setTooltipOffset(value: number): void {
952
+ this.getTooltipInst().offsetY = value;
953
+ }
954
+
955
+ private toggleDisabled(enable: boolean): void {
956
+ if (enable) {
957
+ this.getWrapper().classList.add(DISABLED);
958
+ } else {
959
+ this.getWrapper().classList.remove(DISABLED);
960
+ }
961
+ if (this.showButtons) {
962
+ ([].slice.call(selectAll('.e-btn', this.container))).forEach((ele: HTMLElement) => {
963
+ if (enable) {
964
+ attributes(ele, { 'disabled': '' });
965
+ } else {
966
+ ele.removeAttribute('disabled');
967
+ }
968
+ });
969
+ }
970
+ }
971
+
972
+ private convertToRgbString(rgb: number[]): string {
973
+ return rgb.length ? rgb.length === 4 ? 'rgba(' + rgb.join() + ')' : 'rgb(' + rgb.join() + ')' : '';
974
+ }
975
+
976
+ private convertToHsvString(hsv: number[]): string {
977
+ return hsv.length === 4 ? 'hsva(' + hsv.join() + ')' : 'hsv(' + hsv.join() + ')';
978
+ }
979
+
980
+ private updateHsv(): void {
981
+ this.hsv[1] = this.hsv[1] > 100 ? 100 : this.hsv[1];
982
+ this.hsv[2] = this.hsv[2] > 100 ? 100 : this.hsv[2];
983
+ this.setHandlerPosition();
984
+ }
985
+
986
+ private convertToOtherFormat(isKey: boolean = false, e?: MouseEvent | Event): void {
987
+ const pValue: string = this.rgbToHex(this.rgb);
988
+ this.rgb = this.hsvToRgb.apply(this, this.hsv);
989
+ const cValue: string = this.rgbToHex(this.rgb);
990
+ const rgba: string = this.convertToRgbString(this.rgb);
991
+ this.updatePreview(rgba);
992
+ this.updateInput(cValue);
993
+ this.triggerEvent(cValue, pValue, rgba, isKey, e);
994
+ }
995
+
996
+ private updateInput(value: string): void {
997
+ const wrapper: HTMLElement = this.getWrapper();
998
+ if (!wrapper.classList.contains(HIDEVALUE)) {
999
+ if (!wrapper.classList.contains(HIDEHEX)) {
1000
+ Input.setValue(value.substr(0, 7), select('.' + HEX, this.container) as HTMLInputElement);
1001
+ }
1002
+ if (!wrapper.classList.contains(HIDERGBA)) {
1003
+ if (this.isRgb) {
1004
+ this.updateValue(this.rgb, false);
1005
+ } else {
1006
+ this.updateValue(this.hsv, false);
1007
+ }
1008
+ }
1009
+ }
1010
+ }
1011
+
1012
+ private updatePreview(value: string): void {
1013
+ if (this.enableOpacity) {
1014
+ this.updateOpacitySliderBg();
1015
+ }
1016
+ (select('.e-tip-transparent', this.tooltipEle) as HTMLElement).style.backgroundColor = value;
1017
+ (select('.' + PREVIEW + ' .' + CURRENT, this.container) as HTMLElement).style.backgroundColor = value;
1018
+ (select('.' + PREVIEW + ' .' + PREVIOUS, this.container) as HTMLElement).style.backgroundColor
1019
+ = this.convertToRgbString(this.hexToRgb(this.value));
1020
+ }
1021
+
1022
+ private getDragHandler(): HTMLElement {
1023
+ return select('.' + HANDLER, this.container) as HTMLElement;
1024
+ }
1025
+
1026
+ private removeTileSelection(): void {
1027
+ const selectedEle: Element[] = [].slice.call(selectAll('.' + SELECT, this.container));
1028
+ selectedEle.forEach((ele: Element): void => {
1029
+ ele.classList.remove(SELECT);
1030
+ ele.setAttribute('aria-selected', 'false');
1031
+ });
1032
+ }
1033
+
1034
+ private convertRgbToNumberArray(value: string): number[] {
1035
+ return (value.slice(value.indexOf('(') + 1, value.indexOf(')'))).split(',').map(
1036
+ (n: string, i: number) => {
1037
+ return (i !== 3) ? parseInt(n, 10) : parseFloat(n);
1038
+ });
1039
+ }
1040
+
1041
+ /**
1042
+ * To get color value in specified type.
1043
+ *
1044
+ * @param {string} value - Specify the color value.
1045
+ * @param {string} type - Specify the type to which the specified color needs to be converted.
1046
+ * @method getValue
1047
+ * @returns {string} - Color value
1048
+ */
1049
+ public getValue(value?: string, type?: string): string {
1050
+ if (!value) { value = this.value; }
1051
+ type = !type ? 'hex' : type.toLowerCase();
1052
+ if (value[0] === 'r') {
1053
+ const cValue: number[] = this.convertRgbToNumberArray(value);
1054
+ if (type === 'hex' || type === 'hexa') {
1055
+ const hex: string = this.rgbToHex(cValue);
1056
+ return type === 'hex' ? hex.slice(0, 7) : hex;
1057
+ } else {
1058
+ if (type === 'hsv') {
1059
+ return this.convertToHsvString(this.rgbToHsv.apply(this, cValue.slice(0, 3)));
1060
+ } else {
1061
+ if (type === 'hsva') {
1062
+ return this.convertToHsvString(this.rgbToHsv.apply(this, cValue));
1063
+ } else {
1064
+ return 'null';
1065
+ }
1066
+ }
1067
+ }
1068
+ } else {
1069
+ if (value[0] === 'h') {
1070
+ const cValue: number[] = this.hsvToRgb.apply(this, this.convertRgbToNumberArray(value));
1071
+ if (type === 'rgba') {
1072
+ return this.convertToRgbString(cValue);
1073
+ } else {
1074
+ if (type === 'hex' || type === 'hexa') {
1075
+ const hex: string = this.rgbToHex(cValue);
1076
+ return type === 'hex' ? hex.slice(0, 7) : hex;
1077
+ } else {
1078
+ if (type === 'rgb') {
1079
+ return this.convertToRgbString(cValue.slice(0, 3));
1080
+ } else {
1081
+ return 'null';
1082
+ }
1083
+ }
1084
+ }
1085
+ } else {
1086
+ value = this.roundValue(value);
1087
+ let rgb: number[] = this.hexToRgb(value);
1088
+ if (type === 'rgb' || type === 'hsv') {
1089
+ rgb = rgb.slice(0, 3);
1090
+ }
1091
+ if (type === 'rgba' || type === 'rgb') {
1092
+ return this.convertToRgbString(rgb);
1093
+ } else {
1094
+ if (type === 'hsva' || type === 'hsv') {
1095
+ return this.convertToHsvString(this.rgbToHsv.apply(this, rgb));
1096
+ } else {
1097
+ if (type === 'hex') {
1098
+ return value.slice(0, 7);
1099
+ } else {
1100
+ if (type === 'a') {
1101
+ return rgb[3].toString();
1102
+ } else {
1103
+ return 'null';
1104
+ }
1105
+ }
1106
+ }
1107
+ }
1108
+ }
1109
+ }
1110
+ }
1111
+
1112
+ /**
1113
+ * To show/hide ColorPicker popup based on current state of the SplitButton.
1114
+ *
1115
+ * @method toggle
1116
+ * @returns {void}
1117
+ */
1118
+ public toggle(): void {
1119
+ if (this.container.parentElement.classList.contains('e-popup-close')) {
1120
+ this.splitBtn.toggle();
1121
+ } else {
1122
+ this.closePopup(null);
1123
+ }
1124
+ }
1125
+
1126
+ /**
1127
+ * Get component name.
1128
+ *
1129
+ * @returns {string} - Module Name
1130
+ * @private
1131
+ */
1132
+ public getModuleName(): string {
1133
+ return 'colorpicker';
1134
+ }
1135
+
1136
+ /**
1137
+ * Gets the properties to be maintained in the persisted state.
1138
+ *
1139
+ * @returns {string} - Persist data
1140
+ */
1141
+ public getPersistData(): string {
1142
+ return this.addOnPersist(['value']);
1143
+ }
1144
+
1145
+ protected wireEvents(): void {
1146
+ if (this.isPicker()) {
1147
+ const dragHandler: HTMLElement = this.getDragHandler();
1148
+ EventHandler.add(dragHandler, 'keydown', this.pickerKeyDown, this);
1149
+ const ctrlBtn: HTMLElement = select('.' + CTRLBTN, this.container) as HTMLElement;
1150
+ if (ctrlBtn) {
1151
+ EventHandler.add(ctrlBtn, 'keydown', this.ctrlBtnKeyDown, this);
1152
+ }
1153
+ EventHandler.add(this.getHsvContainer(), 'mousedown touchstart', this.handlerDown, this);
1154
+ if (this.modeSwitcher || this.showButtons) {
1155
+ this.addCtrlSwitchEvent();
1156
+ }
1157
+ EventHandler.add(select('.' + PREVIOUS, this.container), 'click', this.previewHandler, this);
1158
+ } else {
1159
+ EventHandler.add(this.container, 'click', this.paletteClickHandler, this);
1160
+ EventHandler.add(this.container, 'keydown', this.paletteKeyDown, this);
1161
+ }
1162
+ }
1163
+
1164
+ private formResetHandler(): void {
1165
+ this.value = this.initialInputValue;
1166
+ attributes(this.element, { 'value' : this.initialInputValue });
1167
+ }
1168
+
1169
+ private addCtrlSwitchEvent(): void {
1170
+ const ctrlSwitchBtn: Element = select('.' + CTRLSWITCH, this.container);
1171
+ if (ctrlSwitchBtn) { EventHandler.add(ctrlSwitchBtn, 'click', this.btnClickHandler, this); }
1172
+ }
1173
+
1174
+ private ctrlBtnKeyDown(e: KeyboardEvent): void {
1175
+ if (e.keyCode === 13) {
1176
+ const applyBtn: HTMLElement = select('.' + APPLY, this.container) as HTMLElement;
1177
+ if (applyBtn) {
1178
+ const cValue: string = this.rgbToHex(this.rgb);
1179
+ this.triggerChangeEvent(cValue);
1180
+ }
1181
+ this.splitBtn.element.focus();
1182
+ }
1183
+ }
1184
+
1185
+ private pickerKeyDown(e: KeyboardEvent): void {
1186
+ switch (e.keyCode) {
1187
+ case 39:
1188
+ this.handlerDragPosition(1, this.enableRtl ? -1 : 1, e);
1189
+ break;
1190
+ case 37:
1191
+ this.handlerDragPosition(1, this.enableRtl ? 1 : -1, e);
1192
+ break;
1193
+ case 38:
1194
+ this.handlerDragPosition(2, 1, e);
1195
+ break;
1196
+ case 40:
1197
+ this.handlerDragPosition(2, -1, e);
1198
+ break;
1199
+ case 13: {
1200
+ e.preventDefault();
1201
+ const cValue: string = this.rgbToHex(this.rgb);
1202
+ this.enterKeyHandler(cValue);
1203
+ }
1204
+ }
1205
+ }
1206
+
1207
+ private enterKeyHandler(value: string): void {
1208
+ this.triggerChangeEvent(value);
1209
+ if (!this.inline) {
1210
+ this.splitBtn.element.focus();
1211
+ }
1212
+ }
1213
+
1214
+ private closePopup(e: MouseEvent | KeyboardEvent): void {
1215
+ const beforeCloseArgs: BeforeOpenCloseEventArgs = { element: this.container, event: e, cancel: false };
1216
+ this.trigger('beforeClose', beforeCloseArgs, (observedcloseArgs: BeforeOpenCloseEventArgs) => {
1217
+ if (!observedcloseArgs.cancel) {
1218
+ this.splitBtn.toggle();
1219
+ this.onPopupClose();
1220
+ }
1221
+ });
1222
+ }
1223
+
1224
+ private triggerChangeEvent(value: string, e?: MouseEvent): void {
1225
+ const hex: string = value.slice(0, 7);
1226
+ this.trigger('change', {
1227
+ currentValue: { hex: hex, rgba: this.convertToRgbString(this.rgb) }, event: e,
1228
+ previousValue: { hex: this.value.slice(0, 7), rgba: this.convertToRgbString(this.hexToRgb(this.value)) },
1229
+ value: this.enableOpacity ? value : hex
1230
+ });
1231
+ if (this.showRecentColors) {
1232
+ this.recentColors.unshift(hex);
1233
+ if (this.inline) { this.renderRecentColor(); }
1234
+ }
1235
+ if (this.enableOpacity) {
1236
+ this.setProperties({ 'value': value }, true);
1237
+ } else {
1238
+ this.setProperties({ 'value': hex }, true);
1239
+ }
1240
+ this.element.value = hex ? hex : '#000000';
1241
+ }
1242
+
1243
+ private handlerDragPosition(prob: number, value: number, e: KeyboardEvent): void {
1244
+ e.preventDefault();
1245
+ this.hsv[prob as number] += value * (e.ctrlKey ? 1 : 3);
1246
+ if (this.hsv[prob as number] < 0) { this.hsv[prob as number] = 0; }
1247
+ this.updateHsv();
1248
+ this.convertToOtherFormat(true, e);
1249
+ }
1250
+
1251
+ private handlerDown(e: MouseEvent & TouchEvent): void {
1252
+ e.preventDefault();
1253
+ if (e.type === 'mousedown') {
1254
+ this.clientX = Math.abs(e.pageX - pageXOffset); this.clientY = Math.abs(e.pageY - pageYOffset);
1255
+ this.setTooltipOffset(8);
1256
+ } else {
1257
+ this.clientX = Math.abs(e.changedTouches[0].pageX - pageXOffset);
1258
+ this.clientY = Math.abs(e.changedTouches[0].pageY - pageYOffset);
1259
+ this.setTooltipOffset(-8);
1260
+ }
1261
+ this.setHsv(this.clientX, this.clientY);
1262
+ this.getDragHandler().style.transition = 'left .4s cubic-bezier(.25, .8, .25, 1), top .4s cubic-bezier(.25, .8, .25, 1)';
1263
+ this.updateHsv();
1264
+ this.convertToOtherFormat(false, e);
1265
+ this.getDragHandler().focus();
1266
+ EventHandler.add(document, 'mousemove touchmove', this.handlerMove, this);
1267
+ EventHandler.add(document, 'mouseup touchend', this.handlerEnd, this);
1268
+ }
1269
+
1270
+ private handlerMove(e: MouseEvent & TouchEvent): void {
1271
+ if (e.type !== 'touchmove') {
1272
+ e.preventDefault();
1273
+ }
1274
+ let x: number; let y: number;
1275
+ if (e.type === 'mousemove') {
1276
+ x = Math.abs(e.pageX - pageXOffset); y = Math.abs(e.pageY - pageYOffset);
1277
+ } else {
1278
+ x = Math.abs(e.changedTouches[0].pageX - pageXOffset); y = Math.abs(e.changedTouches[0].pageY - pageYOffset);
1279
+ }
1280
+ this.setHsv(x, y);
1281
+ const dragHandler: HTMLElement = this.getDragHandler();
1282
+ this.updateHsv();
1283
+ this.convertToOtherFormat(false, e);
1284
+ this.getTooltipInst().refresh(dragHandler);
1285
+ if (!this.tooltipEle.style.transform) {
1286
+ if (Math.abs(this.clientX - x) > 8 || Math.abs(this.clientY - y) > 8) {
1287
+ (select('.' + HSVAREA, this.container) as HTMLElement).style.cursor = 'pointer';
1288
+ dragHandler.style.transition = 'none';
1289
+ if (!this.inline) {
1290
+ this.tooltipEle.style.zIndex = (parseInt(this.getPopupEle().style.zIndex, 10) + 1).toString();
1291
+ }
1292
+ this.tooltipEle.style.transform = 'rotate(45deg)';
1293
+ dragHandler.classList.add('e-hide-handler');
1294
+ }
1295
+ }
1296
+ }
1297
+
1298
+ private setHsv(clientX: number, clientY: number): void {
1299
+ const ele: HTMLElement = select('.' + HSVAREA, this.container) as HTMLElement;
1300
+ const position: ClientRect = ele.getBoundingClientRect();
1301
+ if (this.enableRtl) {
1302
+ clientX = clientX > position.right ? 0 : Math.abs(clientX - position.right);
1303
+ } else {
1304
+ clientX = clientX > position.left ? Math.abs(clientX - position.left) : 0;
1305
+ }
1306
+ clientY = clientY > position.top ? Math.abs(clientY - position.top) : 0;
1307
+ this.hsv[2] = Math.round(Number(100 * (ele.offsetHeight -
1308
+ Math.max(0, Math.min(ele.offsetHeight, (clientY - ele.offsetTop)))) / ele.offsetHeight) * 10) / 10;
1309
+ this.hsv[1] =
1310
+ Math.round(Number(100 * (Math.max(0, Math.min(ele.offsetWidth, (clientX - ele.offsetLeft)))) / ele.offsetWidth) * 10) / 10;
1311
+ }
1312
+
1313
+ private handlerEnd(e: MouseEvent & TouchEvent): void {
1314
+ if (e.type !== 'touchend') {
1315
+ e.preventDefault();
1316
+ }
1317
+ EventHandler.remove(document, 'mousemove touchmove', this.handlerMove);
1318
+ EventHandler.remove(document, 'mouseup touchend', this.handlerEnd);
1319
+ const dragHandler: HTMLElement = this.getDragHandler();
1320
+ (select('.' + HSVAREA, this.container) as HTMLElement).style.cursor = '';
1321
+ if (this.tooltipEle.style.transform) {
1322
+ this.tooltipEle.style.transform = '';
1323
+ dragHandler.classList.remove('e-hide-handler');
1324
+ }
1325
+ if (!this.inline && !this.showButtons) {
1326
+ this.closePopup(e);
1327
+ }
1328
+ }
1329
+
1330
+ private btnClickHandler(e: MouseEvent): void {
1331
+ const target: HTMLElement = (e.target as HTMLElement);
1332
+ if (closest(target, '.' + MODESWITCH)) {
1333
+ e.stopPropagation();
1334
+ this.switchToPalette();
1335
+ } else {
1336
+ if (target.classList.contains(APPLY) || target.classList.contains(CANCEL)) {
1337
+ this.ctrlBtnClick(target, e);
1338
+ }
1339
+ }
1340
+ }
1341
+
1342
+ private switchToPalette(): void {
1343
+ this.trigger('beforeModeSwitch', <ModeSwitchEventArgs>{ element: this.container, mode: 'Palette' });
1344
+ this.unWireEvents();
1345
+ this.destroyOtherComp();
1346
+ detach(select('.e-slider-preview', this.container));
1347
+ if (!this.getWrapper().classList.contains(HIDEVALUE)) {
1348
+ remove(select('.' + INPUTWRAPPER, this.container));
1349
+ }
1350
+ detach(this.getHsvContainer());
1351
+ this.createPalette();
1352
+ this.firstPaletteFocus();
1353
+ this.createInput();
1354
+ this.refreshPopupPos();
1355
+ //for image editor popup position refreshing
1356
+ if (this.element.parentElement && this.element.parentElement.parentElement && this.element.parentElement.parentElement.classList.contains('e-ie-ddb-popup')) {
1357
+ this.refreshImageEditorPopupPos();
1358
+ }
1359
+ this.wireEvents();
1360
+ this.trigger('onModeSwitch', <ModeSwitchEventArgs>{ element: this.container, mode: 'Palette'});
1361
+ }
1362
+
1363
+ //for image editor popup position refreshing
1364
+ private refreshImageEditorPopupPos(): void {
1365
+ if (Browser.isDevice) {
1366
+ const popupEle: HTMLElement = this.getPopupEle();
1367
+ popupEle.style.left = formatUnit(0 + pageXOffset);
1368
+ popupEle.style.top = formatUnit(0 + pageYOffset);
1369
+ const btnElem: HTMLElement = document.querySelector(`#${this.element.parentElement.parentElement.id.split('-popup')[0]}`);
1370
+ if (btnElem) {
1371
+ //eslint-disable-next-line @typescript-eslint/no-explicit-any
1372
+ (popupEle.parentElement as any).ej2_instances[0].refreshPosition(btnElem);
1373
+ }
1374
+ }
1375
+ }
1376
+
1377
+ private refreshPopupPos(): void {
1378
+ if (!this.inline) {
1379
+ const popupEle: HTMLElement = this.getPopupEle();
1380
+ popupEle.style.left = formatUnit(0 + pageXOffset);
1381
+ popupEle.style.top = formatUnit(0 + pageYOffset);
1382
+ this.getPopupInst().refreshPosition(this.splitBtn.element.parentElement);
1383
+ }
1384
+ }
1385
+
1386
+ private formatSwitchHandler(): void {
1387
+ if (this.isRgb) {
1388
+ this.updateValue(this.hsv, true, 3, [360, 100, 100]);
1389
+ this.isRgb = false;
1390
+ } else {
1391
+ this.updateValue(this.rgb, true, 2);
1392
+ this.isRgb = true;
1393
+ }
1394
+ }
1395
+
1396
+ private updateValue(value: number[], format: boolean, idx?: number, max?: number[]): void {
1397
+ const clsName: string[] = ['e-rh-value', 'e-gs-value', 'e-bv-value'];
1398
+ let inst: NumericTextBox;
1399
+ for (let i: number = 0, len: number = clsName.length; i < len; i++) {
1400
+ inst = getInstance(select('.' + clsName[i as number], this.container) as HTMLInputElement, NumericTextBox) as NumericTextBox;
1401
+ inst.value = Math.round(value[i as number]);
1402
+ if (format) {
1403
+ inst.placeholder = clsName[i as number].substr(idx, 1).toUpperCase();
1404
+ inst.max = max ? max[i as number] : 255;
1405
+ }
1406
+ inst.dataBind();
1407
+ }
1408
+ }
1409
+
1410
+ private previewHandler(e: MouseEvent): void {
1411
+ const target: HTMLElement = e.target as HTMLElement;
1412
+ const pValue: string = this.rgbToHex(this.rgb);
1413
+ this.rgb = this.convertRgbToNumberArray(target.style.backgroundColor);
1414
+ if (!this.rgb[3]) {
1415
+ this.rgb[3] = 1;
1416
+ }
1417
+ const cValue: string = this.rgbToHex(this.rgb);
1418
+
1419
+ const hsv: number[] = this.rgbToHsv.apply(this, this.rgb);
1420
+ if (hsv[0] !== this.hsv[0]) {
1421
+ this.hueSlider.setProperties({ 'value': hsv[0] }, true);
1422
+ this.hueSlider.refresh();
1423
+ }
1424
+ this.setHsvContainerBg(hsv[0]);
1425
+ if (this.enableOpacity && hsv[3] !== this.hsv[3]) {
1426
+ this.opacitySlider.setProperties({ 'value': hsv[3] * 100 }, true);
1427
+ this.opacitySlider.refresh();
1428
+ this.updateOpacitySliderBg();
1429
+ }
1430
+ this.hsv = hsv;
1431
+ this.setHandlerPosition();
1432
+ this.updateInput(cValue);
1433
+ (select('.' + PREVIEW + ' .' + CURRENT, this.container) as HTMLElement).style.backgroundColor = this.convertToRgbString(this.rgb);
1434
+ this.triggerEvent(cValue, pValue, this.convertToRgbString(this.rgb), false, e);
1435
+ }
1436
+
1437
+ private paletteClickHandler(e: MouseEvent): void {
1438
+ e.preventDefault();
1439
+ const target: HTMLElement = e.target as HTMLElement;
1440
+ if (target.classList.contains(TILE)) {
1441
+ this.removeTileSelection();
1442
+ this.addTileSelection(target);
1443
+ if (target.classList.contains(NOCOLOR)) {
1444
+ this.noColorTile();
1445
+ } else {
1446
+ const cValue: string = target.getAttribute('aria-label');
1447
+ const pValue: string = this.rgbToHex(this.rgb);
1448
+ this.rgb = this.hexToRgb(this.roundValue(cValue));
1449
+ this.hsv = this.rgbToHsv.apply(this, this.rgb);
1450
+ if (this.getWrapper().classList.contains(SHOWVALUE)) {
1451
+ this.updateInput(cValue);
1452
+ }
1453
+ this.triggerEvent(cValue, pValue, this.convertToRgbString(this.rgb), false, e);
1454
+ }
1455
+ if (!this.inline && !this.showButtons) {
1456
+ this.closePopup(e);
1457
+ }
1458
+ } else {
1459
+ if (closest(target, '.' + MODESWITCH)) {
1460
+ this.switchToPicker();
1461
+ } else {
1462
+ if (target.classList.contains(APPLY) || target.classList.contains(CANCEL)) {
1463
+ this.ctrlBtnClick(target, e);
1464
+ } else {
1465
+ if (this.getWrapper().classList.contains(SHOWVALUE) && closest(target, '.' + FORMATSWITCH)) {
1466
+ this.formatSwitchHandler();
1467
+ }
1468
+ }
1469
+ }
1470
+ }
1471
+ }
1472
+
1473
+ private noColorTile(isKey: boolean = false): void {
1474
+ const pValue: string = this.rgbToHex(this.rgb);
1475
+ this.rgb = [];
1476
+ this.hsv = [];
1477
+ this.triggerEvent('', pValue, '', isKey);
1478
+ }
1479
+
1480
+ private switchToPicker(): void {
1481
+ const wrapper: Element = this.getWrapper();
1482
+ this.trigger('beforeModeSwitch', <ModeSwitchEventArgs>{ element: this.container, mode: 'Picker' });
1483
+ this.unWireEvents();
1484
+ ([].slice.call(selectAll('.' + PALETTES, this.container))).forEach((ele: HTMLElement) => {
1485
+ detach(ele);
1486
+ });
1487
+ if (this.container.querySelector('.e-clr-pal-rec-wpr')) {
1488
+ detach(this.container.querySelector('.e-clr-pal-rec-wpr'));
1489
+ }
1490
+ if (wrapper.classList.contains(SHOWVALUE)) {
1491
+ detach(select('.' + INPUTWRAPPER, this.container));
1492
+ }
1493
+ this.container.style.width = '';
1494
+ const grpEle: Element = select('.e-custom-palette', this.container);
1495
+ if (this.presetColors) {
1496
+ remove(grpEle);
1497
+ }
1498
+ this.createPicker();
1499
+ this.getDragHandler().focus();
1500
+ this.createInput();
1501
+ this.refreshPopupPos();
1502
+ //for image editor popup position refreshing
1503
+ if (this.element.parentElement && this.element.parentElement.parentElement && this.element.parentElement.parentElement.classList.contains('e-ie-ddb-popup')) {
1504
+ this.refreshImageEditorPopupPos();
1505
+ }
1506
+ this.wireEvents();
1507
+ this.trigger('onModeSwitch', <ModeSwitchEventArgs>{ element: this.container, mode: 'Picker'});
1508
+ }
1509
+
1510
+ private ctrlBtnClick(ele: HTMLElement, e: MouseEvent): void {
1511
+ if (ele.classList.contains(APPLY)) {
1512
+ const cValue: string = this.rgbToHex(this.rgb);
1513
+ this.triggerChangeEvent(cValue, e);
1514
+ }
1515
+ if (!this.inline) {
1516
+ this.closePopup(e);
1517
+ this.splitBtn.element.focus();
1518
+ } else if (ele.classList.contains(CANCEL)) {
1519
+ const beforeCloseArgs: BeforeOpenCloseEventArgs = { element: this.container, event: e, cancel: false };
1520
+ this.trigger('beforeClose', beforeCloseArgs);
1521
+ }
1522
+ }
1523
+
1524
+ private paletteKeyDown(e: KeyboardEvent): void {
1525
+ const target: HTMLElement = e.target as HTMLElement;
1526
+ if (!target.classList.contains(PALETTES)) {
1527
+ return;
1528
+ }
1529
+ let selectedEle: Element;
1530
+ let idx: number;
1531
+ const tiles: Element[] = [].slice.call(selectAll('.' + TILE, target));
1532
+ const prevSelectedEle: Element = (tiles.filter((tile: Element) => tile.classList.contains('e-selected'))).pop();
1533
+ switch (!e.altKey && e.keyCode) {
1534
+ case 39:
1535
+ e.preventDefault();
1536
+ selectedEle = prevSelectedEle ? tiles[this.tilePosition(tiles, prevSelectedEle, this.enableRtl ? -1 : 1)]
1537
+ : tiles[this.enableRtl ? tiles.length - 1 : 0];
1538
+ this.keySelectionChanges(selectedEle);
1539
+ break;
1540
+ case 37:
1541
+ e.preventDefault();
1542
+ selectedEle = prevSelectedEle ? tiles[this.tilePosition(tiles, prevSelectedEle, this.enableRtl ? 1 : -1)]
1543
+ : tiles[this.enableRtl ? 0 : tiles.length - 1];
1544
+ this.keySelectionChanges(selectedEle);
1545
+ break;
1546
+ case 38:
1547
+ e.preventDefault();
1548
+ idx = prevSelectedEle ? this.tilePosition(tiles, prevSelectedEle, -this.columns) : 0;
1549
+ selectedEle = tiles[idx as number] ? tiles[idx as number] : tiles[idx - this.columns];
1550
+ this.keySelectionChanges(selectedEle);
1551
+ break;
1552
+ case 40:
1553
+ e.preventDefault();
1554
+ idx = prevSelectedEle ? this.tilePosition(tiles, prevSelectedEle, this.columns) : tiles.length - 1;
1555
+ if (tiles[idx as number]) {
1556
+ selectedEle = tiles[idx as number];
1557
+ } else {
1558
+ idx %= tiles.length;
1559
+ idx += tiles[tiles.length - 1].parentElement.childElementCount;
1560
+ selectedEle = tiles[idx as number];
1561
+ }
1562
+ this.keySelectionChanges(selectedEle);
1563
+ break;
1564
+ case 13:
1565
+ e.preventDefault();
1566
+ if (prevSelectedEle) {
1567
+ const cValue: string = prevSelectedEle.getAttribute('aria-label');
1568
+ this.enterKeyHandler(cValue ? cValue : '');
1569
+ }
1570
+ break;
1571
+ }
1572
+ }
1573
+
1574
+ private keySelectionChanges(newEle: Element): void {
1575
+ this.removeTileSelection();
1576
+ this.addTileSelection(newEle);
1577
+ if (newEle.classList.contains(NOCOLOR)) {
1578
+ this.noColorTile(true);
1579
+ } else {
1580
+ const cValue: string = newEle.getAttribute('aria-label');
1581
+ const pValue: string = this.rgbToHex(this.rgb);
1582
+ this.rgb = this.hexToRgb(cValue);
1583
+ this.hsv = this.rgbToHsv.apply(this, this.rgb);
1584
+ if (this.getWrapper().classList.contains(SHOWVALUE)) {
1585
+ this.updateInput(cValue);
1586
+ }
1587
+ this.triggerEvent(cValue, pValue, this.convertToRgbString(this.rgb), true);
1588
+ }
1589
+ }
1590
+
1591
+ private tilePosition(items: Element[], element: Element, cIdx: number): number {
1592
+ items = Array.prototype.slice.call(items);
1593
+ const n: number = items.length;
1594
+ const emptyCount: number = this.columns - items[n - 1].parentElement.childElementCount;
1595
+ let idx: number = items.indexOf(element);
1596
+ idx += cIdx;
1597
+ if (idx < 0) {
1598
+ idx += n + emptyCount;
1599
+ } else {
1600
+ idx %= n + emptyCount;
1601
+ }
1602
+ return idx;
1603
+ }
1604
+
1605
+ private inputHandler(e: MouseEvent | Event): void {
1606
+ const target: HTMLInputElement = e.target as HTMLInputElement;
1607
+ if (!target.value.length) {
1608
+ return;
1609
+ }
1610
+ let hsv: number[]; let pValue: string;
1611
+ const label: string = select('.e-float-text', target.parentElement).textContent;
1612
+ switch (label) {
1613
+ case 'HEX': {
1614
+ let value: string = '';
1615
+ if ((target.value[0] === '#' && target.value.length !== 5) || (target.value[0] !== '#' && target.value.length !== 4)) {
1616
+ value = this.roundValue(target.value);
1617
+ }
1618
+ if (value.length === 9) {
1619
+ pValue = this.rgbToHex(this.rgb);
1620
+ this.rgb = this.hexToRgb(value + value.substr(-2));
1621
+ this.inputValueChange(this.rgbToHsv.apply(this, this.rgb), pValue, target.value, e);
1622
+ } else {
1623
+ return;
1624
+ }
1625
+ break;
1626
+ }
1627
+ case 'R':
1628
+ if (this.rgb[0] !== Number(target.value)) {
1629
+ pValue = this.rgbToHex(this.rgb);
1630
+ this.rgb[0] = Number(target.value);
1631
+ hsv = this.rgbToHsv.apply(this, this.rgb);
1632
+ this.inputValueChange(hsv, pValue, null, e);
1633
+ }
1634
+ break;
1635
+ case 'G':
1636
+ if (this.rgb[1] !== Number(target.value)) {
1637
+ pValue = this.rgbToHex(this.rgb);
1638
+ this.rgb[1] = Number(target.value);
1639
+ hsv = this.rgbToHsv.apply(this, this.rgb);
1640
+ this.inputValueChange(hsv, pValue, null, e);
1641
+ }
1642
+ break;
1643
+ case 'B':
1644
+ if (this.rgb[2] !== Number(target.value)) {
1645
+ pValue = this.rgbToHex(this.rgb);
1646
+ this.rgb[2] = Number(target.value);
1647
+ hsv = this.rgbToHsv.apply(this, this.rgb);
1648
+ this.inputValueChange(hsv, pValue, null, e);
1649
+ }
1650
+ break;
1651
+ case 'H':
1652
+ this.hueSlider.value = Number(target.value);
1653
+ break;
1654
+ case 'S':
1655
+ if (this.hsv[1] !== Number(target.value)) {
1656
+ this.hsv[1] = Number(target.value);
1657
+ this.updateHsv();
1658
+ this.convertToOtherFormat(false, e);
1659
+ }
1660
+ break;
1661
+ case 'V':
1662
+ if (this.hsv[2] !== Number(target.value)) {
1663
+ this.hsv[2] = Number(target.value);
1664
+ this.updateHsv();
1665
+ this.convertToOtherFormat(false, e);
1666
+ }
1667
+ break;
1668
+ case 'A':
1669
+ this.opacitySlider.value = Number(target.value);
1670
+ break;
1671
+ }
1672
+
1673
+ }
1674
+
1675
+ private inputValueChange(hsv: number[], pValue: string, value?: string, e?: MouseEvent | Event): void {
1676
+ if (hsv[0] !== this.hsv[0]) {
1677
+ this.hueSlider.setProperties({ 'value': hsv[0] }, true);
1678
+ this.hueSlider.refresh();
1679
+ this.setHsvContainerBg(hsv[0]);
1680
+ }
1681
+ this.hsv = hsv;
1682
+ const cValue: string = this.rgbToHex(this.rgb);
1683
+ this.setHandlerPosition();
1684
+ this.updateInput(value ? value : cValue);
1685
+ const rgba: string = this.convertToRgbString(this.rgb);
1686
+ this.updatePreview(rgba);
1687
+ this.triggerEvent(cValue, pValue, rgba, false, e);
1688
+ }
1689
+
1690
+ private triggerEvent(cValue: string, pValue: string, rgba: string, isKey: boolean = false, e?: MouseEvent | Event): void {
1691
+ const hex: string = cValue.slice(0, 7);
1692
+ if (isNullOrUndefined(e)) {
1693
+ e = new MouseEvent('click', { bubbles: true, cancelable: false });
1694
+ }
1695
+ if (!this.showButtons && !isKey) {
1696
+ this.trigger('change', { currentValue: { hex: hex, rgba: rgba }, event: e,
1697
+ previousValue: { hex: this.value.slice(0, 7), rgba: this.convertToRgbString(this.hexToRgb(this.value)) }, value: cValue });
1698
+ if (this.showRecentColors) {
1699
+ this.recentColors.unshift(hex);
1700
+ if (this.inline) { this.renderRecentColor(); }
1701
+ }
1702
+ if (this.enableOpacity) {
1703
+ this.setProperties({ 'value': cValue }, true);
1704
+ } else {
1705
+ this.setProperties({ 'value': hex }, true);
1706
+ }
1707
+ this.element.value = hex ? hex : '#000000';
1708
+ } else {
1709
+ this.trigger('select', {
1710
+ currentValue: { hex: hex, rgba: rgba }, event: e,
1711
+ previousValue: { hex: pValue.slice(0, 7), rgba: this.convertToRgbString(this.hexToRgb(pValue)) }
1712
+ });
1713
+ }
1714
+ }
1715
+
1716
+ /**
1717
+ * Removes the component from the DOM and detaches all its related event handlers.
1718
+ * Also it maintains the initial input element from the DOM.
1719
+ *
1720
+ * @method destroy
1721
+ * @returns {void}
1722
+ */
1723
+ public destroy(): void {
1724
+ const wrapper: Element = this.getWrapper();
1725
+ super.destroy();
1726
+ ['tabindex', 'spellcheck'].forEach((attr: string): void => { this.element.removeAttribute(attr); });
1727
+ if (this.inline) {
1728
+ this.unWireEvents();
1729
+ this.destroyOtherComp();
1730
+ } else {
1731
+ if (this.isPopupOpen()) {
1732
+ this.unWireEvents();
1733
+ this.destroyOtherComp();
1734
+ }
1735
+ this.splitBtn.destroy();
1736
+ this.splitBtn = null;
1737
+ }
1738
+ this.tileRipple();
1739
+ this.tileRipple = null;
1740
+ this.ctrlBtnRipple();
1741
+ this.ctrlBtnRipple = null;
1742
+ if (this.element.nextElementSibling) {
1743
+ detach(this.element.nextElementSibling);
1744
+ }
1745
+ if (wrapper) {
1746
+ wrapper.parentElement.insertBefore(this.element, wrapper);
1747
+ detach(wrapper);
1748
+ }
1749
+ this.container = null;
1750
+ if (this.formElement) {
1751
+ EventHandler.remove(this.formElement, 'reset', this.formResetHandler);
1752
+ }
1753
+ }
1754
+
1755
+ private destroyOtherComp(): void {
1756
+ if (this.isPicker()) {
1757
+ const popup: HTMLElement = closest(this.hueSlider.element, '.e-color-picker') as HTMLElement;
1758
+ const numericElemColl: NodeListOf<HTMLElement> = popup.querySelectorAll('.e-numerictextbox');
1759
+ for (let i: number = 0; i < numericElemColl.length; i++) {
1760
+ (getInstance(numericElemColl[i as number], NumericTextBox) as NumericTextBox).destroy();
1761
+ }
1762
+ this.hueSlider.destroy();
1763
+ if (this.enableOpacity) { this.opacitySlider.destroy(); this.opacitySlider = null; }
1764
+ this.hueSlider = null;
1765
+ const tooltipInst: Tooltip = this.getTooltipInst();
1766
+ tooltipInst.close();
1767
+ tooltipInst.destroy();
1768
+ this.tooltipEle = null;
1769
+ }
1770
+ }
1771
+
1772
+ private isPopupOpen(): boolean {
1773
+ return this.getPopupEle().classList.contains('e-popup-open');
1774
+ }
1775
+
1776
+ protected unWireEvents(): void {
1777
+ if (this.isPicker()) {
1778
+ const dragHandler: HTMLElement = this.getDragHandler();
1779
+ EventHandler.remove(dragHandler, 'keydown', this.pickerKeyDown);
1780
+ const ctrlBtn: HTMLElement = select('.' + CTRLBTN, this.container) as HTMLElement;
1781
+ if (ctrlBtn) {
1782
+ EventHandler.remove(ctrlBtn, 'keydown', this.ctrlBtnKeyDown);
1783
+ }
1784
+ EventHandler.remove(this.getHsvContainer(), 'mousedown touchstart', this.handlerDown);
1785
+ if (this.modeSwitcher || this.showButtons) {
1786
+ EventHandler.remove(select('.' + CTRLSWITCH, this.container), 'click', this.btnClickHandler);
1787
+ }
1788
+ EventHandler.remove(select('.' + PREVIOUS, this.container), 'click', this.previewHandler);
1789
+ } else {
1790
+ EventHandler.remove(this.container, 'click', this.paletteClickHandler);
1791
+ EventHandler.remove(this.container, 'keydown', this.paletteKeyDown);
1792
+ }
1793
+ }
1794
+
1795
+ private roundValue(value: string): string {
1796
+ if (!value) { return ''; }
1797
+ if (value[0] !== '#') {
1798
+ value = '#' + value;
1799
+ }
1800
+ let len: number = value.length;
1801
+ if (len === 4) {
1802
+ value += 'f';
1803
+ len = 5;
1804
+ }
1805
+ if (len === 5) {
1806
+ let tempValue: string = '';
1807
+ for (let i: number = 1, len: number = value.length; i < len; i++) {
1808
+ tempValue += (value.charAt(i) + value.charAt(i));
1809
+ }
1810
+ value = '#' + tempValue;
1811
+ len = 9;
1812
+ }
1813
+ if (len === 7) {
1814
+ value += 'ff';
1815
+ }
1816
+ return value;
1817
+ }
1818
+
1819
+ private hexToRgb(hex: string): number[] {
1820
+ if (!hex) { return []; }
1821
+ hex = hex.trim();
1822
+ if (hex.length !== 9) {
1823
+ hex = this.roundValue(hex);
1824
+ }
1825
+ const opacity: number = Number((parseInt(hex.slice(-2), 16) / 255).toFixed(2));
1826
+ hex = hex.slice(1, 7);
1827
+ const bigInt: number = parseInt(hex, 16); const h: number[] = [];
1828
+ h.push((bigInt >> 16) & 255);
1829
+ h.push((bigInt >> 8) & 255);
1830
+ h.push(bigInt & 255);
1831
+ h.push(opacity);
1832
+ return h;
1833
+ }
1834
+
1835
+ private rgbToHsv(r: number, g: number, b: number, opacity?: number): number[] {
1836
+ if (this.rgb && !this.rgb.length) { return []; }
1837
+ r /= 255; g /= 255; b /= 255;
1838
+ const max: number = Math.max(r, g, b); const min: number = Math.min(r, g, b);
1839
+ let h: number; const v: number = max;
1840
+
1841
+ const d: number = max - min;
1842
+ const s: number = max === 0 ? 0 : d / max;
1843
+
1844
+ if (max === min) {
1845
+ h = 0;
1846
+ } else {
1847
+ switch (max) {
1848
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
1849
+ case g: h = (b - r) / d + 2; break;
1850
+ case b: h = (r - g) / d + 4; break;
1851
+ }
1852
+ h /= 6;
1853
+ }
1854
+ const hsv: number[] = [Math.round(h * 360), Math.round(s * 1000) / 10, Math.round(v * 1000) / 10];
1855
+ if (!isNullOrUndefined(opacity)) {
1856
+ hsv.push(opacity);
1857
+ }
1858
+ return hsv;
1859
+ }
1860
+
1861
+ private hsvToRgb(h: number, s: number, v: number, opacity?: number): number[] {
1862
+ let r: number; let g: number; let b: number;
1863
+ s /= 100; v /= 100;
1864
+ if (s === 0) {
1865
+ r = g = b = v;
1866
+ return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), opacity];
1867
+ }
1868
+ h /= 60;
1869
+ const i: number = Math.floor(h);
1870
+ const f: number = h - i;
1871
+ const p: number = v * (1 - s);
1872
+ const q: number = v * (1 - s * f);
1873
+ const t: number = v * (1 - s * (1 - f));
1874
+ switch (i) {
1875
+ case 0: r = v; g = t; b = p; break;
1876
+ case 1: r = q; g = v; b = p; break;
1877
+ case 2: r = p; g = v; b = t; break;
1878
+ case 3: r = p; g = q; b = v; break;
1879
+ case 4: r = t; g = p; b = v; break;
1880
+ default: r = v; g = p; b = q;
1881
+ }
1882
+ const rgb: number[] = [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
1883
+ if (!isNullOrUndefined(opacity)) {
1884
+ rgb.push(opacity);
1885
+ }
1886
+ return rgb;
1887
+ }
1888
+
1889
+ private rgbToHex(rgb: number[]): string {
1890
+ return rgb.length ? ('#' + this.hex(rgb[0]) + this.hex(rgb[1]) + this.hex(rgb[2]) +
1891
+ (!isNullOrUndefined(rgb[3]) ? (rgb[3] !== 0 ? (Math.round(rgb[3] * 255) + 0x10000).toString(16).substr(-2) : '00') : '')) : '';
1892
+ }
1893
+
1894
+ private hex(x: number): string {
1895
+ return ('0' + x.toString(16)).slice(-2);
1896
+ }
1897
+
1898
+ private changeModeSwitcherProp(prop: boolean): void {
1899
+ const ctrlSwitchWrapper: Element = select('.' + CTRLSWITCH, this.container);
1900
+ if (prop) {
1901
+ if (ctrlSwitchWrapper) {
1902
+ this.appendModeSwitchBtn();
1903
+ } else {
1904
+ this.createCtrlBtn();
1905
+ if (this.isPicker() && !this.disabled) {
1906
+ this.addCtrlSwitchEvent();
1907
+ }
1908
+ }
1909
+ } else {
1910
+ if (ctrlSwitchWrapper) {
1911
+ if (this.showButtons) {
1912
+ detach(select('.' + MODESWITCH, ctrlSwitchWrapper));
1913
+ } else {
1914
+ remove(ctrlSwitchWrapper);
1915
+ }
1916
+ }
1917
+ }
1918
+ }
1919
+
1920
+ private changeShowBtnProps(prop: boolean): void {
1921
+ const ctrlBtnWrapper: Element = select('.' + CTRLSWITCH, this.container);
1922
+ if (prop) {
1923
+ if (ctrlBtnWrapper) {
1924
+ remove(ctrlBtnWrapper);
1925
+ }
1926
+ this.createCtrlBtn();
1927
+ if (this.isPicker() && !this.disabled) {
1928
+ this.addCtrlSwitchEvent();
1929
+ }
1930
+ } else {
1931
+ if (this.modeSwitcher) {
1932
+ detach(select('.' + CTRLBTN, ctrlBtnWrapper));
1933
+ } else {
1934
+ remove(ctrlBtnWrapper);
1935
+ }
1936
+ }
1937
+ }
1938
+
1939
+ private changeValueProp(newProp: string): void {
1940
+ if (this.isPicker()) {
1941
+ this.rgb = this.hexToRgb(newProp);
1942
+ this.hsv = this.rgbToHsv.apply(this, this.rgb);
1943
+ this.setHandlerPosition();
1944
+ detach(closest(this.hueSlider.element, '.e-slider-preview'));
1945
+ this.createSlider();
1946
+ this.setHsvContainerBg();
1947
+ this.updateInput(newProp);
1948
+ if (this.rgb.length === 4) { this.updateOpacityInput(this.rgb[3] * 100); }
1949
+ } else {
1950
+ this.removeTileSelection();
1951
+ const ele: Element = this.container.querySelector('span[aria-label="' + this.roundValue(newProp) + '"]');
1952
+ if (ele) { this.addTileSelection(ele); }
1953
+ }
1954
+ }
1955
+
1956
+ private setInputEleProps(): void {
1957
+ remove(select('.' + INPUTWRAPPER, this.container));
1958
+ this.createInput();
1959
+ }
1960
+
1961
+ private changeDisabledProp(newProp: boolean): void {
1962
+ if (this.isPicker()) {
1963
+ this.hueSlider.enabled = !newProp;
1964
+ this.opacitySlider.enabled = !newProp;
1965
+ this.setInputEleProps();
1966
+ }
1967
+ if (newProp) {
1968
+ this.toggleDisabled(true);
1969
+ this.unWireEvents();
1970
+ } else {
1971
+ this.toggleDisabled(false);
1972
+ this.wireEvents();
1973
+ }
1974
+ }
1975
+
1976
+ private changeCssClassProps(newProp: string, oldProp: string): void {
1977
+ const wrapper: Element = this.getWrapper();
1978
+ const popupWrapper: HTMLElement = this.getPopupEle();
1979
+ if (oldProp) {
1980
+ removeClass([wrapper, popupWrapper], oldProp.split(' '));
1981
+ if (this.splitBtn && this.splitBtn.activeElem && this.splitBtn.activeElem[0] && this.splitBtn.activeElem[1]) {
1982
+ removeClass([this.splitBtn.activeElem[0], this.splitBtn.activeElem[1]], oldProp.split(' '));
1983
+ }
1984
+ if (this.splitBtn && this.splitBtn.element && this.splitBtn.element.parentElement) {
1985
+ removeClass([this.splitBtn.element.parentElement], oldProp.split(' '));
1986
+ }
1987
+
1988
+ }
1989
+ if (newProp) {
1990
+ addClass([wrapper, popupWrapper], newProp.replace(/\s+/g, ' ').trim().split(' '));
1991
+ if (this.splitBtn && this.splitBtn.activeElem && this.splitBtn.activeElem[0] && this.splitBtn.activeElem[1]) {
1992
+ addClass([this.splitBtn.activeElem[0], this.splitBtn.activeElem[1]], newProp.replace(/\s+/g, ' ').trim().split(' '));
1993
+ }
1994
+ if (this.splitBtn && this.splitBtn.element && this.splitBtn.element.parentElement) {
1995
+ addClass([this.splitBtn.element.parentElement], newProp.replace(/\s+/g, ' ').trim().split(' '));
1996
+ }
1997
+ }
1998
+ }
1999
+
2000
+ private changeRtlProps(newProp: boolean): void {
2001
+ if (newProp) {
2002
+ addClass([this.getWrapper()], 'e-rtl');
2003
+ } else {
2004
+ removeClass([this.getWrapper()], 'e-rtl');
2005
+ }
2006
+ }
2007
+
2008
+ private changePaletteProps(): void {
2009
+ detach(this.container.children[0]);
2010
+ this.container.style.width = '';
2011
+ this.createPalette();
2012
+ }
2013
+
2014
+ private changeOpacityProps(newProp: boolean): void {
2015
+ const wrapper: HTMLElement = this.getWrapper();
2016
+ if (newProp) {
2017
+ removeClass([this.container.parentElement], HIDEOPACITY);
2018
+ this.createOpacitySlider(
2019
+ select('.e-colorpicker-slider', this.container).appendChild(this.createElement('div', { className: 'e-opacity-slider' })));
2020
+ if (!wrapper.classList.contains(HIDEVALUE) && !wrapper.classList.contains(HIDERGBA)) {
2021
+ this.appendOpacityValue(select('.e-input-container', this.container) as HTMLElement);
2022
+ }
2023
+ } else {
2024
+ addClass([this.container.parentElement], HIDEOPACITY);
2025
+ this.opacitySlider.destroy();
2026
+ remove(this.opacitySlider.element);
2027
+ this.opacitySlider = null;
2028
+ if (!wrapper.classList.contains(HIDEVALUE) && !wrapper.classList.contains(HIDERGBA)) {
2029
+ remove(select('.' + OPACITY, this.container).parentElement);
2030
+ }
2031
+ }
2032
+ }
2033
+
2034
+ /**
2035
+ * Called internally if any of the property value changed.
2036
+ *
2037
+ * @param {ColorPickerModel} newProp - Specifies new properties
2038
+ * @param {ColorPickerModel} oldProp - Specifies old properties
2039
+ * @returns {void}
2040
+ * @private
2041
+ */
2042
+ public onPropertyChanged(newProp: ColorPickerModel, oldProp: ColorPickerModel): void {
2043
+ if (!isNullOrUndefined(newProp.value)) {
2044
+ const value: string = this.roundValue(newProp.value);
2045
+ if (value.length === 9) {
2046
+ this.element.value = this.roundValue(value).slice(0, 7);
2047
+ const preview: HTMLElement = this.splitBtn && select('.' + SPLITPREVIEW, this.splitBtn.element) as HTMLElement;
2048
+ if (preview) {
2049
+ preview.style.backgroundColor = this.convertToRgbString(this.hexToRgb(newProp.value));
2050
+ }
2051
+ } else if (this.noColor && this.mode === 'Palette' && this.value === '') {
2052
+ const preview: HTMLElement = this.splitBtn && select('.' + SPLITPREVIEW, this.splitBtn.element) as HTMLElement;
2053
+ preview.style.backgroundColor = '';
2054
+ } else {
2055
+ this.value = oldProp.value;
2056
+ }
2057
+ }
2058
+ if (!this.inline && isNullOrUndefined(newProp.inline)) {
2059
+ const otherCompModel: string[] = ['disabled', 'enableRtl'];
2060
+ this.splitBtn.setProperties(getModel(newProp, otherCompModel));
2061
+ if (!this.isPopupOpen()) {
2062
+ this.changeCssClassProps(newProp.cssClass, oldProp.cssClass);
2063
+ this.changeRtlProps(newProp.enableRtl);
2064
+ return;
2065
+ }
2066
+ }
2067
+ for (const prop of Object.keys(newProp)) {
2068
+ switch (prop) {
2069
+ case 'inline':
2070
+ if (newProp.inline) {
2071
+ this.getWrapper().appendChild(this.container);
2072
+ this.splitBtn.destroy();
2073
+ detach(this.element.nextElementSibling);
2074
+ if (!this.container.children.length) {
2075
+ this.createWidget();
2076
+ }
2077
+ } else {
2078
+ this.destroyOtherComp();
2079
+ this.unWireEvents();
2080
+ this.container.innerHTML = '';
2081
+ this.createSplitBtn();
2082
+ }
2083
+ break;
2084
+ case 'cssClass': {
2085
+ this.changeCssClassProps(newProp.cssClass, oldProp.cssClass);
2086
+ let props: string[] = newProp.cssClass.split(' ').concat(oldProp.cssClass.split(' '));
2087
+ props = props.reduce((a: string[], b: string): string[] => { if (a.indexOf(b) < 0) { a.push(b); } return a; }, []);
2088
+ let count: number = 0;
2089
+ props.forEach((cls: string) => {
2090
+ if (count === 0 &&
2091
+ (cls === HIDEVALUE || cls === HIDEVALUESWITCH || cls === SHOWVALUE || cls === HIDEHEX || cls === HIDERGBA)) {
2092
+ const inputWrap: Element = select('.' + INPUTWRAPPER, this.container);
2093
+ if (inputWrap) { remove(select('.' + INPUTWRAPPER, this.container)); }
2094
+ this.createInput();
2095
+ count++;
2096
+ }
2097
+ });
2098
+ break;
2099
+ }
2100
+ case 'enableRtl':
2101
+ if (this.isPicker()) {
2102
+ this.hueSlider.enableRtl = newProp.enableRtl;
2103
+ if (this.enableOpacity) { this.opacitySlider.enableRtl = newProp.enableRtl; }
2104
+ this.setInputEleProps();
2105
+ }
2106
+ this.changeRtlProps(newProp.enableRtl);
2107
+ break;
2108
+ case 'disabled':
2109
+ this.changeDisabledProp(newProp.disabled);
2110
+ break;
2111
+ case 'value':
2112
+ if (this.value !== oldProp.value) { this.changeValueProp(newProp.value); }
2113
+ break;
2114
+ case 'showButtons':
2115
+ this.changeShowBtnProps(newProp.showButtons);
2116
+ break;
2117
+ case 'mode':
2118
+ if (newProp.mode === 'Picker') {
2119
+ this.switchToPicker();
2120
+ } else {
2121
+ this.switchToPalette();
2122
+ }
2123
+ break;
2124
+ case 'modeSwitcher':
2125
+ this.changeModeSwitcherProp(newProp.modeSwitcher);
2126
+ break;
2127
+ case 'columns':
2128
+ case 'presetColors':
2129
+ if (!this.isPicker()) {
2130
+ this.changePaletteProps();
2131
+ }
2132
+ break;
2133
+ case 'noColor':
2134
+ if (newProp.noColor) {
2135
+ if (this.mode === 'Palette' && !this.modeSwitcher) {
2136
+ this.setNoColor();
2137
+ }
2138
+ } else {
2139
+ this.changePaletteProps();
2140
+ }
2141
+ break;
2142
+ case 'enableOpacity':
2143
+ this.changeOpacityProps(newProp.enableOpacity);
2144
+ break;
2145
+ case 'showRecentColors':
2146
+ if (!newProp.showRecentColors) {
2147
+ const recentClrWpr: HTMLElement = this.container.querySelector('.e-clr-pal-rec-wpr');
2148
+ if (recentClrWpr) { detach(recentClrWpr); }
2149
+ }
2150
+ this.recentColors = [];
2151
+ break;
2152
+ }
2153
+ }
2154
+ }
2155
+
2156
+ /**
2157
+ * Sets the focus to Colorpicker
2158
+ * its native method
2159
+ *
2160
+ * @public
2161
+ * @returns {void}
2162
+ */
2163
+ public focusIn(): void {
2164
+ this.element.parentElement.focus();
2165
+ }
2166
+ }
2167
+
2168
+ /**
2169
+ * Interface for change / select event.
2170
+ */
2171
+ export interface ColorPickerEventArgs extends BaseEventArgs {
2172
+ currentValue: { hex: string, rgba: string };
2173
+ previousValue: { hex: string, rgba: string };
2174
+ value?: string;
2175
+ event?: Event;
2176
+ }
2177
+
2178
+ /**
2179
+ * Interface for before change event.
2180
+ */
2181
+ export interface PaletteTileEventArgs extends BaseEventArgs {
2182
+ element: HTMLElement;
2183
+ presetName: string;
2184
+ value: string;
2185
+ }
2186
+
2187
+ /**
2188
+ * Interface for before open / close event.
2189
+ */
2190
+ export interface BeforeOpenCloseEventArgs extends BaseEventArgs {
2191
+ element: HTMLElement;
2192
+ event: Event;
2193
+ cancel: boolean;
2194
+ }
2195
+
2196
+ /**
2197
+ * Interface for open event.
2198
+ */
2199
+ export interface OpenEventArgs extends BaseEventArgs {
2200
+ element: HTMLElement;
2201
+ }
2202
+
2203
+ /**
2204
+ * Interface for mode switching event.
2205
+ */
2206
+ export interface ModeSwitchEventArgs extends BaseEventArgs {
2207
+ element: HTMLElement;
2208
+ mode: string;
2209
+ }