|
73 | 73 | }
|
74 | 74 | break;
|
75 | 75 | case 'parent':
|
76 |
| - container = document.querySelector(options.parent); |
| 76 | + container = options.parent instanceof HTMLElement ? options.parent : document.querySelector(options.parent); |
77 | 77 | if (container) {
|
78 | 78 | container.appendChild(picker);
|
79 | 79 | settings.parent = options.parent;
|
|
105 | 105 | break;
|
106 | 106 | case 'rtl':
|
107 | 107 | settings.rtl = !!options.rtl;
|
108 |
| - document.querySelectorAll('.clr-field').forEach(function (field) {return field.classList.toggle('clr-rtl', settings.rtl);}); |
| 108 | + Array.from(document.getElementsByClassName('clr-field')).forEach(function (field) {return field.classList.toggle('clr-rtl', settings.rtl);}); |
109 | 109 | break;
|
110 | 110 | case 'margin':
|
111 | 111 | options.margin *= 1;
|
|
125 | 125 | break;
|
126 | 126 | case 'swatches':
|
127 | 127 | if (Array.isArray(options.swatches)) {(function () {
|
128 |
| - var swatches = []; |
| 128 | + var swatchesContainer = getEl('clr-swatches'); |
| 129 | + var swatches = document.createElement('div'); |
129 | 130 |
|
| 131 | + // Clear current swatches |
| 132 | + swatchesContainer.textContent = ''; |
| 133 | + |
| 134 | + // Build new swatches |
130 | 135 | options.swatches.forEach(function (swatch, i) {
|
131 |
| - swatches.push("<button type=\"button\" id=\"clr-swatch-" + i + "\" aria-labelledby=\"clr-swatch-label clr-swatch-" + i + "\" style=\"color: " + swatch + ";\">" + swatch + "</button>"); |
| 136 | + var button = document.createElement('button'); |
| 137 | + |
| 138 | + button.setAttribute('type', "button"); |
| 139 | + button.setAttribute('id', "clr-swatch-" + i); |
| 140 | + button.setAttribute('aria-labelledby', "clr-swatch-label clr-swatch-" + i); |
| 141 | + button.style.color = swatch; |
| 142 | + button.textContent = swatch; |
| 143 | + |
| 144 | + swatches.appendChild(button); |
132 | 145 | });
|
133 | 146 |
|
134 |
| - getEl('clr-swatches').innerHTML = swatches.length ? "<div>" + swatches.join('') + "</div>" : ''; |
| 147 | + // Append new swatches if any |
| 148 | + if (options.swatches.length) { |
| 149 | + swatchesContainer.appendChild(swatches); |
| 150 | + } |
| 151 | + |
135 | 152 | settings.swatches = options.swatches.slice();})();
|
136 | 153 | }
|
137 | 154 | break;
|
|
294 | 311 |
|
295 | 312 | /**
|
296 | 313 | * Bind the color picker to input fields that match the selector.
|
297 |
| - * @param {string} selector One or more selectors pointing to input fields. |
| 314 | + * @param {(string|HTMLElement|HTMLElement[])} selector A CSS selector string, a DOM element or a list of DOM elements. |
298 | 315 | */
|
299 | 316 | function bindFields(selector) {
|
300 |
| - // Show the color picker on click on the input fields that match the selector |
301 |
| - addListener(document, 'click', selector, function (event) { |
302 |
| - // Skip if inline mode is in use |
303 |
| - if (settings.inline) { |
304 |
| - return; |
305 |
| - } |
| 317 | + if (selector instanceof HTMLElement) { |
| 318 | + selector = [selector]; |
| 319 | + } |
306 | 320 |
|
307 |
| - // Apply any per-instance options first |
308 |
| - attachVirtualInstance(event.target); |
| 321 | + if (Array.isArray(selector)) { |
| 322 | + selector.forEach(function (field) { |
| 323 | + addListener(field, 'click', openPicker); |
| 324 | + addListener(field, 'input', updateColorPreview); |
| 325 | + }); |
| 326 | + } else { |
| 327 | + addListener(document, 'click', selector, openPicker); |
| 328 | + addListener(document, 'input', selector, updateColorPreview); |
| 329 | + } |
| 330 | + } |
309 | 331 |
|
310 |
| - currentEl = event.target; |
311 |
| - oldColor = currentEl.value; |
312 |
| - currentFormat = getColorFormatFromStr(oldColor); |
313 |
| - picker.classList.add('clr-open'); |
| 332 | + /** |
| 333 | + * Open the color picker. |
| 334 | + * @param {object} event The event that opens the color picker. |
| 335 | + */ |
| 336 | + function openPicker(event) { |
| 337 | + // Skip if inline mode is in use |
| 338 | + if (settings.inline) { |
| 339 | + return; |
| 340 | + } |
314 | 341 |
|
315 |
| - updatePickerPosition(); |
316 |
| - setColorFromStr(oldColor); |
| 342 | + // Apply any per-instance options first |
| 343 | + attachVirtualInstance(event.target); |
317 | 344 |
|
318 |
| - if (settings.focusInput || settings.selectInput) { |
319 |
| - colorValue.focus({ preventScroll: true }); |
320 |
| - colorValue.setSelectionRange(currentEl.selectionStart, currentEl.selectionEnd); |
321 |
| - } |
| 345 | + currentEl = event.target; |
| 346 | + oldColor = currentEl.value; |
| 347 | + currentFormat = getColorFormatFromStr(oldColor); |
| 348 | + picker.classList.add('clr-open'); |
322 | 349 |
|
323 |
| - if (settings.selectInput) { |
324 |
| - colorValue.select(); |
325 |
| - } |
| 350 | + updatePickerPosition(); |
| 351 | + setColorFromStr(oldColor); |
326 | 352 |
|
327 |
| - // Always focus the first element when using keyboard navigation |
328 |
| - if (keyboardNav || settings.swatchesOnly) { |
329 |
| - getFocusableElements().shift().focus(); |
330 |
| - } |
| 353 | + if (settings.focusInput || settings.selectInput) { |
| 354 | + colorValue.focus({ preventScroll: true }); |
| 355 | + colorValue.setSelectionRange(currentEl.selectionStart, currentEl.selectionEnd); |
| 356 | + } |
331 | 357 |
|
332 |
| - // Trigger an "open" event |
333 |
| - currentEl.dispatchEvent(new Event('open', { bubbles: true })); |
334 |
| - }); |
| 358 | + if (settings.selectInput) { |
| 359 | + colorValue.select(); |
| 360 | + } |
335 | 361 |
|
336 |
| - // Update the color preview of the input fields that match the selector |
337 |
| - addListener(document, 'input', selector, function (event) { |
338 |
| - var parent = event.target.parentNode; |
| 362 | + // Always focus the first element when using keyboard navigation |
| 363 | + if (keyboardNav || settings.swatchesOnly) { |
| 364 | + getFocusableElements().shift().focus(); |
| 365 | + } |
339 | 366 |
|
340 |
| - // Only update the preview if the field has been previously wrapped |
341 |
| - if (parent.classList.contains('clr-field')) { |
342 |
| - parent.style.color = event.target.value; |
343 |
| - } |
344 |
| - }); |
| 367 | + // Trigger an "open" event |
| 368 | + currentEl.dispatchEvent(new Event('open', { bubbles: true })); |
345 | 369 | }
|
346 | 370 |
|
347 | 371 | /**
|
|
423 | 447 |
|
424 | 448 | /**
|
425 | 449 | * Wrap the linked input fields in a div that adds a color preview.
|
426 |
| - * @param {string} selector One or more selectors pointing to input fields. |
| 450 | + * @param {(string|HTMLElement|HTMLElement[])} selector A CSS selector string, a DOM element or a list of DOM elements. |
427 | 451 | */
|
428 | 452 | function wrapFields(selector) {
|
429 |
| - document.querySelectorAll(selector).forEach(function (field) { |
430 |
| - var parentNode = field.parentNode; |
| 453 | + if (selector instanceof HTMLElement) { |
| 454 | + wrapColorField(selector); |
| 455 | + } else if (Array.isArray(selector)) { |
| 456 | + selector.forEach(wrapColorField); |
| 457 | + } else { |
| 458 | + document.querySelectorAll(selector).forEach(wrapColorField); |
| 459 | + } |
| 460 | + } |
431 | 461 |
|
432 |
| - if (!parentNode.classList.contains('clr-field')) { |
433 |
| - var wrapper = document.createElement('div'); |
434 |
| - var classes = 'clr-field'; |
| 462 | + /** |
| 463 | + * Wrap an input field in a div that adds a color preview. |
| 464 | + * @param {object} field The input field. |
| 465 | + */ |
| 466 | + function wrapColorField(field) { |
| 467 | + var parentNode = field.parentNode; |
435 | 468 |
|
436 |
| - if (settings.rtl || field.classList.contains('clr-rtl')) { |
437 |
| - classes += ' clr-rtl'; |
438 |
| - } |
| 469 | + if (!parentNode.classList.contains('clr-field')) { |
| 470 | + var wrapper = document.createElement('div'); |
| 471 | + var classes = 'clr-field'; |
439 | 472 |
|
440 |
| - wrapper.innerHTML = "<button type=\"button\" aria-labelledby=\"clr-open-label\"></button>"; |
441 |
| - parentNode.insertBefore(wrapper, field); |
442 |
| - wrapper.setAttribute('class', classes); |
443 |
| - wrapper.style.color = field.value; |
444 |
| - wrapper.appendChild(field); |
| 473 | + if (settings.rtl || field.classList.contains('clr-rtl')) { |
| 474 | + classes += ' clr-rtl'; |
445 | 475 | }
|
446 |
| - }); |
| 476 | + |
| 477 | + wrapper.innerHTML = '<button type="button" aria-labelledby="clr-open-label"></button>'; |
| 478 | + parentNode.insertBefore(wrapper, field); |
| 479 | + wrapper.className = classes; |
| 480 | + wrapper.style.color = field.value; |
| 481 | + wrapper.appendChild(field); |
| 482 | + } |
| 483 | + } |
| 484 | + |
| 485 | + /** |
| 486 | + * Update the color preview of an input field |
| 487 | + * @param {object} event The "input" event that triggers the color change. |
| 488 | + */ |
| 489 | + function updateColorPreview(event) { |
| 490 | + var parent = event.target.parentNode; |
| 491 | + |
| 492 | + // Only update the preview if the field has been previously wrapped |
| 493 | + if (parent.classList.contains('clr-field')) { |
| 494 | + parent.style.color = event.target.value; |
| 495 | + } |
447 | 496 | }
|
448 | 497 |
|
449 | 498 | /**
|
|
983 | 1032 | addListener(document, 'mousemove', moveMarker);
|
984 | 1033 | });
|
985 | 1034 |
|
| 1035 | + addListener(colorArea, 'contextmenu', function (event) { |
| 1036 | + event.preventDefault(); |
| 1037 | + }); |
| 1038 | + |
986 | 1039 | addListener(colorArea, 'touchstart', function (event) {
|
987 | 1040 | document.addEventListener('touchmove', moveMarker, { passive: false });
|
988 | 1041 | });
|
|
0 commit comments