From f1754b886079aeb87b52160bba2ef141ebd4b5d3 Mon Sep 17 00:00:00 2001 From: Brian Ernesto Date: Mon, 4 Mar 2024 17:07:31 +0000 Subject: [PATCH] ISSUE 5703: Color picker offset relative to editor container (#5704) Closes #5703 --- src/canvas/model/Frame.ts | 2 ++ src/utils/ColorPicker.ts | 66 ++++++++++++++++++++++++--------------- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/canvas/model/Frame.ts b/src/canvas/model/Frame.ts index d9ce11f3da..a8cad8b3e3 100644 --- a/src/canvas/model/Frame.ts +++ b/src/canvas/model/Frame.ts @@ -226,6 +226,8 @@ export default class Frame extends ModuleModel { _emitUpdated(data = {}) { this.em.trigger('frame:updated', { frame: this, ...data }); + // When the frame is updated, the canvas should be refreshed. This may be better up stream from here. + this.em.refreshCanvas(); } hasAutoHeight() { diff --git a/src/utils/ColorPicker.ts b/src/utils/ColorPicker.ts index 7e5cc26ca5..4189a9cafb 100644 --- a/src/utils/ColorPicker.ts +++ b/src/utils/ColorPicker.ts @@ -982,34 +982,48 @@ export default function ($, undefined?: any) { /** * checkOffset - get the offset below/above and left/right element depending on screen position - * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js */ function getOffset(picker, input) { - var extraY = 0; - var dpWidth = picker.outerWidth(); - var dpHeight = picker.outerHeight(); - var inputHeight = input.outerHeight(); - var doc = picker[0].ownerDocument; - var docElem = doc.documentElement; - var cW = docElem.clientWidth; - var cH = docElem.clientHeight; - var scL = $(doc).scrollLeft(); - var scT = $(doc).scrollTop(); - var viewWidth = cW + scL; - var viewHeight = cH + scT; - var offset = input.offset(); - - offset.top += inputHeight; - - offset.left -= Math.min( - offset.left, - offset.left + dpWidth > viewWidth && viewWidth > dpWidth ? Math.abs(offset.left + dpWidth - viewWidth) : 0 - ); - - offset.top -= Math.min( - offset.top, - offset.top + dpHeight > viewHeight && viewHeight > dpHeight ? Math.abs(dpHeight + inputHeight - extraY) : extraY - ); + // Get editor container + const rootElm = document.querySelector('.gjs-editor-cont'); + + // Ensure DOM elements are not a collections + let offsetElm = input.length ? input[0] : input; + picker = picker.length ? picker[0] : picker; + + // Get the input position + let rect = offsetElm.getBoundingClientRect(); + + // Accuumulate the input offset + let offset = { top: 0, left: 0, width: offsetElm.offsetWidth, height: offsetElm.offsetHeight }; + while (offsetElm) { + // Accumulate offsets + offset.top += offsetElm.offsetTop - offsetElm.scrollTop; + offset.left += offsetElm.offsetLeft - offsetElm.scrollLeft; + + // Check if the current element in our root, or if the next offset parent is outside of the root + if (offsetElm === rootElm || !rootElm.contains(offsetElm.offsetParent)) { + break; // Exit the loop if we are at root element + } + + // Move to the next offset parent + offsetElm = offsetElm.offsetParent; + } + + // Input is to close to the right side of the screen to show picker + if (rect.right + picker.offsetWidth > window.innerWidth - window.scrollX && rect.right - picker.offsetWidth > 0) { + // Right align the picker to the input + offset.left -= picker.offsetWidth - offset.width; + } + + // Input is to close to the bottom of the screen to show picker above + if (rect.bottom + picker.offsetHeight < window.innerHeight - window.scrollY) { + // Bottom align the picker to the input + offset.top += offset.height; + } else { + // Top align the picker to the input + offset.top -= picker.offsetHeight; + } return offset; }