haxorqt
Home
Console
Upload
information
Create File
Create Folder
About
:
/
home
/
sc1jaqa5103
/
prod.puv-editions.fr
/
wp-content
/
plugins
/
megamenu
/
js
/
colorpicker
/
Filename :
colorpicker.js
back
Copy
(function($) { // --- Helper Functions --- function hslToRgb(h, s, l) { /* ... (unchanged) ... */ let r, g, b; if (s == 0) { r = g = b = l; } else { const hue2rgb = (p, q, t) => { if (t < 0) t += 1; if (t > 1) t -= 1; if (t < 1 / 6) return p + (q - p) * 6 * t; if (t < 1 / 2) return q; if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; return p; }; const q = l < 0.5 ? l * (1 + s) : l + s - l * s; const p = 2 * l - q; r = hue2rgb(p, q, h + 1 / 3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1 / 3); } return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; } function rgbToHex(r, g, b) { /* ... (unchanged) ... */ return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase(); } function hexToRgb(hex) { /* ... (unchanged) ... */ const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; hex = hex.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b); const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; } function rgbToHsl(r, g, b) { /* ... (unchanged) ... */ r /= 255; g /= 255; b /= 255; const max = Math.max(r, g, b), min = Math.min(r, g, b); let h, s, l = (max + min) / 2; if (max == min) { h = s = 0; } else { const d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return [h, s, l]; } // HSV to HSL conversion function hsvToHsl(h, s, v) { const l = v * (1 - s / 2); const sl = (l === 0 || l === 1) ? 0 : (v - l) / Math.min(l, 1 - l); return [h, sl, l]; } // HSL to HSV conversion function hslToHsv(h, s, l) { const v = l + s * Math.min(l, 1 - l); const sv = (v === 0) ? 0 : 2 * (1 - l / v); return [h, sv, v]; } function parseRgbaString(rgbaString) { /* ... (unchanged) ... */ if (typeof rgbaString !== 'string') return null; const match = rgbaString.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d\.]+))?\)$/i); if (match) { return { r: parseInt(match[1]), g: parseInt(match[2]), b: parseInt(match[3]), a: match[4] !== undefined ? parseFloat(match[4]) : 1 }; } return null; } function resolveCssVariable(variableString) { /* ... (unchanged) ... */ if (!variableString || typeof variableString !== 'string' || !variableString.toLowerCase().startsWith('var(')) { return null; } const tempEl = document.createElement('div'); document.body.appendChild(tempEl); tempEl.style.display = 'none'; tempEl.style.color = variableString; let resolvedColorString = window.getComputedStyle(tempEl).color; document.body.removeChild(tempEl); if (!resolvedColorString || resolvedColorString === variableString || resolvedColorString === 'initial' || resolvedColorString === 'inherit' || resolvedColorString === 'unset' || resolvedColorString === 'currentColor') { return null; } if (resolvedColorString === 'transparent') { return { hex: rgbToHex(0,0,0), alpha: 0}; } const rgba = parseRgbaString(resolvedColorString); if (rgba) { return { hex: rgbToHex(rgba.r, rgba.g, rgba.b), alpha: rgba.a };} return null; } function getDefinedCssVariables() { /* ... (unchanged) ... */ const cssVariables = new Set(); try { for (const sheet of document.styleSheets) { try { const rules = sheet.cssRules || sheet.rules; if (!rules) continue; for (const rule of rules) { if (rule.type === CSSRule.STYLE_RULE && rule.style && typeof rule.style.getPropertyValue === 'function') { for (let i = 0; i < rule.style.length; i++) { const propName = rule.style[i]; if (propName.startsWith('--')) { cssVariables.add(propName); } } } else if (rule.type === CSSRule.STYLE_RULE && rule.styleDeclaration) { for (const propName of rule.styleDeclaration) { if (propName.startsWith('--')) { cssVariables.add(propName); } } } } } catch (e) { /* Silently ignore inaccessible stylesheets */ } } } catch (e) { /* Silently ignore if stylesheets cannot be accessed */ } return Array.from(cssVariables).sort(); } // --- Main Plugin Definition --- $.fn.customColorPicker = function(optionsOrMethodName, valueToSet) { let returnValue = this; if (typeof optionsOrMethodName === 'string') { const methodName = optionsOrMethodName; if (methodName === 'set') { return this.each(function() { const api = $(this).data('customColorPickerApi'); if (api && typeof api.setValue === 'function') { api.setValue(valueToSet); } }); } else if (methodName === 'get') { const api = $(this).first().data('customColorPickerApi'); if (api && typeof api.getValue === 'function') { returnValue = api.getValue(); } else { returnValue = undefined; } } else if (methodName === 'open') { return this.each(function() { const api = $(this).data('customColorPickerApi'); if (api && typeof api.open === 'function') { api.open(); } }); } else if (methodName === 'close') { return this.each(function() { const api = $(this).data('customColorPickerApi'); if (api && typeof api.close === 'function') { api.close(); } }); } } else { const settings = $.extend({ defaultColor: '#CCCCCC', palette: [], showCssVarPalette: true, onColorChange: function(colorString, inputElement) {} }, optionsOrMethodName); this.each(function() { const $originalInput = $(this); let $textDisplayInput; let $swatchElement; let $swatchColorElement; let $swatchTextIndicator; // Renamed from $swatchVarIndicator const instanceApi = $originalInput.data('customColorPickerApi') || {}; if (!$originalInput.data('color-picker-enhanced')) { const $wrapper = $('<div class="mega-custom-color-input-wrapper"></div>'); $swatchElement = $('<span class="mega-custom-color-input-swatch"></span>'); $swatchColorElement = $('<div class="mega-custom-color-input-swatch-color"></div>'); $swatchTextIndicator = $('<span class="mega-swatch-text-indicator">VAR</span>'); // Create indicator with "VAR" $swatchColorElement.append($swatchTextIndicator); $swatchElement.append($swatchColorElement); $textDisplayInput = $('<input type="text" class="mega-color-picker-input-text">'); const originalIdVal = $originalInput.attr('id'); if (originalIdVal) { $wrapper.attr('id', originalIdVal); $originalInput.removeAttr('id'); } if ($originalInput.attr('name')) { $textDisplayInput.attr('name', $originalInput.attr('name') + '-text-display'); } if ($originalInput.attr('placeholder')) { $textDisplayInput.attr('placeholder', $originalInput.attr('placeholder'));} $textDisplayInput.val($originalInput.val()); $wrapper.append($swatchElement).append($textDisplayInput); $originalInput.after($wrapper).addClass('mega-plugin-enhanced'); $originalInput.data('color-picker-enhanced', true); $originalInput.data('swatch-element', $swatchElement); $originalInput.data('swatch-color-element', $swatchColorElement); $originalInput.data('swatch-text-indicator', $swatchTextIndicator); $originalInput.data('text-display-input', $textDisplayInput); } else { $swatchElement = $originalInput.data('swatch-element'); $swatchColorElement = $originalInput.data('swatch-color-element'); $swatchTextIndicator = $originalInput.data('swatch-text-indicator'); $textDisplayInput = $originalInput.data('text-display-input'); } const $uiWrapper = $textDisplayInput.parent('.mega-custom-color-input-wrapper'); const prevSettings = instanceApi.currentSettings || {}; const mergedSettings = $.extend({}, prevSettings, settings); if ( (!mergedSettings.palette || mergedSettings.palette.length === 0) && prevSettings.palette && prevSettings.palette.length > 0 ) { mergedSettings.palette = prevSettings.palette; } instanceApi.currentSettings = mergedSettings; const pluginInstance = this; let $pickerContainer, $paletteContainerElement, $cssVarPaletteContainer, $mainCanvas, $hueCanvas, $opacitySlider, $opacityDisplay, $previewColor, $valueInputInPicker, $selectorDot, $hueIndicator; let mainCanvasEl, hueCanvasEl; let mainCtx, hueCtx; let currentHslHue = 0, currentHslSaturation = 0, currentHslLightness = 0, currentAlpha = 1; let isDraggingMain = false, isDraggingHue = false, isDraggingOpacity = false; const uiWrapperId = $uiWrapper.attr('id') || $originalInput.attr('name') || 'picker'; const pickerInstanceId = uiWrapperId + '-colorpicker-instance-' + Date.now(); let isCssVarMode = false; let currentCssVarString = ''; function initializeColor() { let inputValue = $originalInput.val() || ''; let baseHexForHslState = instanceApi.currentSettings.defaultColor; let alphaForHslState = 1.0; isCssVarMode = false; currentCssVarString = ''; if (inputValue.toLowerCase().startsWith('var(')) { currentCssVarString = inputValue; isCssVarMode = true; const resolved = resolveCssVariable(inputValue); if (resolved) { baseHexForHslState = resolved.hex; alphaForHslState = resolved.alpha; } } else if (inputValue.toLowerCase() === 'transparent') { baseHexForHslState = rgbToHex(0,0,0); alphaForHslState = 0; } else if (inputValue.toLowerCase().startsWith('rgba') || inputValue.toLowerCase().startsWith('rgb(') ) { const parsedRgba = parseRgbaString(inputValue); if (parsedRgba) { baseHexForHslState = rgbToHex(parsedRgba.r, parsedRgba.g, parsedRgba.b); alphaForHslState = parsedRgba.a; } } else if (inputValue.startsWith('#')) { const rgb = hexToRgb(inputValue); if (rgb) { baseHexForHslState = inputValue.toUpperCase(); alphaForHslState = 1.0;} } else if (inputValue === '') { } currentAlpha = alphaForHslState; const rgbForHsl = hexToRgb(baseHexForHslState); if (rgbForHsl) { const hsl = rgbToHsl(rgbForHsl.r, rgbForHsl.g, rgbForHsl.b); currentHslHue = hsl[0]; currentHslSaturation = hsl[1]; currentHslLightness = hsl[2]; } else { const defaultRgb = hexToRgb(instanceApi.currentSettings.defaultColor); const defaultHsl = rgbToHsl(defaultRgb.r, defaultRgb.g, defaultRgb.b); currentHslHue = defaultHsl[0]; currentHslSaturation = defaultHsl[1]; currentHslLightness = defaultHsl[2]; currentAlpha = 1.0; } } function getCurrentColorStringForOutput() { if (isCssVarMode) return currentCssVarString; if (currentAlpha === 0) return "transparent"; const [r, g, b] = hslToRgb(currentHslHue, currentHslSaturation, currentHslLightness); if (currentAlpha < 1) { let alphaStr = currentAlpha.toFixed(2); alphaStr = parseFloat(alphaStr).toString(); return `rgba(${r},${g},${b},${alphaStr})`; } return `rgb(${r},${g},${b})`; } function getVisualRgbaColor() { let r,g,b,a; if (isCssVarMode) { const resolved = resolveCssVariable(currentCssVarString); if (resolved) { const rgbParts = hexToRgb(resolved.hex); r = rgbParts.r; g = rgbParts.g; b = rgbParts.b; a = resolved.alpha; } else { const rgbParts = hexToRgb(instanceApi.currentSettings.defaultColor); r = rgbParts.r; g = rgbParts.g; b = rgbParts.b; a = 1.0; } } else { [r, g, b] = hslToRgb(currentHslHue, currentHslSaturation, currentHslLightness); a = currentAlpha; } return `rgba(${r},${g},${b},${a})`; } function _updateOpacitySliderBackground() { if (!$opacitySlider) return; const [r, g, b] = hslToRgb(currentHslHue, currentHslSaturation, currentHslLightness); const gradient = `linear-gradient(to right, rgba(${r},${g},${b},0), rgba(${r},${g},${b},1))`; $opacitySlider.css('background-image', gradient); } function updateVisualsWithCurrentColor() { const outputStringForDisplay = getCurrentColorStringForOutput(); const visualRgba = getVisualRgbaColor(); if ($textDisplayInput) $textDisplayInput.val(outputStringForDisplay); if ($swatchColorElement) { if (isCssVarMode) { $swatchColorElement.css({ 'background-image': 'none', 'background-color': '#f0f0f0' }); if ($swatchTextIndicator) $swatchTextIndicator.show(); } else { $swatchColorElement.css({ 'background-image': 'none', 'background-color': visualRgba }); if ($swatchTextIndicator) $swatchTextIndicator.hide(); } } if ($pickerContainer && $pickerContainer.is(':visible')) { if ($previewColor) $previewColor.css('background-color', visualRgba); if ($valueInputInPicker) $valueInputInPicker.val(outputStringForDisplay); if ($opacitySlider) { $opacitySlider.val(Math.round(currentAlpha * 100)); _updateOpacitySliderBackground(); } if ($opacityDisplay) $opacityDisplay.text(Math.round(currentAlpha * 100) + '%'); } } instanceApi._drawPalette = function() { if (!$paletteContainerElement) return; $paletteContainerElement.empty(); const seenHex = new Set(); function appendHexPaletteSwatch(hexUpper) { if (seenHex.has(hexUpper)) return; seenHex.add(hexUpper); const $swatch = $('<div class="mega-picker-swatch"></div>') .css('background-color', hexUpper).attr('title', hexUpper) .on('click', function() { isCssVarMode = false; currentCssVarString = ''; const rgb = hexToRgb(hexUpper); if (rgb) { const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b); currentHslHue = hsl[0]; currentHslSaturation = hsl[1]; currentHslLightness = hsl[2]; } currentAlpha = 1.0; handleColorSelectionChange(true); }); $paletteContainerElement.append($swatch); } if (instanceApi.currentSettings.palette && Array.isArray(instanceApi.currentSettings.palette)) { instanceApi.currentSettings.palette.forEach(colorString => { if (typeof colorString !== 'string') return; const s = colorString.trim(); if (s.toLowerCase() === 'transparent') { const $swatch = $('<div class="mega-picker-swatch mega-picker-swatch--transparent"></div>') .attr('title', 'transparent') .on('click', function() { isCssVarMode = false; currentCssVarString = ''; currentAlpha = 0; const fallbackHex = instanceApi.currentSettings.defaultColor || '#cccccc'; const rgb = hexToRgb(fallbackHex); if (rgb) { const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b); currentHslHue = hsl[0]; currentHslSaturation = hsl[1]; currentHslLightness = hsl[2]; } handleColorSelectionChange(true); }); $paletteContainerElement.append($swatch); } else if (s.startsWith('#')) { const rgb = hexToRgb(s); if (rgb) appendHexPaletteSwatch(s.toUpperCase()); } else { console.warn("ColorPicker: Invalid color in predefined palette:", colorString); } }); } $('.mega-color-picker-input.mega-plugin-enhanced').not($originalInput).each(function() { const otherOriginalInput = $(this); const currentInputVal = otherOriginalInput.val(); let baseHexForPalette = null; if (currentInputVal.toLowerCase().startsWith('var(')) { const resolved = resolveCssVariable(currentInputVal); if (resolved) baseHexForPalette = resolved.hex; else baseHexForPalette = instanceApi.currentSettings.defaultColor; } else if (currentInputVal.toLowerCase() === 'transparent') { baseHexForPalette = instanceApi.currentSettings.defaultColor; } else if (currentInputVal.toLowerCase().startsWith('rgba') || currentInputVal.toLowerCase().startsWith('rgb(')) { const parsedRgba = parseRgbaString(currentInputVal); if (parsedRgba) baseHexForPalette = rgbToHex(parsedRgba.r, parsedRgba.g, parsedRgba.b); } else if (currentInputVal.startsWith('#')) { const rgb = hexToRgb(currentInputVal); if (rgb) baseHexForPalette = rgbToHex(rgb.r, rgb.g, rgb.b); } if (baseHexForPalette) { const up = baseHexForPalette.toUpperCase(); if (!seenHex.has(up)) appendHexPaletteSwatch(up); } }); } instanceApi._drawCssVarPalette = function() { /* ... (unchanged, uses instanceApi.currentSettings) ... */ if (!instanceApi.currentSettings.showCssVarPalette || !$cssVarPaletteContainer) { if($cssVarPaletteContainer) $cssVarPaletteContainer.hide(); return; } $cssVarPaletteContainer.empty(); const definedVariables = getDefinedCssVariables(); let validVarsFound = 0; definedVariables.forEach(varName => { const varString = `var(${varName})`; const resolved = resolveCssVariable(varString); if (resolved) { validVarsFound++; const displayColor = `rgba(${hexToRgb(resolved.hex).r}, ${hexToRgb(resolved.hex).g}, ${hexToRgb(resolved.hex).b}, ${resolved.alpha})`; const $swatch = $('<div class="mega-picker-swatch"></div>') .css('background-color', displayColor) .attr('title', varString) .on('click', function() { isCssVarMode = true; currentCssVarString = varString; $originalInput.val(currentCssVarString); initializeColor(); handleColorSelectionChange(true); }); $cssVarPaletteContainer.append($swatch); } }); if (validVarsFound > 0) { $cssVarPaletteContainer.show(); } else { $cssVarPaletteContainer.hide(); } } function _createPickerDOM() { /* ... (unchanged, uses instanceApi.currentSettings) ... */ if ($originalInput.data('picker-container-ref')) { $pickerContainer = $originalInput.data('picker-container-ref'); $paletteContainerElement = $pickerContainer.find('.mega-picker-palette--colors'); if (instanceApi.currentSettings.showCssVarPalette) $cssVarPaletteContainer = $pickerContainer.find('.mega-picker-palette--vars'); $mainCanvas = $pickerContainer.find('.mega-color-picker-main'); mainCanvasEl = $mainCanvas[0]; $selectorDot = $pickerContainer.find('.mega-color-picker-selector-dot'); $hueCanvas = $pickerContainer.find('.mega-color-picker-hue-slider'); hueCanvasEl = $hueCanvas[0]; $hueIndicator = $pickerContainer.find('.mega-hue-slider-indicator'); $opacitySlider = $pickerContainer.find('.mega-color-picker-opacity-slider'); $opacityDisplay = $pickerContainer.find('.mega-color-picker-opacity-display'); $previewColor = $pickerContainer.find('.mega-color-picker-preview-color'); $valueInputInPicker = $pickerContainer.find('.mega-color-picker-value-input'); if (mainCanvasEl) mainCtx = mainCanvasEl.getContext('2d'); if (hueCanvasEl) hueCtx = hueCanvasEl.getContext('2d'); $pickerContainer.data('picker-instance', pluginInstance); return; } $pickerContainer = $('<div class="mega-color-picker-container"></div>').data('picker-instance', pluginInstance); $paletteContainerElement = $('<div class="mega-picker-palette mega-picker-palette--colors"></div>'); $pickerContainer.append($paletteContainerElement); if (instanceApi.currentSettings.showCssVarPalette) { $cssVarPaletteContainer = $('<div class="mega-picker-palette mega-picker-palette--vars"></div>'); $pickerContainer.append($cssVarPaletteContainer); } mainCanvasEl = $('<canvas class="mega-color-picker-main"></canvas>')[0]; $mainCanvas = $(mainCanvasEl); $selectorDot = $('<div class="mega-color-picker-selector-dot"></div>'); $pickerContainer.append($mainCanvas).append($selectorDot); const hueWrapper = $('<div style="position:relative;"></div>'); hueCanvasEl = $('<canvas class="mega-color-picker-hue-slider"></canvas>')[0]; $hueCanvas = $(hueCanvasEl); $hueIndicator = $('<div class="mega-hue-slider-indicator"></div>'); hueWrapper.append($hueCanvas).append($hueIndicator); $pickerContainer.append(hueWrapper); const $opacityContainer = $('<div class="mega-color-picker-opacity-slider-container"></div>'); $opacitySlider = $('<input type="range" min="0" max="100" value="100" class="mega-color-picker-opacity-slider">'); $opacityDisplay = $('<span class="mega-color-picker-opacity-display">100%</span>'); $opacityContainer.append($opacitySlider).append($opacityDisplay); $pickerContainer.append($opacityContainer); const $valueInputWrapper = $('<div class="mega-color-picker-value-input-wrapper"></div>'); const $previewBox = $('<div class="mega-color-picker-preview"></div>'); $previewColor = $('<div class="mega-color-picker-preview-color"></div>'); $previewBox.append($previewColor); $valueInputInPicker = $('<input type="text" class="mega-color-picker-value-input">'); $valueInputWrapper.append($previewBox).append($valueInputInPicker); $pickerContainer.append($valueInputWrapper); $('body').append($pickerContainer); const canvasActualWidth = 280 - (15 * 2); mainCanvasEl.width = canvasActualWidth; mainCanvasEl.height = 150; hueCanvasEl.width = canvasActualWidth; hueCanvasEl.height = 20; mainCtx = mainCanvasEl.getContext('2d'); hueCtx = hueCanvasEl.getContext('2d'); _bindPickerInternalEvents(); $originalInput.data('picker-container-ref', $pickerContainer); } function _drawMainColorCanvas() { if (!mainCtx || !mainCanvasEl || mainCanvasEl.width === 0 || mainCanvasEl.height === 0) return; const width = mainCanvasEl.width; const height = mainCanvasEl.height; mainCtx.clearRect(0,0,width,height); const baseRgb = hslToRgb(currentHslHue, 1, 0.5); mainCtx.fillStyle = `rgb(${baseRgb[0]}, ${baseRgb[1]}, ${baseRgb[2]})`; mainCtx.fillRect(0, 0, width, height); const whiteGradient = mainCtx.createLinearGradient(0, 0, width, 0); whiteGradient.addColorStop(0, 'rgba(255,255,255,1)'); whiteGradient.addColorStop(1, 'rgba(255,255,255,0)'); mainCtx.fillStyle = whiteGradient; mainCtx.fillRect(0, 0, width, height); const blackGradient = mainCtx.createLinearGradient(0, 0, 0, height); blackGradient.addColorStop(0, 'rgba(0,0,0,0)'); blackGradient.addColorStop(1, 'rgba(0,0,0,1)'); mainCtx.fillStyle = blackGradient; mainCtx.fillRect(0, 0, width, height); const [h_dot, s_dot_hsv, v_dot_hsv] = hslToHsv(currentHslHue, currentHslSaturation, currentHslLightness); const x = s_dot_hsv * width; const y = (1 - v_dot_hsv) * height; $selectorDot.css({ top: $mainCanvas.position().top + y + 'px', left: $mainCanvas.position().left + x + 'px' }); } function _drawHueSlider() { /* ... (unchanged) ... */ if (!hueCtx || !hueCanvasEl || hueCanvasEl.width === 0 || hueCanvasEl.height === 0) return; const width = hueCanvasEl.width; const height = hueCanvasEl.height; hueCtx.clearRect(0,0,width,height); const gradient = hueCtx.createLinearGradient(0, 0, width, 0); for (let i = 0; i <= 360; i += 6) { gradient.addColorStop(i / 360, `hsl(${i}, 100%, 50%)`); } hueCtx.fillStyle = gradient; hueCtx.fillRect(0, 0, width, height); const indicatorX = currentHslHue * width; $hueIndicator.css({ left: indicatorX + 'px' }); } function handleColorSelectionChange(isCommittedChange = false) { const finalColorString = getCurrentColorStringForOutput(); $originalInput.val(finalColorString); updateVisualsWithCurrentColor(); if ($pickerContainer && $pickerContainer.is(':visible')) { _drawMainColorCanvas(); _drawHueSlider(); } instanceApi.currentSettings.onColorChange.call($originalInput, finalColorString, $originalInput); } function updateColorFromMainCanvas(event) { if(!mainCanvasEl) return; isCssVarMode = false; currentCssVarString = ''; const rect = mainCanvasEl.getBoundingClientRect(); let x = event.clientX - rect.left; let y = event.clientY - rect.top; const width = mainCanvasEl.width; const height = mainCanvasEl.height; x = Math.max(0, Math.min(width, x)); y = Math.max(0, Math.min(height, y)); const s_hsv = x / width; const v_hsv = 1 - (y / height); const [h, s_hsl, l_hsl] = hsvToHsl(currentHslHue, s_hsv, v_hsv); currentHslSaturation = s_hsl; currentHslLightness = l_hsl; if (currentAlpha === 0) currentAlpha = 1; handleColorSelectionChange(); } function updateColorFromHueSlider(event) { if(!hueCanvasEl) return; isCssVarMode = false; currentCssVarString = ''; const rect = hueCanvasEl.getBoundingClientRect(); let x = event.clientX - rect.left; const width = hueCanvasEl.width; x = Math.max(0, Math.min(width, x)); currentHslHue = x / width; handleColorSelectionChange(); } function updateColorFromOpacitySlider(event) { isCssVarMode = false; currentCssVarString = ''; currentAlpha = parseFloat($(event.target).val()) / 100; handleColorSelectionChange(); } function _showPicker() { _createPickerDOM(); if(instanceApi._drawPalette) instanceApi._drawPalette(); if(instanceApi._drawCssVarPalette) instanceApi._drawCssVarPalette(); $('.mega-color-picker-container').not($pickerContainer).hide(); const uiWrapperPos = $uiWrapper.offset(); const uiWrapperHeight = $uiWrapper.outerHeight(); let pickerLeft = uiWrapperPos.left; let pickerTop = uiWrapperPos.top + uiWrapperHeight + 5; const pickerWidth = $pickerContainer.outerWidth(); const pickerHeight = $pickerContainer.outerHeight(); const windowWidth = $(window).width(); const windowHeight = $(window).height(); const scrollLeft = $(window).scrollLeft(); const scrollTop = $(window).scrollTop(); if (pickerLeft + pickerWidth > windowWidth + scrollLeft) { pickerLeft = windowWidth + scrollLeft - pickerWidth - 5; } if (pickerLeft < scrollLeft) { pickerLeft = scrollLeft + 5; } if (pickerTop + pickerHeight > windowHeight + scrollTop) { let potentialTop = uiWrapperPos.top - pickerHeight - 5; if (potentialTop < scrollTop) { pickerTop = windowHeight + scrollTop - pickerHeight - 5; if (pickerTop < scrollTop) pickerTop = scrollTop + 5; } else { pickerTop = potentialTop; } } if (pickerTop < scrollTop) { pickerTop = scrollTop + 5; } $pickerContainer.css({ top: pickerTop + 'px', left: pickerLeft + 'px' }).fadeIn(200); $originalInput.val($textDisplayInput.val()); initializeColor(); updateVisualsWithCurrentColor(); _drawMainColorCanvas(); _drawHueSlider(); } function _hidePicker() { /* ... (unchanged) ... */ if ($pickerContainer) { $pickerContainer.fadeOut(200); } } function _bindPickerInternalEvents() { if ($mainCanvas) $mainCanvas.on('mousedown', function(e) { e.preventDefault(); isDraggingMain = true; updateColorFromMainCanvas(e); }); if ($hueCanvas) $hueCanvas.on('mousedown', function(e) { e.preventDefault(); isDraggingHue = true; updateColorFromHueSlider(e); }); if ($opacitySlider) { $opacitySlider.on('input', updateColorFromOpacitySlider); $opacitySlider.on('mousedown', function() { isDraggingOpacity = true; }); } // CSS Var Palette swatches have their own click handlers set in _drawCssVarPalette $(document).on(`mousemove.${pickerInstanceId}`, function(e) { if (!$pickerContainer || !$pickerContainer.is(':visible')) return; if (isDraggingMain) updateColorFromMainCanvas(e); if (isDraggingHue) updateColorFromHueSlider(e); }).on(`mouseup.${pickerInstanceId}`, function() { if (!$pickerContainer || !$pickerContainer.is(':visible')) return; if (isDraggingMain || isDraggingHue || isDraggingOpacity) { handleColorSelectionChange(true); } isDraggingMain = false; isDraggingHue = false; isDraggingOpacity = false; }); if($valueInputInPicker) { $valueInputInPicker.on('change', function() { const value = $(this).val().trim(); $originalInput.val(value); initializeColor(); handleColorSelectionChange(true); }); } if($pickerContainer) $pickerContainer.on('click', function(e) { e.stopPropagation(); }); } // --- API Methods --- instanceApi.setValue = function(newValue) { $originalInput.val(newValue); initializeColor(); handleColorSelectionChange(true); }; instanceApi.getValue = function() { return $originalInput.val(); }; instanceApi.open = function() { _showPicker(); if ($textDisplayInput && $textDisplayInput.length) { $textDisplayInput.trigger('focus'); } }; instanceApi.close = function() { _hidePicker(); }; $originalInput.data('customColorPickerApi', instanceApi); initializeColor(); updateVisualsWithCurrentColor(); $uiWrapper.on(`click.${pickerInstanceId}`, function(e) { e.preventDefault(); e.stopPropagation(); _showPicker(); if ($textDisplayInput && $textDisplayInput.length) { $textDisplayInput.trigger('focus'); } }); if ($textDisplayInput) { $textDisplayInput.on(`blur.${pickerInstanceId} keydown.${pickerInstanceId}`, function(e) { if (e.type === 'keydown' && e.key !== 'Enter') { return; } $originalInput.val($textDisplayInput.val()); initializeColor(); updateVisualsWithCurrentColor(); }); } $(document).on(`click.${pickerInstanceId}`, function(e) { if ($pickerContainer && $pickerContainer.is(':visible')) { if (!$uiWrapper.is(e.target) && $uiWrapper.has(e.target).length === 0 && !$pickerContainer.is(e.target) && $pickerContainer.has(e.target).length === 0) { _hidePicker(); } } }); $(document).on(`keydown.${pickerInstanceId}`, function (e) { if (!$pickerContainer || !$pickerContainer.is(':visible')) { return; } if (e.key !== 'Escape') { return; } e.preventDefault(); e.stopImmediatePropagation(); _hidePicker(); }); }); } return returnValue; }; }(jQuery));