PageSourceSearch

https://jsc0179.or.kr/js/coloris.1791261837.js

js jsc0179.or.kr collected 2026-10-08 14:07:43 UTC 59,033 bytes, 1,672 lines download raw bytes

1 /*!
2 * Copyright (c) 2021 Momo Bassit.
3 * Licensed under the MIT License (MIT)
4 * https://github.com/mdbassit/Coloris
5 */
6 if(typeof LANG == 'undefined') var LANG = (typeof getLanguage != 'undefined') ? getLanguage() : 'en';
7 const _coloris_label = {
8    ko: {
9      save: '저장',
10      cancel: '취소',
11      alpha: '불투명도',
12      alpha_info: `완전 투명상태입니다.<br>컬러를 보려면 아래의 불투명도를<br>높여주세요.`,
13      hex: '컬러',
14      guide: `RGB 방식 색상 코드 표기법입니다.`,
15    },
16    en: {
17      save: 'SAVE',
18      cancel: 'CANCEL',
19      alpha: 'Opacity',
20      alpha_info: `It is completely transparent.<br>Please adjust the transparency to see the color.`,
21      hex: 'Color',
22      guide: `The color is expressed as an RGB color code.`,
23    }
24  };
25
26
27 (function (window, document, Math, undefined) {
28
29    var checkReturnFuncArr = ['getColorSelectorPnInfo','getColorInfo','getChangeColorVal','getColorRegex'];
30    var checkUsedFuncArr = [];
31
32    var ctx = document.createElement('canvas').getContext('2d');
33    var currentColor = { r: 0, g: 0, b: 0, h: 0, s: 0, v: 0, a: 1 };
34    var container,picker,colorArea,colorMarker,colorPreview,colorValue,clearButton,closeButton,
35    hueSlider,hueMarker,alphaSlider,alphaMarker,currentEl,currentFormat,oldColor,keyboardNav,
36    colorCursor,hexInput,alphaInput,cancelButton,btnBox,picker_backdrop,
37    colorAreaDims = {};
38
39    // Default settings
40    var settings = {
41      el: '.coloris', //'[data-coloris]',
42      parent: 'body',
43      theme: 'default',
44      themeMode: 'light',
45      rtl: false,
46      wrap: true,
47      margin: 2,
48      format: 'hex',
49      formatToggle: false,
50      swatches: [],
51      swatchesOnly: false,
52      alpha: true,
53      forceAlpha: false,
54      focusInput: false,
55      selectInput: false,
56      inline: false,
57      defaultColor: '#000000',
58      clearButton: false,
59      clearLabel: 'Clear',
60      closeButton: true, //false,
61      closeLabel: _coloris_label[(LANG === 'ko') ? 'ko' : 'en'].save,  //'Close',
62      cancelButton: true,
63      cancelLabel: _coloris_label[(LANG === 'ko') ? 'ko' : 'en'].cancel,
64      onChange: function onChange() {return undefined;},
65      a11y: {
66        open: 'Open color picker',
67        cancel: 'Cancel the selected color',
68        close: 'Save color picker', //'Close color picker',
69        clear: 'Clear the selected color',
70        marker: 'Saturation: {s}. Brightness: {v}.',
71        hueSlider: 'Hue slider',
72        alphaSlider: 'Opacity slider',
73        alphaInput: 'Opacity value field',
74        alphaLabel: _coloris_label[(LANG === 'ko') ? 'ko' : 'en'].alpha,
75        hexInput: 'Color Hex value field',
76        hexLabel: _coloris_label[(LANG === 'ko') ? 'ko' : 'en'].hex,
77        input: 'Color value field',
78        inputLabel: 'Color',
79        format: 'Color format',
80        swatch: 'Color swatch',
81        instruction: 'Saturation and brightness selector. Use up, down, left and right arrow keys to select.' 
82      }
83      };
84  
85  
86    // Virtual instances cache
87    var instances = {};
88    var currentInstanceId = '';
89    var defaultInstance = {};
90    var hasInstance = false;
91  
92    /**
93     * Configure the color picker.
94     * @param {object} options Configuration options.
95     */
96    function configure(options) {
97      if (typeof options !== 'object') {
98        return;
99      }
100  
101      for (var key in options) {
102        switch (key) {
103          case 'el':
104            bindFields(options.el);
105            if (options.wrap !== false) {
106              wrapFields(options.el);
107            }
108            break;
109          case 'parent':
110            container = document.querySelector(options.parent);
111            if (container) {
112              container.appendChild(picker);
113              container.appendChild(picker_backdrop);
114              settings.parent = options.parent;
115  
116              // document.body is special
117              if (container === document.body) {
118                container = undefined;
119              }
120            }
121            break;
122          case 'themeMode':
123            settings.themeMode = options.themeMode;
124            if (options.themeMode === 'auto' && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
125              settings.themeMode = 'dark';
126            }
127          // The lack of a break statement is intentional
128          case 'theme':
129            if (options.theme) {
130              settings.theme = options.theme;
131            }
132  
133            // Set the theme and color scheme
134            picker.className = "clr-picker clr-" + settings.theme + " clr-" + settings.themeMode;
135  
136            // Update the color picker's position if inline mode is in use
137            if (settings.inline) {
138              updatePickerPosition();
139            }
140            break;
141          case 'rtl':
142            settings.rtl = !!options.rtl;
143            document.querySelectorAll('.clr-field').forEach(function (field) {return field.classList.toggle('clr-rtl', settings.rtl);});
144            break;
145          case 'margin':
146            options.margin *= 1;
147            settings.margin = !isNaN(options.margin) ? options.margin : settings.margin;
148            break;
149          case 'wrap':
150            if (options.el && options.wrap) {
151              wrapFields(options.el);
152            }
153            break;
154          case 'formatToggle':
155            settings.formatToggle = !!options.formatToggle;
156            getEl('clr-format').style.display = settings.formatToggle ? 'block' : 'none';
157            if (settings.formatToggle) {
158              settings.format = 'auto';
159            }
160            break;
161          case 'swatches':
162            if (Array.isArray(options.swatches)) {(function () {
163                var swatches = [];
164  
165                options.swatches.forEach(function (swatch, i) {
166                  swatches.push("<button type=\"button\" id=\"clr-swatch-" + i + "\" aria-labelledby=\"clr-swatch-label clr-swatch-" + i + "\" style=\"color: " + swatch + ";\">" + swatch + "</button>");
167                });
168  
169                getEl('clr-swatches').innerHTML = swatches.length ? "<div>" + swatches.join('') + "</div>" : '';
170                settings.swatches = options.swatches.slice();})();
171            }
172            break;
173          case 'swatchesOnly':
174            settings.swatchesOnly = !!options.swatchesOnly;
175            picker.setAttribute('data-minimal', settings.swatchesOnly);
176            break;
177          case 'alpha':
178            settings.alpha = !!options.alpha;
179            picker.setAttribute('data-alpha', settings.alpha);
180            break;
181          case 'inline':
182            settings.inline = !!options.inline;
183            picker.setAttribute('data-inline', settings.inline);
184  
185            if (settings.inline) {
186              var defaultColor = options.defaultColor || settings.defaultColor;
187  
188              currentFormat = getColorFormatFromStr(defaultColor);
189              updatePickerPosition();
190              setColorFromStr(defaultColor);
191            }
192            break;
193          case 'clearButton':
194            // Backward compatibility
195            if (typeof options.clearButton === 'object') {
196              if (options.clearButton.label) {
197                settings.clearLabel = options.clearButton.label;
198                clearButton.innerHTML = settings.clearLabel;
199              }
200  
201              options.clearButton = options.clearButton.show;
202            }
203            settings.clearButton = !!options.clearButton;
204            clearButton.style.display = settings.clearButton ? 'block' : 'none';
205            break;
206          case 'clearLabel':
207            settings.clearLabel = options.clearLabel;
208            clearButton.innerHTML = settings.clearLabel;
209            break;
210
211          case 'closeButton':
212            settings.closeButton = !!options.closeButton;
213
214            if (settings.closeButton) {
215              // picker.insertBefore(closeButton, colorPreview);
216              btnBox.append(closeButton);
217            } else {
218              // colorPreview.appendChild(closeButton);
219              paletteBox.appendChild(closeButton);
220            }
221            break;
222          case 'closeLabel':
223            settings.closeLabel = options.closeLabel;
224            closeButton.innerHTML = settings.closeLabel;
225            break;
226
227          case 'cancelButton':
228            settings.cancelButton = !!options.cancelButton;
229  
230            if (settings.cancelButton) {
231              // picker.insertBefore(cancelButton, colorPreview);
232              btnBox.append(cancelButton);
233            } else {
234              // colorPreview.appendChild(cancelButton);
235              paletteBox.appendChild(cancelButton);
236            }
237            break;
238          case 'cancelLabel':
239            settings.cancelLabel = options.cancelLabel;
240            cancelButton.innerHTML = settings.cancelLabel;
241            break;
242
243          case 'a11y':
244            var labels = options.a11y;
245            var update = false;
246  
247            if (typeof labels === 'object') {
248              for (var label in labels) {
249                if (labels[label] && settings.a11y[label]) {
250                  settings.a11y[label] = labels[label];
251                  update = true;
252                }
253              }
254            }
255  
256            if (update) {
257              var openLabel = getEl('clr-open-label');
258              var swatchLabel = getEl('clr-swatch-label');
259  
260              openLabel.innerHTML = settings.a11y.open;
261              swatchLabel.innerHTML = settings.a11y.swatch;
262              closeButton.setAttribute('aria-label', settings.a11y.close);
263              clearButton.setAttribute('aria-label', settings.a11y.clear);
264              CancelButton.setAttribute('aria-label', settings.a11y.cancel);
265              hueSlider.setAttribute('aria-label', settings.a11y.hueSlider);
266              alphaInput.setAttribute('aria-label', settings.a11y.alphaInput);
267              alphaSlider.setAttribute('aria-label', settings.a11y.alphaSlider);
268              colorValue.setAttribute('aria-label', settings.a11y.input);
269              colorArea.setAttribute('aria-label', settings.a11y.instruction);
270            }
271            break;
272          default:
273            settings[key] = options[key];}
274  
275      }
276    }
277  
278    /**
279     * Add or update a virtual instance.
280     * @param {String} selector The CSS selector of the elements to which the instance is attached.
281     * @param {Object} options Per-instance options to apply.
282     */
283    function setVirtualInstance(selector, options) {
284      if (typeof selector === 'string' && typeof options === 'object') {
285        instances[selector] = options;
286        hasInstance = true;
287      }
288    }
289
290    function returnInstance() {
291      return instances;
292    }
293  
294    /**
295     * Remove a virtual instance.
296     * @param {String} selector The CSS selector of the elements to which the instance is attached.
297     */
298    function removeVirtualInstance(selector) {
299      delete instances[selector];
300  
301      if (Object.keys(instances).length === 0) {
302        hasInstance = false;
303  
304        if (selector === currentInstanceId) {
305          resetVirtualInstance();
306        }
307      }
308    }
309  
310    /**
311     * Attach a virtual instance to an element if it matches a selector.
312     * @param {Object} element Target element that will receive a virtual instance if applicable.
313     */
314    function attachVirtualInstance(element) {
315      if (hasInstance) {
316        // These options can only be set globally, not per instance
317        var unsupportedOptions = ['el', 'wrap', 'rtl', 'inline', 'defaultColor', 'a11y'];var _loop = function _loop(
318  
319        selector) {
320          var options = instances[selector];
321  
322          // If the element matches an instance's CSS selector
323          if (element.matches(selector)) {
324            currentInstanceId = selector;
325            defaultInstance = {};
326  
327            // Delete unsupported options
328            unsupportedOptions.forEach(function (option) {return delete options[option];});
329  
330            // Back up the default options so we can restore them later
331            for (var option in options) {
332              defaultInstance[option] = Array.isArray(settings[option]) ? settings[option].slice() : settings[option];
333            }
334  
335            // Set the instance's options
336            configure(options);
337            return "break";
338          }};for (var selector in instances) {var _ret = _loop(selector);if (_ret === "break") break;
339        }
340      }
341    }
342  
343    /**
344     * Revert any per-instance options that were previously applied.
345     */
346    function resetVirtualInstance() {
347      if (Object.keys(defaultInstance).length > 0) {
348        configure(defaultInstance);
349        currentInstanceId = '';
350        defaultInstance = {};
351      }
352    }
353  
354
355    function getCurrentLanguage(_s) {
356      if(typeof LANG == 'undefined') return;
357      
358      var curlang = (LANG === 'ko') ? 'ko' : 'en';
359
360      _s.cancelLabel = _coloris_label[curlang].cancel;
361      _s.closeLabel = _coloris_label[curlang].save;
362      _s.a11y.alphaLabel = _coloris_label[curlang].alpha;
363      _s.a11y.hexLabel = _coloris_label[curlang].hex;
364
365      $('#clr-picker .clr-color-info.hex .info-label').text(_s.a11y.hexLabel);
366      $('#clr-picker .clr-color-info.alpha .info-label').text(_s.a11y.alphaLabel);
367      $('#clr-picker #clr-cancel').text(_s.cancelLabel);
368      $('#clr-picker #clr-close').text(_s.closeLabel);
369
370      return _s;
371    }
372
373    /**
374     * Bind the color picker to input fields that match the selector.
375     * @param {string} selector One or more selectors pointing to input fields.
376     */
377    function bindFields(selector) {
378      // Show the color picker on click on the input fields that match the selector
379      $(document).off('click input', selector);
380
381      addListener(document, 'click', selector, function (event) {
382        settings = getCurrentLanguage(settings);
383
384        // Skip if inline mode is in use
385        if (settings.inline) {
386          return;
387        }
388  
389        // Apply any per-instance options first
390        attachVirtualInstance(event.target);
391  
392        currentEl = event.target;
393        oldColor = currentEl.value;
394        currentFormat = getColorFormatFromStr(oldColor);
395
396        settings.alpha = (currentEl.classList.contains('clr-alphaoff')) ? false : true;
397        picker.setAttribute('data-alpha', settings.alpha);
398        picker.classList.add('clr-open');
399        paletteBox.classList.add('ready');
400
401        updatePickerPosition();
402        setColorFromStr(oldColor);
403  
404        $('#clr-color-comment').addClass('hide');
405        $('.back-black').addClass('hide');
406        if(alphaInput.value == 0) {
407          $('#clr-color-comment').removeClass('hide');
408          $('.back-black').removeClass('hide');
409        }
410        
411        if (settings.focusInput || settings.selectInput) {
412          if(settings.focusInput) colorValue.focus({ preventScroll: true });
413          if(settings.selectInput) colorValue.setSelectionRange(currentEl.selectionStart, currentEl.selectionEnd);
414        }
415  
416        if (settings.selectInput) {
417          colorValue.select();
418        }
419  
420        // Always focus the first element when using keyboard navigation
421        if (keyboardNav || settings.swatchesOnly) {
422          getFocusableElements().shift().focus();
423        }
424  
425        // Trigger an "open" event
426        currentEl.dispatchEvent(new Event('open', { bubbles: true }));
427      });
428  
429      // Update the color preview of the input fields that match the selector
430      addListener(document, 'input', selector, function (event) {
431        var parent = event.target.parentNode;
432  
433        // Only update the preview if the field has been previously wrapped
434        if (parent.classList.contains('clr-field')) {
435          parent.style.color = event.target.value;
436        }
437      });
438    }
439  
440    /**
441     * Update the color picker's position and the color gradient's offset
442     */
443    function updatePickerPosition() {
444      var parent = container;
445      var scrollY = window.scrollY;
446      var pickerWidth = picker.offsetWidth;
447      var pickerHeight = picker.offsetHeight;
448      var reposition = { left: false, top: false };
449      var parentStyle, parentMarginTop, parentBorderTop;
450      var offset = { x: 0, y: 0 };
451  
452      if (parent) {
453        parentStyle = window.getComputedStyle(parent);
454        parentMarginTop = parseFloat(parentStyle.marginTop);
455        parentBorderTop = parseFloat(parentStyle.borderTopWidth);
456  
457        offset = parent.getBoundingClientRect();
458        offset.y += parentBorderTop + scrollY;
459      }
460  
461      if (!settings.inline) {
462        var coords = currentEl.getBoundingClientRect();
463        var left = coords.x;
464        var top = scrollY + coords.y + coords.height + settings.margin;
465  
466        // If the color picker is inside a custom container
467        // set the position relative to it
468        if (parent) {
469          left -= offset.x;
470          top -= offset.y;
471  
472          if (left + pickerWidth > parent.clientWidth) {
473            left += coords.width - pickerWidth;
474            reposition.left = true;
475          }
476  
477          if (top + pickerHeight > parent.clientHeight - parentMarginTop) {
478            if (pickerHeight + settings.margin <= coords.top - (offset.y - scrollY)) {
479              top -= coords.height + pickerHeight + settings.margin * 2;
480              reposition.top = true;
481            }
482          }
483  
484          top += parent.scrollTop;
485  
486          // Otherwise set the position relative to the whole document
487        } else {
488          if (left + pickerWidth > document.documentElement.clientWidth) {
489            left += coords.width - pickerWidth;
490            reposition.left = true;
491          }
492  
493          if (top + pickerHeight - scrollY > document.documentElement.clientHeight) {
494            if (pickerHeight + settings.margin <= coords.top) {
495              top = scrollY + coords.y - pickerHeight - settings.margin;
496              reposition.top = true;
497            }
498          }
499        }
500
501        if(top < 0) {
502          top = 0;
503          left -= 23;
504        }
505        if(top > document.documentElement.clientHeight - pickerHeight 
506          && (!$('body').hasClass('off-config') && !$('html').hasClass('_scroll'))
507        ) {
508          top = document.documentElement.clientHeight - pickerHeight;
509          left -= 23;
510        }
511  
512        picker.classList.toggle('clr-left', reposition.left);
513        picker.classList.toggle('clr-top', reposition.top);
514        picker.style.left = left + "px";
515        picker.style.top = top + "px";
516        offset.x += picker.offsetLeft;
517        offset.y += picker.offsetTop;
518      }
519
520      colorAreaDims = {
521        width: colorArea.offsetWidth,
522        height: colorArea.offsetHeight,
523        x: colorArea.offsetLeft + offset.x,
524        y: colorArea.offsetTop + offset.y };
525  
526    }
527  
528    /**
529     * Wrap the linked input fields in a div that adds a color preview.
530     * @param {string} selector One or more selectors pointing to input fields.
531     */
532    function excludeColorFieldAutofill(field) {
533      if (!field.matches('input[type="text"], input:not([type]), input[type="number"]')) return;
534      field.setAttribute('autocomplete', 'off');
535      field.setAttribute('autocorrect', 'off');
536      field.setAttribute('autocapitalize', 'off');
537      field.setAttribute('spellcheck', 'false');
538      field.setAttribute('data-1p-ignore', 'true');
539      field.setAttribute('data-bwignore', 'true');
540    }
541
542    function wrapFields(selector) {
543      document.querySelectorAll(selector).forEach(function (field) {
544        excludeColorFieldAutofill(field);
545        var parentNode = field.parentNode;
546  
547        if (!parentNode.classList.contains('clr-field')) {
548          var wrapper = document.createElement('div');
549          var classes = 'clr-field';
550  
551          if (settings.rtl || field.classList.contains('clr-rtl')) {
552            classes += ' clr-rtl';
553          }
554  
555          wrapper.innerHTML = "<button type=\"button\" aria-labelledby=\"clr-open-label\"></button>";
556          parentNode.insertBefore(wrapper, field);
557          wrapper.setAttribute('class', classes);
558          wrapper.style.color = field.value;
559          wrapper.appendChild(field);
560        }
561      });
562    }
563  
564    /**
565     * Close the color picker.
566     * @param {boolean} [revert] If true, revert the color to the original value.
567     */
568    function closePicker(revert) {
569      if (currentEl && !settings.inline) {
570        var prevEl = currentEl;
571  
572        // Revert the color to the original value if needed
573        if (revert) {
574          // This will prevent the "change" event on the colorValue input to execute its handler
575          currentEl = undefined;
576  
577          if (oldColor !== prevEl.value) {
578            prevEl.value = oldColor;
579  
580            // Trigger an "input" event to force update the thumbnail next to the input field
581            prevEl.dispatchEvent(new Event('input', { bubbles: true }));
582          }
583        }
584  
585        // Trigger a "change" event if needed
586        setTimeout(function () {// Add this to the end of the event loop
587          if (oldColor !== prevEl.value) {
588            prevEl.dispatchEvent(new Event('change', { bubbles: true }));
589          }
590        });
591  
592        // Hide the picker dialog
593        picker.classList.remove('clr-open');
594  
595        // Reset any previously set per-instance options
596        if (hasInstance) {
597          resetVirtualInstance();
598        }
599  
600        // Trigger a "close" event
601        prevEl.dispatchEvent(new Event('close', { bubbles: true }));
602  
603        if (settings.focusInput) {
604          prevEl.focus({ preventScroll: false });
605        }
606  
607        // This essentially marks the picker as closed
608        currentEl = undefined;
609      }
610    }
611  
612    /**
613     * Set the active color from a string.
614     * @param {string} str String representing a color.
615     */
616    function setColorFromStr(str) {
617      var rgba = strToRGBA(str);
618      var hsva = RGBAtoHSVA(rgba);
619  
620      updateMarkerA11yLabel(hsva.s, hsva.v);
621      updateColor(rgba, hsva);
622  
623      // Update the UI
624      hueSlider.value = hsva.h;
625      picker.style.color = "hsl(" + hsva.h + ", 100%, 50%)";
626      hueMarker.style.left = hsva.h / 360 * 100 + "%";
627  
628      colorMarker.style.left = colorAreaDims.width * hsva.s / 100 + "px";
629      colorMarker.style.top = colorAreaDims.height - colorAreaDims.height * hsva.v / 100 + "px";
630  
631      alphaSlider.value = hsva.a * 100;
632      alphaMarker.style.left = hsva.a * 100 + "%";
633      alphaInput.value = alphaSlider.value;
634    }
635  
636    /**
637     * Guess the color format from a string.
638     * @param {string} str String representing a color.
639     * @return {string} The color format.
640     */
641    function getColorFormatFromStr(str) {
642      var format = str.substring(0, 3).toLowerCase();
643  
644      if (format === 'rgb' || format === 'hsl') {
645        return format;
646      }
647  
648      return 'hex';
649    }
650  
651    /**
652     * Copy the active color to the linked input field.
653     * @param {number} [color] Color value to override the active color.
654     */
655    function pickColor(color) {
656      color = color !== undefined ? color : colorValue.value;
657
658      if (currentEl) {
659        currentEl.value = color;
660        currentEl.dispatchEvent(new Event('input', { bubbles: true }));
661      }
662  
663      if (settings.onChange) {
664        settings.onChange.call(window, color, currentEl);
665      }
666  
667      document.dispatchEvent(new CustomEvent('coloris:pick', { detail: { color: color, currentEl: currentEl } }));
668    }
669  
670    /**
671     * Set the active color based on a specific point in the color gradient.
672     * @param {number} x Left position.
673     * @param {number} y Top position.
674     */
675    function setColorAtPosition(x, y) {
676      var hsva = {
677        h: hueSlider.value * 1,
678        s: x / colorAreaDims.width * 100,
679        v: 100 - y / colorAreaDims.height * 100,
680        a: alphaSlider.value / 100 };
681  
682      var rgba = HSVAtoRGBA(hsva);
683  
684      updateMarkerA11yLabel(hsva.s, hsva.v);
685      updateColor(rgba, hsva);
686      // pickColor();
687    }
688  
689    /**
690     * Update the color marker's accessibility label.
691     * @param {number} saturation
692     * @param {number} value
693     */
694    function updateMarkerA11yLabel(saturation, value) {
695      var label = settings.a11y.marker;
696  
697      saturation = saturation.toFixed(1) * 1;
698      value = value.toFixed(1) * 1;
699      label = label.replace('{s}', saturation);
700      label = label.replace('{v}', value);
701      colorMarker.setAttribute('aria-label', label);
702    }
703  
704    //
705    /**
706     * Get the pageX and pageY positions of the pointer.
707     * @param {object} event The MouseEvent or TouchEvent object.
708     * @return {object} The pageX and pageY positions.
709     */
710    function getPointerPosition(event) {
711      return {
712        pageX: event.changedTouches ? event.changedTouches[0].pageX : event.pageX,
713        pageY: event.changedTouches ? event.changedTouches[0].pageY : event.pageY };
714  
715    }
716  
717    /**
718     * Move the color marker when dragged.
719     * @param {object} event The MouseEvent object.
720     */
721    function moveMarker(event) {
722      var pointer = getPointerPosition(event);
723      var x = pointer.pageX - colorAreaDims.x;
724      var y = pointer.pageY - colorAreaDims.y;
725  
726      if (container) {
727        y += container.scrollTop;
728      }
729
730      setMarkerPosition(x, y);
731  
732      // Prevent scrolling while dragging the marker
733      event.preventDefault();
734      event.stopPropagation();
735    }
736  
737    /**
738     * Move the color marker when the arrow keys are pressed.
739     * @param {number} offsetX The horizontal amount to move.
740     * @param {number} offsetY The vertical amount to move.
741     */
742    function moveMarkerOnKeydown(offsetX, offsetY) {
743      var x = colorMarker.style.left.replace('px', '') * 1 + offsetX;
744      var y = colorMarker.style.top.replace('px', '') * 1 + offsetY;
745  
746      setMarkerPosition(x, y);
747    }
748  
749    /**
750     * Set the color marker's position.
751     * @param {number} x Left position.
752     * @param {number} y Top position.
753     */
754    function setMarkerPosition(x, y) {
755      
756      // .clr-picker padding val
757      x -= 22;
758      y -= 20;
759
760      // Make sure the marker doesn't go out of bounds
761      x = x < 0 ? 0 : x > colorAreaDims.width ? colorAreaDims.width : x;
762      y = y < 0 ? 0 : y > colorAreaDims.height ? colorAreaDims.height : y;
763
764      // Set the position
765      colorMarker.style.left = x + 'px';
766      colorMarker.style.top = y + 'px';
767
768      colorCursor.style.lfet = x + 'px';
769      colorCursor.style.top = y + 'px';
770  
771      // Update the color
772      setColorAtPosition(x, y);
773  
774      // Make sure the marker is focused
775      colorMarker.focus();
776    }
777  
778    /**
779     * Update the color picker's input field and preview thumb.
780     * @param {Object} rgba Red, green, blue and alpha values.
781     * @param {Object} [hsva] Hue, saturation, value and alpha values.
782     */
783    function updateColor(rgba, hsva) {if (rgba === void 0) {rgba = {};}if (hsva === void 0) {hsva = {};}
784      var format = settings.format;
785  
786      for (var key in rgba) {
787        currentColor[key] = rgba[key];
788      }
789  
790      for (var _key in hsva) {
791        currentColor[_key] = hsva[_key];
792      }
793  
794      var hex = RGBAToHex(currentColor);
795      var opaqueHex = hex.substring(0, 7);
796      var hex_zero = (hex.substring(7) != '') ? hex.substring(7) : 'ff';
797  
798      colorMarker.style.color = opaqueHex;
799      alphaMarker.parentNode.style.color = opaqueHex;
800      alphaMarker.style.color = hex;
801      colorPreview.style.color = hex;
802      if(paletteBox.classList.contains('ready')) {
803        colorCurrent.style.color = hex;
804        paletteBox.classList.remove('ready');
805      }
806  
807      // Force repaint the color and alpha gradients as a workaround for a Google Chrome bug
808      colorArea.style.display = 'none';
809      colorArea.offsetHeight;
810      colorArea.style.display = '';
811      alphaMarker.nextElementSibling.style.display = 'none';
812      alphaMarker.nextElementSibling.offsetHeight;
813      alphaMarker.nextElementSibling.style.display = '';
814  
815      if (format === 'mixed') {
816        format = currentColor.a === 1 ? 'hex' : 'rgb';
817      } else if (format === 'auto') {
818        format = currentFormat;
819      }
820  
821      alphaInput.value = alphaSlider.value;
822      hexInput.value = hex.slice(0,7);
823
824      switch (format) {
825        case 'hex':
826          colorValue.value = hex;
827          break;
828        case 'rgb':
829          colorValue.value = RGBAToStr(currentColor);
830          break;
831        case 'hsl':
832          colorValue.value = HSLAToStr(HSVAtoHSLA(currentColor));
833          break;
834      }
835    
836      // Select the current format in the format switcher
837      document.querySelector(".clr-format [value=\"" + format + "\"]").checked = true;
838    }
839  
840    /**
841     * Set the hue when its slider is moved.
842     */
843    function setHue() {
844      var hue = hueSlider.value * 1;
845      var x = colorMarker.style.left.replace('px', '') * 1;
846      var y = colorMarker.style.top.replace('px', '') * 1;
847  
848      picker.style.color = "hsl(" + hue + ", 100%, 50%)";
849      hueMarker.style.left = hue / 360 * 100 + "%";
850  
851      setColorAtPosition(x, y);
852    }
853  
854    /**
855     * Set the alpha when its slider is moved.
856     */
857    function setAlpha() {
858      var alpha = alphaSlider.value / 100;
859      
860      if(alphaSlider.value > 0) {
861        $('#clr-color-comment').addClass('hide');
862        $('.back-black').addClass('hide');
863      } else {
864        $('#clr-color-comment').removeClass('hide');
865        $('.back-black').removeClass('hide');
866      }
867
868      alphaMarker.style.left = alpha * 100 + "%";
869      updateColor({ a: alpha });
870      // pickColor();
871    }
872    function setAlphaInput() {
873      if(alphaInput.value < 1 || !alphaInput.value) alphaInput.value = 0;
874      else if(alphaInput.value > 100) alphaInput.value = 100;
875
876      if(alphaInput.value > 0) {
877        $('#clr-color-comment, .back-black').addClass('hide');
878      } else {
879        $('#clr-color-comment, .back-black').removeClass('hide');
880      }
881
882      var alpha = alphaInput.value / 100;
883
884      alphaSlider.value = alphaInput.value;
885      alphaMarker.style.left = alpha * 100 + "%";
886      updateColor({ a: alpha });
887      // pickColor();
888    }
889  
890  
891    /**
892     * Convert HSVA to RGBA.
893     * @param {object} hsva Hue, saturation, value and alpha values.
894     * @return {object} Red, green, blue and alpha values.
895     */
896    function HSVAtoRGBA(hsva) {
897      var saturation = hsva.s / 100;
898      var value = hsva.v / 100;
899      var chroma = saturation * value;
900      var hueBy60 = hsva.h / 60;
901      var x = chroma * (1 - Math.abs(hueBy60 % 2 - 1));
902      var m = value - chroma;
903  
904      chroma = chroma + m;
905      x = x + m;
906  
907      var index = Math.floor(hueBy60) % 6;
908      var red = [chroma, x, m, m, x, chroma][index];
909      var green = [x, chroma, chroma, x, m, m][index];
910      var blue = [m, m, x, chroma, chroma, x][index];
911  
912      return {
913        r: Math.round(red * 255),
914        g: Math.round(green * 255),
915        b: Math.round(blue * 255),
916        a: hsva.a };
917  
918    }
919  
920    /**
921     * Convert HSVA to HSLA.
922     * @param {object} hsva Hue, saturation, value and alpha values.
923     * @return {object} Hue, saturation, lightness and alpha values.
924     */
925    function HSVAtoHSLA(hsva) {
926      var value = hsva.v / 100;
927      var lightness = value * (1 - hsva.s / 100 / 2);
928      var saturation;
929  
930      if (lightness > 0 && lightness < 1) {
931        saturation = Math.round((value - lightness) / Math.min(lightness, 1 - lightness) * 100);
932      }
933  
934      return {
935        h: hsva.h,
936        s: saturation || 0,
937        l: Math.round(lightness * 100),
938        a: hsva.a };
939  
940    }
941  
942    /**
943     * Convert RGBA to HSVA.
944     * @param {object} rgba Red, green, blue and alpha values.
945     * @return {object} Hue, saturation, value and alpha values.
946     */
947    function RGBAtoHSVA(rgba) {
948      var red = rgba.r / 255;
949      var green = rgba.g / 255;
950      var blue = rgba.b / 255;
951      var xmax = Math.max(red, green, blue);
952      var xmin = Math.min(red, green, blue);
953      var chroma = xmax - xmin;
954      var value = xmax;
955      var hue = 0;
956      var saturation = 0;
957  
958      if (chroma) {
959        if (xmax === red) {hue = (green - blue) / chroma;}
960        if (xmax === green) {hue = 2 + (blue - red) / chroma;}
961        if (xmax === blue) {hue = 4 + (red - green) / chroma;}
962        if (xmax) {saturation = chroma / xmax;}
963      }
964  
965      hue = Math.floor(hue * 60);
966  
967      return {
968        h: hue < 0 ? hue + 360 : hue,
969        s: Math.round(saturation * 100),
970        v: Math.round(value * 100),
971        a: rgba.a };
972  
973    }
974  
975    /**
976     * Parse a string to RGBA.
977     * @param {string} str String representing a color.
978     * @return {object} Red, green, blue and alpha values.
979     */
980    function strToRGBA(str) {
981      var regex = /^((rgba)|rgb)[\D]+([\d.]+)[\D]+([\d.]+)[\D]+([\d.]+)[\D]*?([\d.]+|$)/i;
982      var match, rgba;
983  
984      // Default to black for invalid color strings
985      ctx.fillStyle = '#000';
986  
987      // Use canvas to convert the string to a valid color string
988      ctx.fillStyle = str;
989      match = regex.exec(ctx.fillStyle);
990  
991      if (match) {
992        rgba = {
993          r: match[3] * 1,
994          g: match[4] * 1,
995          b: match[5] * 1,
996          a: match[6] * 1 };
997  
998  
999        // Workaround to mitigate a Chromium bug where the alpha value is rounded incorrectly
1000        rgba.a = +rgba.a.toFixed(2);
1001  
1002      } else {
1003        match = ctx.fillStyle.replace('#', '').match(/.{2}/g).map(function (h) {return parseInt(h, 16);});
1004        rgba = {
1005          r: match[0],
1006          g: match[1],
1007          b: match[2],
1008          a: 1 };
1009  
1010      }
1011  
1012      return rgba;
1013    }
1014  
1015    /**
1016     * Convert RGBA to Hex.
1017     * @param {object} rgba Red, green, blue and alpha values.
1018     * @return {string} Hex color string.
1019     */
1020    function RGBAToHex(rgba) {
1021      var R = rgba.r.toString(16);
1022      var G = rgba.g.toString(16);
1023      var B = rgba.b.toString(16);
1024      var A = '';
1025  
1026      if (rgba.r < 16) {
1027        R = '0' + R;
1028      }
1029  
1030      if (rgba.g < 16) {
1031        G = '0' + G;
1032      }
1033  
1034      if (rgba.b < 16) {
1035        B = '0' + B;
1036      }
1037  
1038      if (settings.alpha && (rgba.a < 1 || settings.forceAlpha)) {
1039        var alpha = rgba.a * 255 | 0;
1040        A = alpha.toString(16);
1041  
1042        if (alpha < 16) {
1043          A = '0' + A;
1044        }
1045      }
1046  
1047      return '#' + R + G + B + A;
1048    }
1049  
1050    /**
1051     * Convert RGBA values to a CSS rgb/rgba string.
1052     * @param {object} rgba Red, green, blue and alpha values.
1053     * @return {string} CSS color string.
1054     */
1055    function RGBAToStr(rgba) {
1056      if (!settings.alpha || rgba.a === 1 && !settings.forceAlpha) {
1057        return "rgb(" + rgba.r + ", " + rgba.g + ", " + rgba.b + ")";
1058      } else {
1059        return "rgba(" + rgba.r + ", " + rgba.g + ", " + rgba.b + ", " + rgba.a + ")";
1060      }
1061    }
1062  
1063    /**
1064     * Convert HSLA values to a CSS hsl/hsla string.
1065     * @param {object} hsla Hue, saturation, lightness and alpha values.
1066     * @return {string} CSS color string.
1067     */
1068    function HSLAToStr(hsla) {
1069      if (!settings.alpha || hsla.a === 1 && !settings.forceAlpha) {
1070        return "hsl(" + hsla.h + ", " + hsla.s + "%, " + hsla.l + "%)";
1071      } else {
1072        return "hsla(" + hsla.h + ", " + hsla.s + "%, " + hsla.l + "%, " + hsla.a + ")";
1073      }
1074    }
1075  
1076    /**
1077     * Init the color picker.
1078     */
1079    function init() {
1080      // Render the UI
1081      var checkEditorMode = (typeof PAGE_MODE != 'undefined' && PAGE_MODE == 'c');
1082      var alphaInfoLabel = checkEditorMode ? _coloris_label[(LANG === 'ko') ? 'ko' : 'en'].alpha_info : '';
1083
1084      container = undefined;
1085      picker_backdrop = document.createElement('div');
1086      picker_backdrop.setAttribute('id', 'clr-picker-backdrop');
1087      picker_backdrop.className = 'clr-picker-backdrop';
1088      
1089      picker = document.createElement('div');
1090      picker.setAttribute('id', 'clr-picker');
1091      picker.className = 'clr-picker';
1092      picker.innerHTML = `
1093        <div class="clr-body">
1094          <div class="clr-section top">
1095            <div id="clr-color-area" class="clr-gradient" role="application" aria-label="${settings.a11y.instruction}">
1096              <div id="clr-color-marker" class="clr-marker" tabindex="0"></div>
1097              <div id="clr-color-cursor" class="clr-cursor" tabindex="-1"></div>
1098              <div class="back-black"></div>
1099              <div id="clr-color-comment" class="clr-comment" tabindex="-2">${alphaInfoLabel}</div>
1100            </div>
1101            <div class="clr-hue">
1102              <input id="clr-hue-slider" inputmode="none" onfocus="this.blur()" name="clr-hue-slider" type="range" min="0" max="360" step="1" aria-label="${settings.a11y.hueSlider}">
1103              <div id="clr-hue-marker" class="clr-hue-marker"></div>
1104            </div>
1105            <div class="clr-color-info hex">
1106              <div class="info-label">
1107                ${settings.a11y.hexLabel}
1108              </div>
1109              <div class="info-val">
1110                <input id="clr-hex-value" name="clr-hex-value" class="clr-hex-value" type="text" value="" aria-label="${settings.a11y.hexInput}">
1111              </div>
1112            </div>
1113            <div class="clr-alpha">
1114              <input id="clr-alpha-slider" inputmode="none" onfocus="this.blur()"  name="clr-alpha-slider" type="range" min="0" max="100" step="1" aria-label="${settings.a11y.alphaSlider}">
1115              <div id="clr-alpha-marker" class="clr-alpha-marker"></div>
1116              <span></span>
1117            </div>
1118            <div class="clr-color-info alpha">
1119              <div class="info-label">
1120                ${settings.a11y.alphaLabel}
1121              </div>
1122              <div class="info-val">
1123                <input id="clr-alpha-value" name="clr-alpha-value" class="clr-alpha-value" type="number" value="" aria-label="${settings.a11y.alphaInput}">
1124              </div>
1125            </div>
1126          </div>
1127          <div class="clr-section center">
1128            <div id="clr-format" class="clr-format">
1129              <fieldset class="clr-segmented">
1130                <legend>${settings.a11y.format}</legend>
1131                <input id="clr-f1" type="radio" name="clr-format" value="hex">
1132                <label for="clr-f1">Hex</label>
1133                <input id="clr-f2" type="radio" name="clr-format" value="rgb">
1134                <label for="clr-f2">RGB</label>
1135                <input id="clr-f3" type="radio" name="clr-format" value="hsl">
1136                <label for="clr-f3">HSL</label>
1137                <span></span>
1138              </fieldset>
1139            </div>
1140            <div class="clr-color-info color hide">
1141              <div class="info-label">
1142                ${settings.a11y.inputLabel}
1143                <span class="bc-tooltip colorisguide">${tooltipSVG('top','',`${_coloris_label[(LANG === 'ko') ? 'ko' : 'en'].guide}`,'')}</span>
1144              </div>
1145              <div class="info-val">
1146                <input id="clr-color-value" name="clr-color-value" class="clr-color" type="text" value="" spellcheck="false" aria-label="${settings.a11y.input}">
1147              </div>
1148            </div>
1149            <div id="clr-swatches" class="clr-swatches"></div>
1150          </div>
1151          <div class="clr-section bottom">
1152            <div class="clr-palette-box ready" id="clr-palette-box">
1153              <div id="clr-color-preview" class="clr-preview"></div>
1154              <div id="clr-color-current" class="clr-current"></div>
1155            </div>
1156            <div class="clr-btn-box" id="clr-btn-box">
1157              <button type="button" id="clr-clear" class="clr-clear" aria-label="${settings.a11y.clear}">${settings.clearLabel}</button>
1158              <button type="button" id="clr-cancel" class="clr-cancel" aria-label="${settings.a11y.cancel}">${settings.cancelLabel}</button>
1159              <button type="button" id="clr-close" class="clr-close" aria-label="${settings.a11y.close}">${settings.closeLabel}</button>
1160            </div>
1161          </div>
1162          <span id="clr-open-label" hidden>${settings.a11y.open}</span>
1163          <span id="clr-swatch-label" hidden>${settings.a11y.swatch}</span>
1164        </div>
1165      `;
1166
1167      /*
1168      picker.innerHTML =
1169      "<input id=\"clr-color-value\" name=\"clr-color-value\" class=\"clr-color\" type=\"text\" value=\"\" spellcheck=\"false\" aria-label=\"" + settings.a11y.input + "\">" + ("<div id=\"clr-color-area\" class=\"clr-gradient\" role=\"application\" aria-label=\"" +
1170      settings.a11y.instruction + "\">") +
1171      '<div id="clr-color-marker" class="clr-marker" tabindex="0"></div>' +
1172      '</div>' +
1173      '<div class="clr-hue">' + ("<input id=\"clr-hue-slider\" name=\"clr-hue-slider\" type=\"range\" min=\"0\" max=\"360\" step=\"1\" aria-label=\"" +
1174      settings.a11y.hueSlider + "\">") +
1175      '<div id="clr-hue-marker"></div>' +
1176      '</div>' +
1177      '<div class="clr-alpha">' + ("<input id=\"clr-alpha-slider\" name=\"clr-alpha-slider\" type=\"range\" min=\"0\" max=\"100\" step=\"1\" aria-label=\"" +
1178      settings.a11y.alphaSlider + "\">") +
1179      '<div id="clr-alpha-marker"></div>' +
1180      '<span></span>' +
1181      '</div>' +
1182      '<div id="clr-format" class="clr-format">' +
1183      '<fieldset class="clr-segmented">' + ("<legend>" +
1184      settings.a11y.format + "</legend>") +
1185      '<input id="clr-f1" type="radio" name="clr-format" value="hex">' +
1186      '<label for="clr-f1">Hex</label>' +
1187      '<input id="clr-f2" type="radio" name="clr-format" value="rgb">' +
1188      '<label for="clr-f2">RGB</label>' +
1189      '<input id="clr-f3" type="radio" name="clr-format" value="hsl">' +
1190      '<label for="clr-f3">HSL</label>' +
1191      '<span></span>' +
1192      '</fieldset>' +
1193      '</div>' +
1194      '<div id="clr-swatches" class="clr-swatches"></div>' + ("<button type=\"button\" id=\"clr-clear\" class=\"clr-clear\" aria-label=\"" +
1195      settings.a11y.clear + "\">" + settings.clearLabel + "</button>") +
1196      '<div id="clr-color-preview" class="clr-preview">' + ("<button type=\"button\" id=\"clr-close\" class=\"clr-close\" aria-label=\"" +
1197      settings.a11y.close + "\">" + settings.closeLabel + "</button>") +
1198      '</div>' + ("<span id=\"clr-open-label\" hidden>" +
1199      settings.a11y.open + "</span>") + ("<span id=\"clr-swatch-label\" hidden>" +
1200      settings.a11y.swatch + "</span>");
1201      */
1202
1203
1204      // Append the color picker to the DOM
1205      picker.querySelectorAll('input').forEach(excludeColorFieldAutofill);
1206      document.body.appendChild(picker);
1207      document.body.appendChild(picker_backdrop);
1208  
1209      // Reference the UI elements
1210      colorArea = getEl('clr-color-area');
1211      colorMarker = getEl('clr-color-marker');
1212      colorCursor = getEl('clr-color-cursor');
1213      btnBox = getEl('clr-btn-box');
1214      clearButton = getEl('clr-clear');
1215      cancelButton = getEl('clr-cancel');
1216      closeButton = getEl('clr-close');
1217      paletteBox = getEl('clr-palette-box');
1218      colorPreview = getEl('clr-color-preview');
1219      colorCurrent = getEl('clr-color-current');
1220      colorValue = getEl('clr-color-value');
1221      hueSlider = getEl('clr-hue-slider');
1222      hueMarker = getEl('clr-hue-marker');
1223      hexInput = getEl('clr-hex-value');
1224      alphaInput = getEl('clr-alpha-value');
1225      alphaSlider = getEl('clr-alpha-slider');
1226      alphaMarker = getEl('clr-alpha-marker');
1227  
1228      // Bind the picker to the default selector
1229      bindFields(settings.el);
1230      wrapFields(settings.el);
1231
1232      addListener(picker_backdrop, 'mousedown', function (event) {
1233        closePicker(true);
1234      });
1235  
1236      addListener(picker, 'mousedown', function (event) {
1237        picker.classList.remove('clr-keyboard-nav');
1238        event.stopPropagation();
1239      });
1240
1241      addListener(colorArea, 'mousedown', function (event) {
1242        addListener(document, 'mousemove', moveMarker);
1243      });
1244  
1245      addListener(colorArea, 'touchstart', function (event) {
1246        document.addEventListener('touchmove', moveMarker, { passive: false });
1247      });
1248
1249      addListener(colorArea, 'mousemove', function (event) {
1250        var tmpColorCursor = document.querySelector('.clr-cursor');
1251        tmpColorCursor.style.top = (event.pageY - Math.round($('#clr-color-area').offset().top) + 1) + 'px';
1252        tmpColorCursor.style.left = (event.pageX - Math.round($('#clr-color-area').offset().left) - 1) + 'px';
1253      });
1254  
1255      addListener(colorMarker, 'mousedown', function (event) {
1256        addListener(document, 'mousemove', moveMarker);
1257      });
1258  
1259      addListener(colorMarker, 'touchstart', function (event) {
1260        document.addEventListener('touchmove', moveMarker, { passive: false });
1261      });
1262  
1263      addListener(colorValue, 'change', function (event) {
1264        var value = colorValue.value;
1265
1266        if (currentEl || settings.inline) {
1267          var color = value === '' ? value : setColorFromStr(value);
1268          pickColor(color);
1269        }
1270        
1271        $('#clr-color-comment').addClass('hide');
1272        $('.back-black').addClass('hide');
1273        if(alphaInput.value == 0) {
1274          $('#clr-color-comment').removeClass('hide');
1275          $('.back-black').removeClass('hide');
1276        }
1277      });
1278      addListener(colorValue, 'keyup', function(e) { if(e.which == 13) { $(this).closest('.clr-picker').find('.clr-close').click(); } });
1279  
1280      addListener(clearButton, 'click', function (event) {
1281        pickColor('');
1282        closePicker();
1283      });
1284  
1285      addListener(closeButton, 'click', function (event) {
1286        pickColor();
1287        closePicker();
1288      });
1289
1290      addListener(cancelButton, 'click', function (event) {
1291        closePicker(true);
1292      });
1293  
1294      addListener(getEl('clr-format'), 'click', '.clr-format input', function (event) {
1295        currentFormat = event.target.value;
1296        updateColor();
1297        pickColor();
1298      });
1299  
1300      addListener(picker, 'click', '.clr-swatches button', function (event) {
1301        setColorFromStr(event.target.textContent);
1302        // pickColor();
1303  
1304        if (settings.swatchesOnly) {
1305          closePicker();
1306        }
1307      });
1308  
1309      addListener(document, 'mouseup', function (event) {
1310        document.removeEventListener('mousemove', moveMarker);
1311      });
1312  
1313      addListener(document, 'touchend', function (event) {
1314        document.removeEventListener('touchmove', moveMarker);
1315      });
1316  
1317      addListener(document, 'mousedown', function (event) {
1318        keyboardNav = false;
1319        picker.classList.remove('clr-keyboard-nav');
1320        closePicker();
1321      });
1322  
1323      addListener(document, 'keydown', function (event) {
1324        var key = event.key;
1325        var target = event.target;
1326        var shiftKey = event.shiftKey;
1327        var navKeys = ['Tab', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
1328  
1329        if (key === 'Escape') {
1330          closePicker(true);
1331  
1332          // Display focus rings when using the keyboard
1333        } else if (navKeys.includes(key)) {
1334          keyboardNav = true;
1335          picker.classList.add('clr-keyboard-nav');
1336        }
1337
1338        // Trap the focus within the color picker while it's open
1339        if (key === 'Tab' && target.matches('.clr-picker *')) {
1340          var focusables = getFocusableElements();
1341          var firstFocusable = focusables.shift();
1342          var lastFocusable = focusables.pop();
1343  
1344          if (shiftKey && target === firstFocusable) {
1345            lastFocusable.focus();
1346            event.preventDefault();
1347          } else if (!shiftKey && target === lastFocusable) {
1348            firstFocusable.focus();
1349            event.preventDefault();
1350          }
1351        }
1352      });
1353  
1354      addListener(document, 'click', '.clr-field button', function (event) {
1355        // Reset any previously set per-instance options
1356        if (hasInstance) {
1357          resetVirtualInstance();
1358        }
1359  
1360        // Open the color picker
1361        event.target.nextElementSibling.dispatchEvent(new Event('click', { bubbles: true }));
1362      });
1363  
1364      addListener(colorMarker, 'keydown', function (event) {
1365        var movements = {
1366          ArrowUp: [0, -1],
1367          ArrowDown: [0, 1],
1368          ArrowLeft: [-1, 0],
1369          ArrowRight: [1, 0] };
1370  
1371  
1372        if (Object.keys(movements).includes(event.key)) {
1373          moveMarkerOnKeydown.apply(void 0, movements[event.key]);
1374          event.preventDefault();
1375        }
1376      });
1377  
1378      addListener(colorArea, 'click', moveMarker);
1379      addListener(hueSlider, 'input', setHue);
1380      
1381      addListener(alphaInput, 'input', setAlphaInput);
1382      addListener(alphaInput, 'keyup', function(e) { if(e.which == 13) { $(this).closest('.clr-picker').find('.clr-close').click(); } });
1383      addListener(alphaSlider, 'input', setAlpha);
1384
1385      addListener(hexInput, 'change', function (event) {
1386        var hex6 = hexInput.value,
1387            alpha = (settings.alpha) ? alphaInput.value : 100,
1388            new_color = getChangeColorVal([hex6,'a',alpha / 100]);
1389
1390        if (currentEl || settings.inline) {
1391          var color = new_color === '' ? hex6 : setColorFromStr(new_color);
1392          pickColor(color);
1393        }
1394      });
1395      addListener(hexInput, 'keyup', function(e) { if(e.which == 13) { $(this).closest('.clr-picker').find('.clr-close').click(); } });
1396
1397    }
1398  
1399    /**
1400     * Return a list of focusable elements within the color picker.
1401     * @return {array} The list of focusable DOM elemnts.
1402     */
1403    function getFocusableElements() {
1404      var controls = Array.from(picker.querySelectorAll('input, button'));
1405      var focusables = controls.filter(function (node) {return !!node.offsetWidth;});
1406  
1407      return focusables;
1408    }
1409  
1410    /**
1411     * Shortcut for getElementById to optimize the minified JS.
1412     * @param {string} id The element id.
1413     * @return {object} The DOM element with the provided id.
1414     */
1415    function getEl(id) {
1416      return document.getElementById(id);
1417    }
1418  
1419    /**
1420     * Shortcut for addEventListener to optimize the minified JS.
1421     * @param {object} context The context to which the listener is attached.
1422     * @param {string} type Event type.
1423     * @param {(string|function)} selector Event target if delegation is used, event handler if not.
1424     * @param {function} [fn] Event handler if delegation is used.
1425     */
1426    function addListener(context, type, selector, fn) {
1427      var matches = Element.prototype.matches || Element.prototype.msMatchesSelector;
1428  
1429      // Delegate event to the target of the selector
1430      if (typeof selector === 'string') {
1431        context.addEventListener(type, function (event) {
1432          if (matches.call(event.target, selector)) {
1433            fn.call(event.target, event);
1434          }
1435        });
1436  
1437        // If the selector is not a string then it's a function
1438        // in which case we need a regular event listener
1439      } else {
1440        fn = selector;
1441        context.addEventListener(type, fn);
1442      }
1443    }
1444  
1445    /**
1446     * Call a function only when the DOM is ready.
1447     * @param {function} fn The function to call.
1448     * @param {array} [args] Arguments to pass to the function.
1449     */
1450    function DOMReady(fn, args) {
1451      args = args !== undefined ? args : [];
1452
1453      if($.inArray(fn.name, checkReturnFuncArr) > -1) return fn(args);
1454  
1455      if (document.readyState !== 'loading') {
1456        fn.apply(void 0, args);
1457      } else {
1458        document.addEventListener('DOMContentLoaded', function () {
1459          fn.apply(void 0, args);
1460        });
1461      }
1462    }
1463
1464
1465    function getColorSelectorPnInfo(args_arr) { 
1466      var css = args_arr[0],
1467          elname = (typeof args_arr[1] != 'undefined') ? args_arr[1] : '',
1468          selector = (typeof args_arr[2] != 'undefined') ? args_arr[2] : '',
1469          pn = (typeof args_arr[3] != 'undefined') ? args_arr[3] : '',
1470          withcss = (typeof args_arr[4] != 'undefined') ? args_arr[4] : '',
1471          result = {'selector':selector, 'pn':pn, 'color':''}
1472
1473      var this_selector = '',
1474          this_pn = '',
1475          this_color = '',
1476          this_css = {};
1477      
1478      var elnameRegex = new RegExp('^\.' + elname),
1479          checkSelectorWidthElname = (selector.match(elnameRegex) != null) ? true : false;
1480
1481      $.each(selector.split(','), function(i,s) {
1482          if(i > 0) this_selector += ',';
1483          this_selector += (checkSelectorWidthElname) ? s.trim() : '.' + elname + ' ' + s.trim();
1484
1485          var tmp_pn = pn.split(','),
1486              tmp_s = s.trim(),
1487              tmp_changepn = s.match(/^(.*?)(?=\([^)]*\)$)/);
1488          if(tmp_changepn != null) {
1489            tmp_pn = s.substring(tmp_changepn[0].length + 1, s.length - 1).split('/');
1490            tmp_s = tmp_changepn[0].trim();
1491          }
1492
1493          var tmp_selector = (checkSelectorWidthElname) ? tmp_s : '.' + elname + ' ' + tmp_s,
1494              tmp_style = style.get(css,tmp_selector);
1495          if(typeof this_css[tmp_selector] == 'undefined') this_css[tmp_selector] = {};
1496
1497          if(withcss) {
1498            $.each(withcss.split(','), function(i,v) {
1499              if(!v) return;
1500
1501              if($.inArray(v, ['fill','color','background','background-color','border-color','border','border-top','border-bottom','border-left','border-right']) > -1) {
1502                if(tmp_pn.indexOf(v) < 0) tmp_pn.push(v);
1503                return;
1504              }
1505  
1506              var tmp_v = '';
1507              switch(v) {
1508                case 'font-family': tmp_v = tmp_style.txName; break;
1509                case 'font-size':   tmp_v = tmp_style.txSize; break;
1510                default:            tmp_v = style.getCssProperty(css,tmp_selector,v); break;
1511              }
1512  
1513              this_css[tmp_selector][v] = {'val': tmp_v};
1514            });
1515          }
1516
1517          $.each(tmp_pn, function(i,v) {
1518            var tmp_color = '';
1519            switch(v) {
1520              case 'fill': tmp_color = tmp_style.fill; break;
1521              case 'color': tmp_color = tmp_style.txColor; break;
1522              case 'background':
1523              case 'background-color': tmp_color = tmp_style.bgColor; break;
1524              case 'border-color': 
1525              case 'border': 
1526              case 'border-top':
1527              case 'border-bottom':
1528              case 'border-left':
1529              case 'border-right': tmp_color = tmp_style.borderColor; break;
1530              default: break;
1531            }
1532
1533            if(v) {
1534              this_css[tmp_selector][v] = {
1535                'val': style.getCssProperty(css,tmp_selector,v),
1536                'color': Coloris.getColorInfo(tmp_color,'org'),
1537              };
1538
1539              if(typeof this_css[tmp_selector][v]['val'] != 'string') this_css[tmp_selector][v]['val'] = this_css[tmp_selector][v]['val'].pop();
1540
1541              if(pn.split(',').length > 1 && pn.split(',').indexOf(v) > -1) {
1542                this_css[tmp_selector][v]['checkPass'] = (this_css[tmp_selector][v]['color'] == '' && $.inArray(this_css[tmp_selector][v]['val'], ['initial','inherit']) > -1) ? true : false;
1543              }
1544            }
1545
1546
1547            if(i == 0) {
1548              this_pn = v;
1549              this_color = tmp_color;
1550            }
1551          });
1552      });
1553
1554      return {
1555        'selector': this_selector,
1556        'pn': this_pn,
1557        'color': this_color,
1558        'css': this_css,
1559      }
1560    }
1561
1562    function getColorInfo(args_arr) {
1563      var tmp_str = args_arr[0],
1564          return_type = (typeof args_arr[1] != 'undefined' && args_arr[1]) ? args_arr[1] : 'hex8';
1565
1566      var str = (typeof tmp_str == 'string') ? tmp_str : tmp_str.pop(),
1567          colorRegex = getColorRegex(),
1568          tmp_matches = str.match(colorRegex);
1569      if(tmp_matches != null) str = tmp_matches.pop();
1570      if(return_type == 'org') return str;
1571
1572      var this_rgba = strToRGBA(str),
1573          this_hex = RGBAToHex(this_rgba);
1574
1575      if(return_type == 'hex' || return_type == 'rgb') {
1576        this_rgba['a'] = 1;
1577        return (return_type == 'rgb') ? RGBAToStr(this_rgba) : RGBAToHex(this_rgba);
1578      }
1579      else if(return_type == 'rgba') return RGBAToStr(this_rgba);
1580      else if(return_type == 'alpha') return this_rgba['a'];
1581      else return this_hex;
1582    }
1583
1584    function getColorRegex() {
1585      return new RegExp(/(#([a-fA-F0-9]{3,8})\b|rgba?\(\s*(\d{1,3}\s*,\s*){2}\d{1,3}\s*(,\s*\d*(?:\.\d+)?)?\s*\)|hsla?\(\s*\d{1,3}\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%\s*(,\s*\d*(?:\.\d+)?)?\s*\)|\btransparent\b|\binherit\b|\binitial\b|\bunset\b|\brevert\b)/g);
1586    }
1587
1588    function getChangeColorVal(args_arr) {
1589      var str = args_arr[0],
1590          change_key = (typeof args_arr[1] != 'undefined' && args_arr[1]) ? args_arr[1] : '',
1591          change_val = (typeof args_arr[2] != 'undefined' && args_arr[2]) ? args_arr[2] : '';
1592
1593      var this_rgba = strToRGBA(str),
1594          this_hex = RGBAToHex(this_rgba);
1595      if(change_key == '' && change_val == '') return this_hex.substring(0, 7);
1596      if(change_key == 'rgb_str') return this_rgba.r+','+this_rgba.g+','+this_rgba.b;
1597
1598      if(change_key && typeof this_rgba[change_key] != 'undefined') {
1599          this_rgba[change_key] = change_val * 1;
1600      }
1601
1602      var org_alpha = settings.alpha;
1603      if(change_key == 'a') settings.alpha = true;
1604      var hex = RGBAToHex(this_rgba);
1605      if(change_key == 'a') settings.alpha = org_alpha;
1606
1607      if(this_rgba.a < 1) return 'rgba('+this_rgba.r+','+this_rgba.g+','+this_rgba.b+','+this_rgba.a+')';
1608      else return hex;
1609          // opaqueHex = hex.substring(0, 7);
1610    }
1611
1612  
1613    // Polyfill for Nodelist.forEach
1614    if (NodeList !== undefined && NodeList.prototype && !NodeList.prototype.forEach) {
1615      NodeList.prototype.forEach = Array.prototype.forEach;
1616    }
1617  
1618    // Expose the color picker to the global scope
1619    window.Coloris = function () {
1620      var methods = {
1621        set: configure,
1622        wrap: wrapFields,
1623        close: closePicker,
1624        setInstance: setVirtualInstance,
1625        removeInstance: removeVirtualInstance,
1626        updatePosition: updatePickerPosition,
1627        ready: DOMReady
1628      };
1629
1630      $.each(checkUsedFuncArr, function(i,fname) {
1631        methods[fname] = eval(fname);
1632      });
1633
1634      $.each(checkReturnFuncArr, function(i,fname) {
1635        methods[fname] = eval(fname);
1636      });
1637  
1638      function Coloris(options) {
1639        DOMReady(function () {
1640          if (options) {
1641            if (typeof options === 'string') {
1642              bindFields(options);
1643            } else {
1644              configure(options);
1645            }
1646          }
1647        });
1648      }
1649      
1650      var _loop2 = function _loop2(key) {
1651        Coloris[key] = function () {
1652          for (var _len = arguments.length, args = new Array(_len), _key2 = 0; _key2 < _len; _key2++) {
1653            args[_key2] = arguments[_key2];
1654          }
1655
1656          if($.inArray(key, checkReturnFuncArr) > -1) return DOMReady(methods[key], args);
1657          else DOMReady(methods[key], args);
1658        };
1659      };
1660        
1661        
1662      for (var key in methods) {
1663          _loop2(key);
1664      }
1665  
1666      return Coloris;
1667    }();
1668  
1669    // Init the color picker when the DOM is ready
1670    DOMReady(init);
1671  
1672  })(window, document, Math);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.