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 wrapFields(selector) { 533 document.querySelectorAll(selector).forEach(function (field) { 534 var parentNode = field.parentNode; 535 536 if (!parentNode.classList.contains('clr-field')) { 537 var wrapper = document.createElement('div'); 538 var classes = 'clr-field'; 539 540 if (settings.rtl || field.classList.contains('clr-rtl')) { 541 classes += ' clr-rtl'; 542 } 543 544 wrapper.innerHTML = "<button type=\"button\" aria-labelledby=\"clr-open-label\"></button>"; 545 parentNode.insertBefore(wrapper, field); 546 wrapper.setAttribute('class', classes); 547 wrapper.style.color = field.value; 548 wrapper.appendChild(field); 549 } 550 }); 551 } 552 553 /** 554 * Close the color picker. 555 * @param {boolean} [revert] If true, revert the color to the original value. 556 */ 557 function closePicker(revert) {
558 if (currentEl && !settings.inline) { 559 var prevEl = currentEl; 560 561 // Revert the color to the original value if needed 562 if (revert) { 563 // This will prevent the "change" event on the colorValue input to execute its handler 564 currentEl = undefined; 565 566 if (oldColor !== prevEl.value) { 567 prevEl.value = oldColor; 568 569 // Trigger an "input" event to force update the thumbnail next to the input field 570 prevEl.dispatchEvent(new Event('input', { bubbles: true })); 571 } 572 } 573 574 // Trigger a "change" event if needed 575 setTimeout(function () {// Add this to the end of the event loop 576 if (oldColor !== prevEl.value) { 577 prevEl.dispatchEvent(new Event('change', { bubbles: true })); 578 } 579 }); 580 581 // Hide the picker dialog 582 picker.classList.remove('clr-open'); 583 584 // Reset any previously set per-instance options 585 if (hasInstance) { 586 resetVirtualInstance(); 587 } 588 589 // Trigger a "close" event 590 prevEl.dispatchEvent(new Event('close', { bubbles: true })); 591 592 if (settings.focusInput) { 593 prevEl.focus({ preventScroll: false }); 594 } 595 596 // This essentially marks the picker as closed 597 currentEl = undefined; 598 } 599 } 600 601 /** 602 * Set the active color from a string. 603 * @param {string} str String representing a color. 604 */ 605 function setColorFromStr(str) { 606 var rgba = strToRGBA(str); 607 var hsva = RGBAtoHSVA(rgba); 608 609 updateMarkerA11yLabel(hsva.s, hsva.v); 610 updateColor(rgba, hsva); 611 612 // Update the UI 613 hueSlider.value = hsva.h; 614 picker.style.color = "hsl(" + hsva.h + ", 100%, 50%)"; 615 hueMarker.style.left = hsva.h / 360 * 100 + "%"; 616 617 colorMarker.style.left = colorAreaDims.width * hsva.s / 100 + "px"; 618 colorMarker.style.top = colorAreaDims.height - colorAreaDims.height * hsva.v / 100 + "px"; 619 620 alphaSlider.value = hsva.a * 100; 621 alphaMarker.style.left = hsva.a * 100 + "%"; 622 alphaInput.value = alphaSlider.value; 623 } 624 625 /** 626 * Guess the color format from a string. 627 * @param {string} str String representing a color. 628 * @return {string} The color format. 629 */ 630 function getColorFormatFromStr(str) { 631 var format = str.substring(0, 3).toLowerCase(); 632 633 if (format === 'rgb' || format === 'hsl') { 634 return format; 635 } 636 637 return 'hex'; 638 } 639 640 /** 641 * Copy the active color to the linked input field. 642 * @param {number} [color] Color value to override the active color. 643 */ 644 function pickColor(color) { 645 color = color !== undefined ? color : colorValue.value; 646 647 if (currentEl) { 648 currentEl.value = color; 649 currentEl.dispatchEvent(new Event('input', { bubbles: true })); 650 } 651 652 if (settings.onChange) { 653 settings.onChange.call(window, color, currentEl); 654 } 655 656 document.dispatchEvent(new CustomEvent('coloris:pick', { detail: { color: color, currentEl: currentEl } })); 657 } 658 659 /** 660 * Set the active color based on a specific point in the color gradient. 661 * @param {number} x Left position. 662 * @param {number} y Top position. 663 */ 664 function setColorAtPosition(x, y) { 665 var hsva = { 666 h: hueSlider.value * 1, 667 s: x / colorAreaDims.width * 100, 668 v: 100 - y / colorAreaDims.height * 100, 669 a: alphaSlider.value / 100 }; 670 671 var rgba = HSVAtoRGBA(hsva); 672 673 updateMarkerA11yLabel(hsva.s, hsva.v); 674 updateColor(rgba, hsva); 675 // pickColor(); 676 } 677 678 /** 679 * Update the color marker's accessibility label. 680 * @param {number} saturation 681 * @param {number} value 682 */ 683 function updateMarkerA11yLabel(saturation, value) { 684 var label = settings.a11y.marker; 685 686 saturation = saturation.toFixed(1) * 1; 687 value = value.toFixed(1) * 1; 688 label = label.replace('{s}', saturation); 689 label = label.replace('{v}', value); 690 colorMarker.setAttribute('aria-label', label); 691 } 692 693 // 694 /** 695 * Get the pageX and pageY positions of the pointer. 696 * @param {object} event The MouseEvent or TouchEvent object. 697 * @return {object} The pageX and pageY positions. 698 */ 699 function getPointerPosition(event) { 700 return { 701 pageX: event.changedTouches ? event.changedTouches[0].pageX : event.pageX, 702 pageY: event.changedTouches ? event.changedTouches[0].pageY : event.pageY }; 703 704 } 705 706 /** 707 * Move the color marker when dragged. 708 * @param {object} event The MouseEvent object. 709 */ 710 function moveMarker(event) { 711 var pointer = getPointerPosition(event); 712 var x = pointer.pageX - colorAreaDims.x; 713 var y = pointer.pageY - colorAreaDims.y; 714 715 if (container) { 716 y += container.scrollTop; 717 } 718 719 setMarkerPosition(x, y); 720 721 // Prevent scrolling while dragging the marker 722 event.preventDefault(); 723 event.stopPropagation(); 724 } 725 726 /** 727 * Move the color marker when the arrow keys are pressed. 728 * @param {number} offsetX The horizontal amount to move. 729 * @param {number} offsetY The vertical amount to move. 730 */ 731 function moveMarkerOnKeydown(offsetX, offsetY) { 732 var x = colorMarker.style.left.replace('px', '') * 1 + offsetX; 733 var y = colorMarker.style.top.replace('px', '') * 1 + offsetY; 734 735 setMarkerPosition(x, y); 736 } 737 738 /** 739 * Set the color marker's position. 740 * @param {number} x Left position. 741 * @param {number} y Top position. 742 */ 743 function setMarkerPosition(x, y) { 744 745 // .clr-picker padding val 746 x -= 22; 747 y -= 20; 748 749 // Make sure the marker doesn't go out of bounds 750 x = x < 0 ? 0 : x > colorAreaDims.width ? colorAreaDims.width : x; 751 y = y < 0 ? 0 : y > colorAreaDims.height ? colorAreaDims.height : y; 752 753 // Set the position 754 colorMarker.style.left = x + 'px'; 755 colorMarker.style.top = y + 'px'; 756 757 colorCursor.style.lfet = x + 'px'; 758 colorCursor.style.top = y + 'px'; 759 760 // Update the color 761 setColorAtPosition(x, y); 762 763 // Make sure the marker is focused
764 colorMarker.focus(); 765 } 766 767 /** 768 * Update the color picker's input field and preview thumb. 769 * @param {Object} rgba Red, green, blue and alpha values. 770 * @param {Object} [hsva] Hue, saturation, value and alpha values. 771 */ 772 function updateColor(rgba, hsva) {if (rgba === void 0) {rgba = {};}if (hsva === void 0) {hsva = {};} 773 var format = settings.format; 774 775 for (var key in rgba) { 776 currentColor[key] = rgba[key]; 777 } 778 779 for (var _key in hsva) { 780 currentColor[_key] = hsva[_key]; 781 } 782 783 var hex = RGBAToHex(currentColor); 784 var opaqueHex = hex.substring(0, 7); 785 var hex_zero = (hex.substring(7) != '') ? hex.substring(7) : 'ff'; 786 787 colorMarker.style.color = opaqueHex; 788 alphaMarker.parentNode.style.color = opaqueHex; 789 alphaMarker.style.color = hex; 790 colorPreview.style.color = hex; 791 if(paletteBox.classList.contains('ready')) { 792 colorCurrent.style.color = hex; 793 paletteBox.classList.remove('ready'); 794 } 795 796 // Force repaint the color and alpha gradients as a workaround for a Google Chrome bug 797 colorArea.style.display = 'none'; 798 colorArea.offsetHeight; 799 colorArea.style.display = ''; 800 alphaMarker.nextElementSibling.style.display = 'none'; 801 alphaMarker.nextElementSibling.offsetHeight; 802 alphaMarker.nextElementSibling.style.display = ''; 803 804 if (format === 'mixed') { 805 format = currentColor.a === 1 ? 'hex' : 'rgb'; 806 } else if (format === 'auto') { 807 format = currentFormat; 808 } 809 810 alphaInput.value = alphaSlider.value; 811 hexInput.value = hex.slice(0,7); 812 813 switch (format) { 814 case 'hex': 815 colorValue.value = hex; 816 break; 817 case 'rgb': 818 colorValue.value = RGBAToStr(currentColor); 819 break; 820 case 'hsl': 821 colorValue.value = HSLAToStr(HSVAtoHSLA(currentColor)); 822 break; 823 } 824 825 // Select the current format in the format switcher 826 document.querySelector(".clr-format [value=\"" + format + "\"]").checked = true; 827 } 828 829 /** 830 * Set the hue when its slider is moved. 831 */ 832 function setHue() { 833 var hue = hueSlider.value * 1; 834 var x = colorMarker.style.left.replace('px', '') * 1; 835 var y = colorMarker.style.top.replace('px', '') * 1; 836 837 picker.style.color = "hsl(" + hue + ", 100%, 50%)"; 838 hueMarker.style.left = hue / 360 * 100 + "%"; 839 840 setColorAtPosition(x, y); 841 } 842 843 /** 844 * Set the alpha when its slider is moved. 845 */ 846 function setAlpha() { 847 var alpha = alphaSlider.value / 100; 848 849 if(alphaSlider.value > 0) { 850 $('#clr-color-comment').addClass('hide'); 851 $('.back-black').addClass('hide'); 852 } else { 853 $('#clr-color-comment').removeClass('hide'); 854 $('.back-black').removeClass('hide'); 855 } 856 857 alphaMarker.style.left = alpha * 100 + "%"; 858 updateColor({ a: alpha }); 859 // pickColor(); 860 } 861 function setAlphaInput() { 862 if(alphaInput.value < 1 || !alphaInput.value) alphaInput.value = 0; 863 else if(alphaInput.value > 100) alphaInput.value = 100; 864 865 if(alphaInput.value > 0) { 866 $('#clr-color-comment, .back-black').addClass('hide'); 867 } else { 868 $('#clr-color-comment, .back-black').removeClass('hide'); 869 } 870 871 var alpha = alphaInput.value / 100; 872 873 alphaSlider.value = alphaInput.value; 874 alphaMarker.style.left = alpha * 100 + "%"; 875 updateColor({ a: alpha }); 876 // pickColor(); 877 } 878 879 880 /** 881 * Convert HSVA to RGBA. 882 * @param {object} hsva Hue, saturation, value and alpha values. 883 * @return {object} Red, green, blue and alpha values. 884 */ 885 function HSVAtoRGBA(hsva) { 886 var saturation = hsva.s / 100; 887 var value = hsva.v / 100; 888 var chroma = saturation * value; 889 var hueBy60 = hsva.h / 60; 890 var x = chroma * (1 - Math.abs(hueBy60 % 2 - 1)); 891 var m = value - chroma; 892 893 chroma = chroma + m; 894 x = x + m; 895 896 var index = Math.floor(hueBy60) % 6; 897 var red = [chroma, x, m, m, x, chroma][index]; 898 var green = [x, chroma, chroma, x, m, m][index]; 899 var blue = [m, m, x, chroma, chroma, x][index]; 900 901 return { 902 r: Math.round(red * 255), 903 g: Math.round(green * 255), 904 b: Math.round(blue * 255), 905 a: hsva.a }; 906 907 } 908 909 /** 910 * Convert HSVA to HSLA. 911 * @param {object} hsva Hue, saturation, value and alpha values. 912 * @return {object} Hue, saturation, lightness and alpha values. 913 */ 914 function HSVAtoHSLA(hsva) { 915 var value = hsva.v / 100; 916 var lightness = value * (1 - hsva.s / 100 / 2); 917 var saturation; 918 919 if (lightness > 0 && lightness < 1) { 920 saturation = Math.round((value - lightness) / Math.min(lightness, 1 - lightness) * 100); 921 } 922 923 return { 924 h: hsva.h, 925 s: saturation || 0, 926 l: Math.round(lightness * 100), 927 a: hsva.a }; 928 929 } 930 931 /** 932 * Convert RGBA to HSVA. 933 * @param {object} rgba Red, green, blue and alpha values. 934 * @return {object} Hue, saturation, value and alpha values. 935 */ 936 function RGBAtoHSVA(rgba) { 937 var red = rgba.r / 255; 938 var green = rgba.g / 255; 939 var blue = rgba.b / 255; 940 var xmax = Math.max(red, green, blue); 941 var xmin = Math.min(red, green, blue); 942 var chroma = xmax - xmin; 943 var value = xmax; 944 var hue = 0; 945 var saturation = 0; 946 947 if (chroma) { 948 if (xmax === red) {hue = (green - blue) / chroma;} 949 if (xmax === green) {hue = 2 + (blue - red) / chroma;} 950 if (xmax === blue) {hue = 4 + (red - green) / chroma;} 951 if (xmax) {saturation = chroma / xmax;} 952 } 953 954 hue = Math.floor(hue * 60); 955 956 return { 957 h: hue < 0 ? hue + 360 : hue, 958 s: Math.round(saturation * 100), 959 v: Math.round(value * 100), 960 a: rgba.a }; 961 962 } 963 964 /** 965 * Parse a string to RGBA. 966 * @param {string} str String representing a color. 967 * @return {object} Red, green, blue and alpha values. 968 */ 969 function strToRGBA(str) { 970 var regex = /^((rgba)|rgb)[\D]+([\d.]+)[\D]+([\d.]+)[\D]+([\d.]+)[\D]*?([\d.]+|$)/i; 971 var match, rgba; 972 973 // Default to black for invalid color strings 974 ctx.fillStyle = '#000'; 975 976 // Use canvas to convert the string to a valid color string 977 ctx.fillStyle = str; 978 match = regex.exec(ctx.fillStyle); 979 980 if (match) { 981 rgba = { 982 r: match[3] * 1, 983 g: match[4] * 1, 984 b: match[5] * 1, 985 a: match[6] * 1 }; 986 987 988 // Workaround to mitigate a Chromium bug where the alpha value is rounded incorrectly 989 rgba.a = +rgba.a.toFixed(2); 990 991 } else { 992 match = ctx.fillStyle.replace('#', '').match(/.{2}/g).map(function (h) {return parseInt(h, 16);}); 993 rgba = { 994 r: match[0], 995 g: match[1], 996 b: match[2], 997 a: 1 }; 998 999 } 1000 1001 return rgba; 1002 } 1003 1004 /** 1005 * Convert RGBA to Hex. 1006 * @param {object} rgba Red, green, blue and alpha values. 1007 * @return {string} Hex color string. 1008 */ 1009 function RGBAToHex(rgba) { 1010 var R = rgba.r.toString(16); 1011 var G = rgba.g.toString(16); 1012 var B = rgba.b.toString(16); 1013 var A = ''; 1014
1015 if (rgba.r < 16) { 1016 R = '0' + R; 1017 } 1018 1019 if (rgba.g < 16) { 1020 G = '0' + G; 1021 } 1022 1023 if (rgba.b < 16) { 1024 B = '0' + B; 1025 } 1026 1027 if (settings.alpha && (rgba.a < 1 || settings.forceAlpha)) { 1028 var alpha = rgba.a * 255 | 0; 1029 A = alpha.toString(16); 1030 1031 if (alpha < 16) { 1032 A = '0' + A; 1033 } 1034 } 1035 1036 return '#' + R + G + B + A; 1037 } 1038 1039 /** 1040 * Convert RGBA values to a CSS rgb/rgba string. 1041 * @param {object} rgba Red, green, blue and alpha values. 1042 * @return {string} CSS color string. 1043 */ 1044 function RGBAToStr(rgba) { 1045 if (!settings.alpha || rgba.a === 1 && !settings.forceAlpha) { 1046 return "rgb(" + rgba.r + ", " + rgba.g + ", " + rgba.b + ")"; 1047 } else { 1048 return "rgba(" + rgba.r + ", " + rgba.g + ", " + rgba.b + ", " + rgba.a + ")"; 1049 } 1050 } 1051 1052 /** 1053 * Convert HSLA values to a CSS hsl/hsla string. 1054 * @param {object} hsla Hue, saturation, lightness and alpha values. 1055 * @return {string} CSS color string. 1056 */ 1057 function HSLAToStr(hsla) { 1058 if (!settings.alpha || hsla.a === 1 && !settings.forceAlpha) { 1059 return "hsl(" + hsla.h + ", " + hsla.s + "%, " + hsla.l + "%)"; 1060 } else { 1061 return "hsla(" + hsla.h + ", " + hsla.s + "%, " + hsla.l + "%, " + hsla.a + ")"; 1062 } 1063 } 1064 1065 /** 1066 * Init the color picker. 1067 */ 1068 function init() { 1069 // Render the UI 1070 var checkEditorMode = (typeof PAGE_MODE != 'undefined' && PAGE_MODE == 'c'); 1071 var alphaInfoLabel = checkEditorMode ? _coloris_label[(LANG === 'ko') ? 'ko' : 'en'].alpha_info : ''; 1072 1073 container = undefined; 1074 picker_backdrop = document.createElement('div'); 1075 picker_backdrop.setAttribute('id', 'clr-picker-backdrop'); 1076 picker_backdrop.className = 'clr-picker-backdrop'; 1077 1078 picker = document.createElement('div'); 1079 picker.setAttribute('id', 'clr-picker'); 1080 picker.className = 'clr-picker'; 1081 picker.innerHTML = ` 1082 <div class="clr-body"> 1083 <div class="clr-section top"> 1084 <div id="clr-color-area" class="clr-gradient" role="application" aria-label="${settings.a11y.instruction}"> 1085 <div id="clr-color-marker" class="clr-marker" tabindex="0"></div> 1086 <div id="clr-color-cursor" class="clr-cursor" tabindex="-1"></div> 1087 <div class="back-black"></div> 1088 <div id="clr-color-comment" class="clr-comment" tabindex="-2">${alphaInfoLabel}</div> 1089 </div> 1090 <div class="clr-hue"> 1091 <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}"> 1092 <div id="clr-hue-marker" class="clr-hue-marker"></div> 1093 </div> 1094 <div class="clr-color-info hex"> 1095 <div class="info-label"> 1096 ${settings.a11y.hexLabel} 1097 </div> 1098 <div class="info-val"> 1099 <input id="clr-hex-value" name="clr-hex-value" class="clr-hex-value" type="text" value="" aria-label="${settings.a11y.hexInput}"> 1100 </div> 1101 </div> 1102 <div class="clr-alpha"> 1103 <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}"> 1104 <div id="clr-alpha-marker" class="clr-alpha-marker"></div> 1105 <span></span> 1106 </div> 1107 <div class="clr-color-info alpha"> 1108 <div class="info-label"> 1109 ${settings.a11y.alphaLabel} 1110 </div> 1111 <div class="info-val"> 1112 <input id="clr-alpha-value" name="clr-alpha-value" class="clr-alpha-value" type="number" value="" aria-label="${settings.a11y.alphaInput}"> 1113 </div> 1114 </div> 1115 </div> 1116 <div class="clr-section center"> 1117 <div id="clr-format" class="clr-format"> 1118 <fieldset class="clr-segmented"> 1119 <legend>${settings.a11y.format}</legend> 1120 <input id="clr-f1" type="radio" name="clr-format" value="hex"> 1121 <label for="clr-f1">Hex</label> 1122 <input id="clr-f2" type="radio" name="clr-format" value="rgb"> 1123 <label for="clr-f2">RGB</label> 1124 <input id="clr-f3" type="radio" name="clr-format" value="hsl"> 1125 <label for="clr-f3">HSL</label>
1126 <span></span> 1127 </fieldset> 1128 </div> 1129 <div class="clr-color-info color hide"> 1130 <div class="info-label"> 1131 ${settings.a11y.inputLabel} 1132 <span class="bc-tooltip colorisguide">${tooltipSVG('top','',`${_coloris_label[(LANG === 'ko') ? 'ko' : 'en'].guide}`,'')}</span> 1133 </div> 1134 <div class="info-val"> 1135 <input id="clr-color-value" name="clr-color-value" class="clr-color" type="text" value="" spellcheck="false" aria-label="${settings.a11y.input}"> 1136 </div> 1137 </div> 1138 <div id="clr-swatches" class="clr-swatches"></div> 1139 </div> 1140 <div class="clr-section bottom"> 1141 <div class="clr-palette-box ready" id="clr-palette-box"> 1142 <div id="clr-color-preview" class="clr-preview"></div> 1143 <div id="clr-color-current" class="clr-current"></div> 1144 </div> 1145 <div class="clr-btn-box" id="clr-btn-box"> 1146 <button type="button" id="clr-clear" class="clr-clear" aria-label="${settings.a11y.clear}">${settings.clearLabel}</button> 1147 <button type="button" id="clr-cancel" class="clr-cancel" aria-label="${settings.a11y.cancel}">${settings.cancelLabel}</button> 1148 <button type="button" id="clr-close" class="clr-close" aria-label="${settings.a11y.close}">${settings.closeLabel}</button> 1149 </div> 1150 </div> 1151 <span id="clr-open-label" hidden>${settings.a11y.open}</span> 1152 <span id="clr-swatch-label" hidden>${settings.a11y.swatch}</span> 1153 </div> 1154 `; 1155 1156 /* 1157 picker.innerHTML = 1158 "<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=\"" + 1159 settings.a11y.instruction + "\">") + 1160 '<div id="clr-color-marker" class="clr-marker" tabindex="0"></div>' + 1161 '</div>' + 1162 '<div class="clr-hue">' + ("<input id=\"clr-hue-slider\" name=\"clr-hue-slider\" type=\"range\" min=\"0\" max=\"360\" step=\"1\" aria-label=\"" + 1163 settings.a11y.hueSlider + "\">") + 1164 '<div id="clr-hue-marker"></div>' + 1165 '</div>' + 1166 '<div class="clr-alpha">' + ("<input id=\"clr-alpha-slider\" name=\"clr-alpha-slider\" type=\"range\" min=\"0\" max=\"100\" step=\"1\" aria-label=\"" + 1167 settings.a11y.alphaSlider + "\">") + 1168 '<div id="clr-alpha-marker"></div>' + 1169 '<span></span>' + 1170 '</div>' + 1171 '<div id="clr-format" class="clr-format">' + 1172 '<fieldset class="clr-segmented">' + ("<legend>" + 1173 settings.a11y.format + "</legend>") + 1174 '<input id="clr-f1" type="radio" name="clr-format" value="hex">' + 1175 '<label for="clr-f1">Hex</label>' + 1176 '<input id="clr-f2" type="radio" name="clr-format" value="rgb">' + 1177 '<label for="clr-f2">RGB</label>' + 1178 '<input id="clr-f3" type="radio" name="clr-format" value="hsl">' + 1179 '<label for="clr-f3">HSL</label>' + 1180 '<span></span>' + 1181 '</fieldset>' + 1182 '</div>' + 1183 '<div id="clr-swatches" class="clr-swatches"></div>' + ("<button type=\"button\" id=\"clr-clear\" class=\"clr-clear\" aria-label=\"" + 1184 settings.a11y.clear + "\">" + settings.clearLabel + "</button>") + 1185 '<div id="clr-color-preview" class="clr-preview">' + ("<button type=\"button\" id=\"clr-close\" class=\"clr-close\" aria-label=\"" + 1186 settings.a11y.close + "\">" + settings.closeLabel + "</button>") + 1187 '</div>' + ("<span id=\"clr-open-label\" hidden>" + 1188 settings.a11y.open + "</span>") + ("<span id=\"clr-swatch-label\" hidden>" + 1189 settings.a11y.swatch + "</span>"); 1190 */ 1191 1192 1193 // Append the color picker to the DOM 1194 document.body.appendChild(picker); 1195 document.body.appendChild(picker_backdrop); 1196 1197 // Reference the UI elements 1198 colorArea = getEl('clr-color-area'); 1199 colorMarker = getEl('clr-color-marker'); 1200 colorCursor = getEl('clr-color-cursor'); 1201 btnBox = getEl('clr-btn-box'); 1202 clearButton = getEl('clr-clear'); 1203 cancelButton = getEl('clr-cancel'); 1204 closeButton = getEl('clr-close'); 1205 paletteBox = getEl('clr-palette-box'); 1206 colorPreview = getEl('clr-color-preview'); 1207 colorCurrent = getEl('clr-color-current'); 1208 colorValue = getEl('clr-color-value'); 1209 hueSlider = getEl('clr-hue-slider'); 1210 hueMarker = getEl('clr-hue-marker'); 1211 hexInput = getEl('clr-hex-value'); 1212 alphaInput = getEl('clr-alpha-value'); 1213 alphaSlider = getEl('clr-alpha-slider'); 1214 alphaMarker = getEl('clr-alpha-marker'); 1215 1216 // Bind the picker to the default selector 1217 bindFields(settings.el); 1218 wrapFields(settings.el); 1219 1220 addListener(picker_backdrop, 'mousedown', function (event) { 1221 closePicker(true); 1222 }); 1223 1224 addListener(picker, 'mousedown', function (event) { 1225 picker.classList.remove('clr-keyboard-nav'); 1226 event.stopPropagation(); 1227 }); 1228 1229 addListener(colorArea, 'mousedown', function (event) { 1230 addListener(document, 'mousemove', moveMarker); 1231 }); 1232 1233 addListener(colorArea, 'touchstart', function (event) { 1234 document.addEventListener('touchmove', moveMarker, { passive: false }); 1235 }); 1236 1237 addListener(colorArea, 'mousemove', function (event) { 1238 var tmpColorCursor = document.querySelector('.clr-cursor'); 1239 tmpColorCursor.style.top = (event.pageY - Math.round($('#clr-color-area').offset().top) + 1) + 'px'; 1240 tmpColorCursor.style.left = (event.pageX - Math.round($('#clr-color-area').offset().left) - 1) + 'px'; 1241 }); 1242 1243 addListener(colorMarker, 'mousedown', function (event) { 1244 addListener(document, 'mousemove', moveMarker); 1245 }); 1246 1247 addListener(colorMarker, 'touchstart', function (event) { 1248 document.addEventListener('touchmove', moveMarker, { passive: false }); 1249 }); 1250 1251 addListener(colorValue, 'change', function (event) { 1252 var value = colorValue.value; 1253 1254 if (currentEl || settings.inline) { 1255 var color = value === '' ? value : setColorFromStr(value); 1256 pickColor(color); 1257 } 1258 1259 $('#clr-color-comment').addClass('hide'); 1260 $('.back-black').addClass('hide'); 1261 if(alphaInput.value == 0) { 1262 $('#clr-color-comment').removeClass('hide'); 1263 $('.back-black').removeClass('hide'); 1264 } 1265 });
1266 addListener(colorValue, 'keyup', function(e) { if(e.which == 13) { $(this).closest('.clr-picker').find('.clr-close').click(); } }); 1267 1268 addListener(clearButton, 'click', function (event) { 1269 pickColor(''); 1270 closePicker(); 1271 }); 1272 1273 addListener(closeButton, 'click', function (event) { 1274 pickColor(); 1275 closePicker(); 1276 }); 1277 1278 addListener(cancelButton, 'click', function (event) { 1279 closePicker(true); 1280 }); 1281 1282 addListener(getEl('clr-format'), 'click', '.clr-format input', function (event) { 1283 currentFormat = event.target.value; 1284 updateColor(); 1285 pickColor(); 1286 }); 1287 1288 addListener(picker, 'click', '.clr-swatches button', function (event) { 1289 setColorFromStr(event.target.textContent); 1290 // pickColor(); 1291 1292 if (settings.swatchesOnly) { 1293 closePicker(); 1294 } 1295 }); 1296 1297 addListener(document, 'mouseup', function (event) { 1298 document.removeEventListener('mousemove', moveMarker); 1299 }); 1300 1301 addListener(document, 'touchend', function (event) { 1302 document.removeEventListener('touchmove', moveMarker); 1303 }); 1304 1305 addListener(document, 'mousedown', function (event) { 1306 keyboardNav = false;
1307 picker.classList.remove('clr-keyboard-nav'); 1308 closePicker(); 1309 }); 1310 1311 addListener(document, 'keydown', function (event) { 1312 var key = event.key; 1313 var target = event.target; 1314 var shiftKey = event.shiftKey; 1315 var navKeys = ['Tab', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight']; 1316 1317 if (key === 'Escape') { 1318 closePicker(true); 1319 1320 // Display focus rings when using the keyboard 1321 } else if (navKeys.includes(key)) { 1322 keyboardNav = true; 1323 picker.classList.add('clr-keyboard-nav'); 1324 } 1325 1326 // Trap the focus within the color picker while it's open 1327 if (key === 'Tab' && target.matches('.clr-picker *')) { 1328 var focusables = getFocusableElements(); 1329 var firstFocusable = focusables.shift(); 1330 var lastFocusable = focusables.pop(); 1331 1332 if (shiftKey && target === firstFocusable) { 1333 lastFocusable.focus(); 1334 event.preventDefault(); 1335 } else if (!shiftKey && target === lastFocusable) { 1336 firstFocusable.focus(); 1337 event.preventDefault(); 1338 } 1339 } 1340 }); 1341 1342 addListener(document, 'click', '.clr-field button', function (event) { 1343 // Reset any previously set per-instance options 1344 if (hasInstance) { 1345 resetVirtualInstance(); 1346 } 1347 1348 // Open the color picker 1349 event.target.nextElementSibling.dispatchEvent(new Event('click', { bubbles: true })); 1350 }); 1351 1352 addListener(colorMarker, 'keydown', function (event) { 1353 var movements = { 1354 ArrowUp: [0, -1], 1355 ArrowDown: [0, 1], 1356 ArrowLeft: [-1, 0], 1357 ArrowRight: [1, 0] }; 1358 1359 1360 if (Object.keys(movements).includes(event.key)) { 1361 moveMarkerOnKeydown.apply(void 0, movements[event.key]); 1362 event.preventDefault(); 1363 } 1364 }); 1365 1366 addListener(colorArea, 'click', moveMarker); 1367 addListener(hueSlider, 'input', setHue); 1368 1369 addListener(alphaInput, 'input', setAlphaInput); 1370 addListener(alphaInput, 'keyup', function(e) { if(e.which == 13) { $(this).closest('.clr-picker').find('.clr-close').click(); } }); 1371 addListener(alphaSlider, 'input', setAlpha); 1372 1373 addListener(hexInput, 'change', function (event) { 1374 var hex6 = hexInput.value, 1375 alpha = (settings.alpha) ? alphaInput.value : 100, 1376 new_color = getChangeColorVal([hex6,'a',alpha / 100]); 1377 1378 if (currentEl || settings.inline) { 1379 var color = new_color === '' ? hex6 : setColorFromStr(new_color); 1380 pickColor(color); 1381 } 1382 }); 1383 addListener(hexInput, 'keyup', function(e) { if(e.which == 13) { $(this).closest('.clr-picker').find('.clr-close').click(); } }); 1384 1385 } 1386 1387 /** 1388 * Return a list of focusable elements within the color picker. 1389 * @return {array} The list of focusable DOM elemnts. 1390 */ 1391 function getFocusableElements() { 1392 var controls = Array.from(picker.querySelectorAll('input, button')); 1393 var focusables = controls.filter(function (node) {return !!node.offsetWidth;}); 1394 1395 return focusables; 1396 } 1397 1398 /** 1399 * Shortcut for getElementById to optimize the minified JS. 1400 * @param {string} id The element id. 1401 * @return {object} The DOM element with the provided id. 1402 */ 1403 function getEl(id) { 1404 return document.getElementById(id); 1405 } 1406 1407 /** 1408 * Shortcut for addEventListener to optimize the minified JS. 1409 * @param {object} context The context to which the listener is attached. 1410 * @param {string} type Event type. 1411 * @param {(string|function)} selector Event target if delegation is used, event handler if not. 1412 * @param {function} [fn] Event handler if delegation is used. 1413 */ 1414 function addListener(context, type, selector, fn) { 1415 var matches = Element.prototype.matches || Element.prototype.msMatchesSelector; 1416 1417 // Delegate event to the target of the selector 1418 if (typeof selector === 'string') { 1419 context.addEventListener(type, function (event) { 1420 if (matches.call(event.target, selector)) { 1421 fn.call(event.target, event); 1422 } 1423 }); 1424 1425 // If the selector is not a string then it's a function 1426 // in which case we need a regular event listener 1427 } else { 1428 fn = selector;
1429 context.addEventListener(type, fn); 1430 } 1431 } 1432 1433 /** 1434 * Call a function only when the DOM is ready. 1435 * @param {function} fn The function to call. 1436 * @param {array} [args] Arguments to pass to the function. 1437 */ 1438 function DOMReady(fn, args) { 1439 args = args !== undefined ? args : []; 1440 1441 if($.inArray(fn.name, checkReturnFuncArr) > -1) return fn(args); 1442 1443 if (document.readyState !== 'loading') { 1444 fn.apply(void 0, args); 1445 } else { 1446 document.addEventListener('DOMContentLoaded', function () { 1447 fn.apply(void 0, args); 1448 }); 1449 } 1450 } 1451 1452 1453 function getColorSelectorPnInfo(args_arr) { 1454 var css = args_arr[0], 1455 elname = (typeof args_arr[1] != 'undefined') ? args_arr[1] : '', 1456 selector = (typeof args_arr[2] != 'undefined') ? args_arr[2] : '', 1457 pn = (typeof args_arr[3] != 'undefined') ? args_arr[3] : '', 1458 withcss = (typeof args_arr[4] != 'undefined') ? args_arr[4] : '', 1459 result = {'selector':selector, 'pn':pn, 'color':''} 1460 1461 var this_selector = '', 1462 this_pn = '', 1463 this_color = '', 1464 this_css = {}; 1465 1466 var elnameRegex = new RegExp('^\.' + elname), 1467 checkSelectorWidthElname = (selector.match(elnameRegex) != null) ? true : false; 1468 1469 $.each(selector.split(','), function(i,s) { 1470 if(i > 0) this_selector += ','; 1471 this_selector += (checkSelectorWidthElname) ? s.trim() : '.' + elname + ' ' + s.trim(); 1472 1473 var tmp_pn = pn.split(','), 1474 tmp_s = s.trim(), 1475 tmp_changepn = s.match(/^(.*?)(?=\([^)]*\)$)/); 1476 if(tmp_changepn != null) { 1477 tmp_pn = s.substring(tmp_changepn[0].length + 1, s.length - 1).split('/'); 1478 tmp_s = tmp_changepn[0].trim(); 1479 } 1480 1481 var tmp_selector = (checkSelectorWidthElname) ? tmp_s : '.' + elname + ' ' + tmp_s, 1482 tmp_style = style.get(css,tmp_selector); 1483 if(typeof this_css[tmp_selector] == 'undefined') this_css[tmp_selector] = {}; 1484 1485 if(withcss) { 1486 $.each(withcss.split(','), function(i,v) { 1487 if(!v) return; 1488 1489 if($.inArray(v, ['fill','color','background','background-color','border-color','border','border-top','border-bottom','border-left','border-right']) > -1) { 1490 if(tmp_pn.indexOf(v) < 0) tmp_pn.push(v); 1491 return; 1492 } 1493 1494 var tmp_v = ''; 1495 switch(v) { 1496 case 'font-family': tmp_v = tmp_style.txName; break; 1497 case 'font-size': tmp_v = tmp_style.txSize; break; 1498 default: tmp_v = style.getCssProperty(css,tmp_selector,v); break; 1499 } 1500 1501 this_css[tmp_selector][v] = {'val': tmp_v}; 1502 }); 1503 } 1504 1505 $.each(tmp_pn, function(i,v) { 1506 var tmp_color = ''; 1507 switch(v) { 1508 case 'fill': tmp_color = tmp_style.fill; break; 1509 case 'color': tmp_color = tmp_style.txColor; break; 1510 case 'background': 1511 case 'background-color': tmp_color = tmp_style.bgColor; break; 1512 case 'border-color': 1513 case 'border': 1514 case 'border-top': 1515 case 'border-bottom': 1516 case 'border-left': 1517 case 'border-right': tmp_color = tmp_style.borderColor; break; 1518 default: break; 1519 } 1520 1521 if(v) { 1522 this_css[tmp_selector][v] = { 1523 'val': style.getCssProperty(css,tmp_selector,v), 1524 'color': Coloris.getColorInfo(tmp_color,'org'), 1525 }; 1526 1527 if(typeof this_css[tmp_selector][v]['val'] != 'string') this_css[tmp_selector][v]['val'] = this_css[tmp_selector][v]['val'].pop(); 1528 1529 if(pn.split(',').length > 1 && pn.split(',').indexOf(v) > -1) { 1530 this_css[tmp_selector][v]['checkPass'] = (this_css[tmp_selector][v]['color'] == '' && $.inArray(this_css[tmp_selector][v]['val'], ['initial','inherit']) > -1) ? true : false; 1531 } 1532 } 1533 1534 1535 if(i == 0) { 1536 this_pn = v; 1537 this_color = tmp_color; 1538 } 1539 }); 1540 }); 1541 1542 return { 1543 'selector': this_selector, 1544 'pn': this_pn, 1545 'color': this_color, 1546 'css': this_css, 1547 } 1548 } 1549 1550 function getColorInfo(args_arr) { 1551 var tmp_str = args_arr[0], 1552 return_type = (typeof args_arr[1] != 'undefined' && args_arr[1]) ? args_arr[1] : 'hex8'; 1553 1554 var str = (typeof tmp_str == 'string') ? tmp_str : tmp_str.pop(), 1555 colorRegex = getColorRegex(), 1556 tmp_matches = str.match(colorRegex); 1557 if(tmp_matches != null) str = tmp_matches.pop(); 1558 if(return_type == 'org') return str; 1559 1560 var this_rgba = strToRGBA(str), 1561 this_hex = RGBAToHex(this_rgba); 1562 1563 if(return_type == 'hex' || return_type == 'rgb') { 1564 this_rgba['a'] = 1; 1565 return (return_type == 'rgb') ? RGBAToStr(this_rgba) : RGBAToHex(this_rgba); 1566 } 1567 else if(return_type == 'rgba') return RGBAToStr(this_rgba); 1568 else if(return_type == 'alpha') return this_rgba['a']; 1569 else return this_hex; 1570 } 1571 1572 function getColorRegex() {
1573 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); 1574 } 1575 1576 function getChangeColorVal(args_arr) { 1577 var str = args_arr[0], 1578 change_key = (typeof args_arr[1] != 'undefined' && args_arr[1]) ? args_arr[1] : '', 1579 change_val = (typeof args_arr[2] != 'undefined' && args_arr[2]) ? args_arr[2] : ''; 1580 1581 var this_rgba = strToRGBA(str), 1582 this_hex = RGBAToHex(this_rgba); 1583 if(change_key == '' && change_val == '') return this_hex.substring(0, 7); 1584 if(change_key == 'rgb_str') return this_rgba.r+','+this_rgba.g+','+this_rgba.b; 1585 1586 if(change_key && typeof this_rgba[change_key] != 'undefined') { 1587 this_rgba[change_key] = change_val * 1; 1588 } 1589 1590 var org_alpha = settings.alpha; 1591 if(change_key == 'a') settings.alpha = true; 1592 var hex = RGBAToHex(this_rgba); 1593 if(change_key == 'a') settings.alpha = org_alpha; 1594 1595 if(this_rgba.a < 1) return 'rgba('+this_rgba.r+','+this_rgba.g+','+this_rgba.b+','+this_rgba.a+')'; 1596 else return hex; 1597 // opaqueHex = hex.substring(0, 7); 1598 } 1599 1600 1601 // Polyfill for Nodelist.forEach 1602 if (NodeList !== undefined && NodeList.prototype && !NodeList.prototype.forEach) { 1603 NodeList.prototype.forEach = Array.prototype.forEach; 1604 } 1605 1606 // Expose the color picker to the global scope 1607 window.Coloris = function () { 1608 var methods = { 1609 set: configure, 1610 wrap: wrapFields, 1611 close: closePicker, 1612 setInstance: setVirtualInstance, 1613 removeInstance: removeVirtualInstance, 1614 updatePosition: updatePickerPosition, 1615 ready: DOMReady 1616 }; 1617 1618 $.each(checkUsedFuncArr, function(i,fname) { 1619 methods[fname] = eval(fname); 1620 }); 1621 1622 $.each(checkReturnFuncArr, function(i,fname) { 1623 methods[fname] = eval(fname); 1624 }); 1625 1626 function Coloris(options) { 1627 DOMReady(function () { 1628 if (options) { 1629 if (typeof options === 'string') { 1630 bindFields(options); 1631 } else { 1632 configure(options); 1633 } 1634 } 1635 }); 1636 } 1637 1638 var _loop2 = function _loop2(key) { 1639 Coloris[key] = function () { 1640 for (var _len = arguments.length, args = new Array(_len), _key2 = 0; _key2 < _len; _key2++) { 1641 args[_key2] = arguments[_key2]; 1642 } 1643 1644 if($.inArray(key, checkReturnFuncArr) > -1) return DOMReady(methods[key], args); 1645 else DOMReady(methods[key], args); 1646 }; 1647 }; 1648 1649 1650 for (var key in methods) { 1651 _loop2(key); 1652 } 1653 1654 return Coloris; 1655 }(); 1656 1657 // Init the color picker when the DOM is ready 1658 DOMReady(init); 1659 1660 })(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.