1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-15 09:34:13 +00:00

Allow event propagation while selecting only the clicked element

This commit is contained in:
Jeremie Pardou 2023-12-21 15:35:15 +01:00
parent c49591f13d
commit 6dd08432bb
2 changed files with 44 additions and 1 deletions
web-frontend/modules
builder/components/elements
core/utils

View file

@ -6,7 +6,7 @@
'element-preview--parent-of-selected': isParentOfSelectedElement,
'element-preview--in-error': inError,
}"
@click.stop="actionSelectElement({ element })"
@click="onSelect"
>
<InsertElementButton
v-if="isSelected"
@ -59,6 +59,7 @@ import AddElementModal from '@baserow/modules/builder/components/elements/AddEle
import { notifyIf } from '@baserow/modules/core/utils/error'
import { mapActions, mapGetters } from 'vuex'
import PageRootElement from '@baserow/modules/builder/components/page/PageRootElement'
import { checkIntermediateElements } from '@baserow/modules/core/utils/dom'
export default {
name: 'ElementPreview',
@ -172,6 +173,18 @@ export default {
actionDeleteElement: 'element/delete',
actionSelectElement: 'element/select',
}),
onSelect($event) {
// Here we check that the event has been emitted for this particular element
// If we found an intermediate DOM element with the class `element-preview`
// It means it hasn't been originated by this element so we don't select it.
if (
!checkIntermediateElements(this.$el, $event.target, (el) => {
return el.classList.contains('element-preview')
})
) {
this.actionSelectElement({ element: this.element })
}
},
showAddElementModal(placement) {
this.$refs.addElementModal.show({
placeInContainer: this.element.place_in_container,

View file

@ -124,3 +124,33 @@ export const doesAncestorMatchPredicate = (node, predicate, stop) => {
}
return false
}
/**
* Checks a given predicate on all intermediate DOM elements between a descendant and its ancestor.
*
* @param {HTMLElement} ancestor - The ancestor DOM element.
* @param {HTMLElement} descendant - The descendant DOM element. The function assumes that
* this is a descendant of the ancestor element.
* @param {Function} predicate - A function that takes a DOM element as an argument and returns
* a boolean. This function is called on each intermediate element
* between the descendant and the ancestor.
* @returns {boolean} - Returns true if the predicate returns true for at least one intermediate
* element between the descendant and ancestor. Otherwise, returns false.
*
* @example
* // Example usage
* const ancestorElement = document.getElementById('parent');
* const descendantElement = document.getElementById('child');
* const result = checkIntermediateElements(ancestorElement, descendantElement, (el) => {
* return el.tagName === 'DIV';
* });
* console.log(result); // Outputs true if any intermediate element is a <div>, otherwise false.
*/
export const checkIntermediateElements = (ancestor, descendant, predicate) => {
for (let el = descendant; el && el !== ancestor; el = el.parentElement) {
if (predicate(el)) {
return true
}
}
return false
}