[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/media/system/js/fields/ -> joomla-field-simple-color.js (source)

   1  /**
   2   * Based on:
   3   * Very simple jQuery Color Picker
   4   * Copyright (C) 2012 Tanguy Krotoff
   5   * Licensed under the MIT license
   6   *
   7   * ADAPTED BY: Dimitris Grammatikogiannis
   8   *
   9   * MIT License
  10   *
  11   * Permission is hereby granted, free of charge, to any person obtaining
  12   * a copy of this software and associated documentation files (the
  13   * "Software"), to deal in the Software without restriction, including
  14   * without limitation the rights to use, copy, modify, merge, publish,
  15   * distribute, sublicense, and/or sell copies of the Software, and to
  16   * permit persons to whom the Software is furnished to do so, subject to
  17   * the following conditions:
  18   *
  19   * The above copyright notice and this permission notice shall be
  20   * included in all copies or substantial portions of the Software.
  21   *
  22   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26   * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27   * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28   * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29   */
  30  (customElements => {
  31    const KEYCODE = {
  32      TAB: 9,
  33      ESC: 27
  34    };
  35    const colorNames = {
  36      aliceblue: '#f0f8ff',
  37      antiquewhite: '#faebd7',
  38      aqua: '#00ffff',
  39      aquamarine: '#7fffd4',
  40      azure: '#f0ffff',
  41      beige: '#f5f5dc',
  42      bisque: '#ffe4c4',
  43      black: '#000000',
  44      blanchedalmond: '#ffebcd',
  45      blue: '#0000ff',
  46      blueviolet: '#8a2be2',
  47      brown: '#a52a2a',
  48      burlywood: '#deb887',
  49      cadetblue: '#5f9ea0',
  50      chartreuse: '#7fff00',
  51      chocolate: '#d2691e',
  52      coral: '#ff7f50',
  53      cornflowerblue: '#6495ed',
  54      cornsilk: '#fff8dc',
  55      crimson: '#dc143c',
  56      cyan: '#00ffff',
  57      darkblue: '#00008b',
  58      darkcyan: '#008b8b',
  59      darkgoldenrod: '#b8860b',
  60      darkgray: '#a9a9a9',
  61      darkgreen: '#006400',
  62      darkgrey: '#a9a9a9',
  63      darkkhaki: '#bdb76b',
  64      darkmagenta: '#8b008b',
  65      darkolivegreen: '#556b2f',
  66      darkorange: '#ff8c00',
  67      darkorchid: '#9932cc',
  68      darkred: '#8b0000',
  69      darksalmon: '#e9967a',
  70      darkseagreen: '#8fbc8f',
  71      darkslateblue: '#483d8b',
  72      darkslategray: '#2f4f4f',
  73      darkslategrey: '#2f4f4f',
  74      darkturquoise: '#00ced1',
  75      darkviolet: '#9400d3',
  76      deeppink: '#ff1493',
  77      deepskyblue: '#00bfff',
  78      dimgray: '#696969',
  79      dimgrey: '#696969',
  80      dodgerblue: '#1e90ff',
  81      firebrick: '#b22222',
  82      floralwhite: '#fffaf0',
  83      forestgreen: '#228b22',
  84      fuchsia: '#ff00ff',
  85      gainsboro: '#dcdcdc',
  86      ghostwhite: '#f8f8ff',
  87      gold: '#ffd700',
  88      goldenrod: '#daa520',
  89      gray: '#808080',
  90      green: '#008000',
  91      greenyellow: '#adff2f',
  92      grey: '#808080',
  93      honeydew: '#f0fff0',
  94      hotpink: '#ff69b4',
  95      indianred: '#cd5c5c',
  96      indigo: '#4b0082',
  97      ivory: '#fffff0',
  98      khaki: '#f0e68c',
  99      lavender: '#e6e6fa',
 100      lavenderblush: '#fff0f5',
 101      lawngreen: '#7cfc00',
 102      lemonchiffon: '#fffacd',
 103      lightblue: '#add8e6',
 104      lightcoral: '#f08080',
 105      lightcyan: '#e0ffff',
 106      lightgoldenrodyellow: '#fafad2',
 107      lightgray: '#d3d3d3',
 108      lightgreen: '#90ee90',
 109      lightgrey: '#d3d3d3',
 110      lightpink: '#ffb6c1',
 111      lightsalmon: '#ffa07a',
 112      lightseagreen: '#20b2aa',
 113      lightskyblue: '#87cefa',
 114      lightslategray: '#778899',
 115      lightslategrey: '#778899',
 116      lightsteelblue: '#b0c4de',
 117      lightyellow: '#ffffe0',
 118      lime: '#00ff00',
 119      limegreen: '#32cd32',
 120      linen: '#faf0e6',
 121      magenta: '#ff00ff',
 122      maroon: '#800000',
 123      mediumaquamarine: '#66cdaa',
 124      mediumblue: '#0000cd',
 125      mediumorchid: '#ba55d3',
 126      mediumpurple: '#9370db',
 127      mediumseagreen: '#3cb371',
 128      mediumslateblue: '#7b68ee',
 129      mediumspringgreen: '#00fa9a',
 130      mediumturquoise: '#48d1cc',
 131      mediumvioletred: '#c71585',
 132      midnightblue: '#191970',
 133      mintcream: '#f5fffa',
 134      mistyrose: '#ffe4e1',
 135      moccasin: '#ffe4b5',
 136      navajowhite: '#ffdead',
 137      navy: '#000080',
 138      oldlace: '#fdf5e6',
 139      olive: '#808000',
 140      olivedrab: '#6b8e23',
 141      orange: '#ffa500',
 142      orangered: '#ff4500',
 143      orchid: '#da70d6',
 144      palegoldenrod: '#eee8aa',
 145      palegreen: '#98fb98',
 146      paleturquoise: '#afeeee',
 147      palevioletred: '#db7093',
 148      papayawhip: '#ffefd5',
 149      peachpuff: '#ffdab9',
 150      peru: '#cd853f',
 151      pink: '#ffc0cb',
 152      plum: '#dda0dd',
 153      powderblue: '#b0e0e6',
 154      purple: '#800080',
 155      red: '#ff0000',
 156      rosybrown: '#bc8f8f',
 157      royalblue: '#4169e1',
 158      saddlebrown: '#8b4513',
 159      salmon: '#fa8072',
 160      sandybrown: '#f4a460',
 161      seagreen: '#2e8b57',
 162      seashell: '#fff5ee',
 163      sienna: '#a0522d',
 164      silver: '#c0c0c0',
 165      skyblue: '#87ceeb',
 166      slateblue: '#6a5acd',
 167      slategray: '#708090',
 168      slategrey: '#708090',
 169      snow: '#fffafa',
 170      springgreen: '#00ff7f',
 171      steelblue: '#4682b4',
 172      tan: '#d2b48c',
 173      teal: '#008080',
 174      thistle: '#d8bfd8',
 175      tomato: '#ff6347',
 176      turquoise: '#40e0d0',
 177      violet: '#ee82ee',
 178      wheat: '#f5deb3',
 179      white: '#ffffff',
 180      whitesmoke: '#f5f5f5',
 181      yellow: '#ffff00',
 182      yellowgreen: '#9acd32'
 183    };
 184  
 185    class JoomlaFieldSimpleColor extends HTMLElement {
 186      constructor() {
 187        super(); // Define some variables
 188  
 189        this.select = '';
 190        this.options = [];
 191        this.icon = '';
 192        this.panel = '';
 193        this.buttons = [];
 194        this.focusableElements = null;
 195        this.focusableSelectors = ['a[href]', 'area[href]', 'input:not([disabled])', 'select:not([disabled])', 'textarea:not([disabled])', 'button:not([disabled])', 'iframe', 'object', 'embed', '[contenteditable]', '[tabindex]:not([tabindex^="-"])'];
 196      }
 197  
 198      connectedCallback() {
 199        this.select = this.querySelector('select');
 200  
 201        if (!this.select) {
 202          throw new Error('Simple color field requires a select element');
 203        }
 204  
 205        this.options = [].slice.call(this.select.querySelectorAll('option'));
 206        this.select.classList.add('hidden'); // Build the pop up
 207  
 208        this.options.forEach(option => {
 209          let color = option.value;
 210          let clss = 'swatch';
 211  
 212          if (color === 'none') {
 213            clss += ' nocolor';
 214            color = 'transparent';
 215          }
 216  
 217          if (option.selected) {
 218            clss += ' active';
 219          }
 220  
 221          const el = document.createElement('button');
 222          el.setAttribute('class', clss);
 223          el.style.backgroundColor = color;
 224          el.setAttribute('type', 'button');
 225          const a11yColor = color === 'transparent' ? this.textTransp : this.getColorName(color);
 226          el.innerHTML = Joomla.sanitizeHtml(`<span class="visually-hidden">$a11yColor}</span>`);
 227          this.buttons.push(el);
 228        }); // Add a close button
 229  
 230        const close = document.createElement('button');
 231        close.setAttribute('class', 'btn-close');
 232        close.setAttribute('type', 'button');
 233        close.innerHTML = Joomla.sanitizeHtml(this.textClose);
 234        this.buttons.push(close);
 235        let color = this.select.value;
 236        let clss = '';
 237  
 238        if (color === 'none') {
 239          clss += ' nocolor';
 240          color = 'transparent';
 241        }
 242  
 243        this.icon = document.createElement('button');
 244  
 245        if (clss) {
 246          this.icon.setAttribute('class', clss);
 247        }
 248  
 249        const uniqueId = `simple-color-$Math.random().toString(36).substr(2, 10)}`;
 250        this.icon.setAttribute('type', 'button');
 251        this.icon.setAttribute('tabindex', '0');
 252        this.icon.style.backgroundColor = color;
 253        this.icon.innerHTML = Joomla.sanitizeHtml(`<span class="visually-hidden">$this.textSelect}</span>`);
 254        this.icon.id = uniqueId;
 255        this.select.insertAdjacentElement('beforebegin', this.icon);
 256        this.icon.addEventListener('click', this.show.bind(this));
 257        this.panel = document.createElement('div');
 258        this.panel.classList.add('simplecolors-panel');
 259        this.panel.setAttribute('aria-labelledby', uniqueId);
 260        this.hide = this.hide.bind(this);
 261        this.colorSelect = this.colorSelect.bind(this);
 262        this.buttons.forEach(el => {
 263          if (el.classList.contains('btn-close')) {
 264            el.addEventListener('click', this.hide);
 265          } else {
 266            el.addEventListener('click', this.colorSelect);
 267          }
 268  
 269          this.panel.insertAdjacentElement('beforeend', el);
 270        });
 271        this.appendChild(this.panel);
 272        this.focusableElements = [].slice.call(this.panel.querySelectorAll(this.focusableSelectors.join()));
 273        this.keys = this.keys.bind(this);
 274        this.hide = this.hide.bind(this);
 275        this.mousedown = this.mousedown.bind(this);
 276      }
 277  
 278      static get observedAttributes() {
 279        return ['text-select', 'text-color', 'text-close', 'text-transparent'];
 280      }
 281  
 282      get textSelect() {
 283        return this.getAttribute('text-select');
 284      }
 285  
 286      get textColor() {
 287        return this.getAttribute('text-color');
 288      }
 289  
 290      get textClose() {
 291        return this.getAttribute('text-close');
 292      }
 293  
 294      get textTransp() {
 295        return this.getAttribute('text-transparent');
 296      } // Show the panel
 297  
 298  
 299      show() {
 300        document.addEventListener('mousedown', this.hide);
 301        this.addEventListener('keydown', this.keys);
 302        this.panel.addEventListener('mousedown', this.mousedown);
 303        this.panel.setAttribute('data-open', '');
 304        const focused = this.panel.querySelector('button');
 305  
 306        if (focused) {
 307          focused.focus();
 308        }
 309      } // Hide panel
 310  
 311  
 312      hide() {
 313        document.removeEventListener('mousedown', this.hide, false);
 314        this.removeEventListener('keydown', this.keys);
 315  
 316        if (this.panel.hasAttribute('data-open')) {
 317          this.panel.removeAttribute('data-open');
 318        }
 319  
 320        this.icon.focus();
 321      }
 322  
 323      colorSelect(e) {
 324        let color = '';
 325        let bgcolor = '';
 326        let clss = '';
 327  
 328        if (e.target.classList.contains('nocolor')) {
 329          color = 'none';
 330          bgcolor = 'transparent';
 331          clss = 'nocolor';
 332        } else {
 333          color = this.rgb2hex(e.target.style.backgroundColor);
 334          bgcolor = color;
 335        } // Reset the active class
 336  
 337  
 338        this.buttons.forEach(el => {
 339          if (el.classList.contains('active')) {
 340            el.classList.remove('active');
 341          }
 342        }); // Add the active class to the selected button
 343  
 344        e.target.classList.add('active');
 345        this.icon.classList.remove('nocolor');
 346        this.icon.setAttribute('class', clss);
 347        this.icon.style.backgroundColor = bgcolor; // trigger change event both on the select and on the custom element
 348  
 349        this.select.dispatchEvent(new Event('change'));
 350        this.dispatchEvent(new CustomEvent('change', {
 351          detail: {
 352            value: color
 353          },
 354          bubbles: true
 355        })); // Hide the panel
 356  
 357        this.hide(); // Change select value
 358  
 359        this.options.forEach(el => {
 360          if (el.selected) {
 361            el.removeAttribute('selected');
 362          }
 363  
 364          if (el.value === bgcolor) {
 365            el.setAttribute('selected', '');
 366          }
 367        });
 368      }
 369  
 370      keys(e) {
 371        if (e.keyCode === KEYCODE.ESC) {
 372          this.hide();
 373        }
 374  
 375        if (e.keyCode === KEYCODE.TAB) {
 376          // Get the index of the current active element
 377          const focusedIndex = this.focusableElements.indexOf(document.activeElement); // If first element is focused and shiftkey is in use, focus last item within modal
 378  
 379          if (e.shiftKey && (focusedIndex === 0 || focusedIndex === -1)) {
 380            this.focusableElements[this.focusableElements.length - 1].focus();
 381            e.preventDefault();
 382          } // If last element is focused and shiftkey is not in use, focus first item within modal
 383  
 384  
 385          if (!e.shiftKey && focusedIndex === this.focusableElements.length - 1) {
 386            this.focusableElements[0].focus();
 387            e.preventDefault();
 388          }
 389        }
 390      } // Prevents the mousedown event from "eating" the click event.
 391      // eslint-disable-next-line class-methods-use-this
 392  
 393  
 394      mousedown(e) {
 395        e.stopPropagation();
 396        e.preventDefault();
 397      }
 398  
 399      getColorName(value) {
 400        // Expand any short code
 401        let newValue = value;
 402  
 403        if (value.length === 4) {
 404          const tmpValue = value.split('');
 405          newValue = tmpValue[0] + tmpValue[1] + tmpValue[1] + tmpValue[2] + tmpValue[2] + tmpValue[3] + tmpValue[3];
 406        } // eslint-disable-next-line no-restricted-syntax
 407  
 408  
 409        for (const color in colorNames) {
 410          // eslint-disable-next-line no-prototype-builtins
 411          if (colorNames.hasOwnProperty(color) && newValue.toLowerCase() === colorNames[color]) {
 412            return color;
 413          }
 414        }
 415  
 416        return `$this.textColor} $value.replace('#', '').split('').join(', ')}`;
 417      }
 418      /**
 419       * Converts a RGB color to its hexadecimal value.
 420       * See http://stackoverflow.com/questions/1740700/get-hex-value-rather-than-rgb-value-using-$
 421       */
 422      // eslint-disable-next-line class-methods-use-this
 423  
 424  
 425      rgb2hex(rgb) {
 426        const hex = x => `0$parseInt(x, 10).toString(16)}`.slice(-2);
 427  
 428        const matches = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
 429        return `#$hex(matches[1])}$hex(matches[2])}$hex(matches[3])}`;
 430      }
 431  
 432    }
 433  
 434    customElements.define('joomla-field-simple-color', JoomlaFieldSimpleColor);
 435  })(customElements);


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer