@@ -26,7 +26,7 @@ import { VB_EmptyBlockParentClass } from "../..";
2626type HandleBuilderInteractionParams = Omit <
2727 EventListenerHandlerParams ,
2828 "eventDetails" | "customCursor"
29- > ;
29+ > & { reEvaluate ?: boolean } ;
3030
3131type AddFocusOverlayParams = Pick <
3232 EventListenerHandlerParams ,
@@ -86,42 +86,24 @@ async function handleBuilderInteraction(
8686 }
8787
8888 const eventDetails = getCsDataOfElement ( params . event ) ;
89- visualBuilderPostMessage
90- ?. send ( VisualBuilderPostMessageEvents . MOUSE_CLICK , {
91- cslpData : eventDetails ?. cslpData ,
92- fieldMetadata : eventDetails ?. fieldMetadata ,
93- } )
94- . catch ( ( err ) => {
95- console . warn ( "Error while sending post message" , err ) ;
96- } ) ;
89+
90+ // Send mouse click post message
91+ sendMouseClickPostMessage ( eventDetails ) ;
92+
9793 if (
9894 ! eventDetails ||
9995 ! params . overlayWrapper ||
10096 ! params . visualBuilderContainer
10197 ) {
10298 return ;
10399 }
104- const { editableElement, fieldMetadata } = eventDetails ;
105100
106- if (
107- VisualBuilder . VisualBuilderGlobalState . value
108- . previousSelectedEditableDOM &&
109- VisualBuilder . VisualBuilderGlobalState . value
110- . previousSelectedEditableDOM !== editableElement
111- ) {
112- cleanIndividualFieldResidual ( {
113- overlayWrapper : params . overlayWrapper ,
114- visualBuilderContainer : params . visualBuilderContainer ,
115- focusedToolbar : params . focusedToolbar ,
116- resizeObserver : params . resizeObserver ,
117- } ) ;
118- }
101+ const { editableElement, fieldMetadata } = eventDetails ;
102+ // Clean residuals if necessary
103+ cleanResidualsIfNeeded ( params , editableElement ) ;
119104
120- // if the selected element is our empty block element, return
121- if (
122- editableElement . classList . contains ( VB_EmptyBlockParentClass ) ||
123- editableElement . classList . contains ( "visual-builder__empty-block" )
124- ) {
105+ // Return if the selected element is an empty block
106+ if ( isEmptyBlockElement ( editableElement ) ) {
125107 return ;
126108 }
127109
@@ -133,15 +115,87 @@ async function handleBuilderInteraction(
133115 VisualBuilder . VisualBuilderGlobalState . value
134116 . previousSelectedEditableDOM ;
135117 if (
136- previousSelectedElement &&
137- previousSelectedElement === editableElement
118+ isSameSelectedElement ( previousSelectedElement , editableElement , params )
138119 ) {
139120 return ;
140121 }
141122
142123 VisualBuilder . VisualBuilderGlobalState . value . previousSelectedEditableDOM =
143124 editableElement ;
144125
126+ // Add overlay and focused toolbar
127+ addOverlayAndToolbar ( params , eventDetails , editableElement ) ;
128+
129+ const { cslpValue } = fieldMetadata ;
130+
131+ toggleHighlightedCommentIconDisplay ( cslpValue , false ) ;
132+
133+ // Handle field schema and individual fields
134+ await handleFieldSchemaAndIndividualFields (
135+ params ,
136+ eventDetails ,
137+ fieldMetadata ,
138+ editableElement
139+ ) ;
140+
141+ // Observe changes to the editable element
142+ observeEditableElementChanges ( params , editableElement ) ;
143+ }
144+
145+ function sendMouseClickPostMessage ( eventDetails : any ) {
146+ visualBuilderPostMessage
147+ ?. send ( VisualBuilderPostMessageEvents . MOUSE_CLICK , {
148+ cslpData : eventDetails ?. cslpData ,
149+ fieldMetadata : eventDetails ?. fieldMetadata ,
150+ } )
151+ . catch ( ( err ) => {
152+ console . warn ( "Error while sending post message" , err ) ;
153+ } ) ;
154+ }
155+ function cleanResidualsIfNeeded (
156+ params : HandleBuilderInteractionParams ,
157+ editableElement : Element
158+ ) {
159+ const previousSelectedElement =
160+ VisualBuilder . VisualBuilderGlobalState . value
161+ . previousSelectedEditableDOM ;
162+ if (
163+ ( previousSelectedElement &&
164+ previousSelectedElement !== editableElement ) ||
165+ params . reEvaluate
166+ ) {
167+ cleanIndividualFieldResidual ( {
168+ overlayWrapper : params . overlayWrapper ! ,
169+ visualBuilderContainer : params . visualBuilderContainer ,
170+ focusedToolbar : params . focusedToolbar ,
171+ resizeObserver : params . resizeObserver ,
172+ } ) ;
173+ }
174+ }
175+ function isEmptyBlockElement ( editableElement : Element ) : boolean {
176+ return (
177+ editableElement . classList . contains ( VB_EmptyBlockParentClass ) ||
178+ editableElement . classList . contains ( "visual-builder__empty-block" )
179+ ) ;
180+ }
181+
182+ function isSameSelectedElement (
183+ previousSelectedElement : Element | null ,
184+ editableElement : Element ,
185+ params : HandleBuilderInteractionParams
186+ ) : boolean {
187+ return ! ! (
188+ previousSelectedElement &&
189+ previousSelectedElement === editableElement &&
190+ ! params . reEvaluate
191+ ) ;
192+ }
193+
194+ function addOverlayAndToolbar (
195+ params : HandleBuilderInteractionParams ,
196+ eventDetails : any ,
197+ editableElement : Element
198+ ) {
145199 addOverlay ( {
146200 overlayWrapper : params . overlayWrapper ,
147201 resizeObserver : params . resizeObserver ,
@@ -160,18 +214,20 @@ async function handleBuilderInteraction(
160214 } ) ;
161215 } ,
162216 } ) ;
163-
164- const { content_type_uid, fieldPath, cslpValue } = fieldMetadata ;
165-
166- toggleHighlightedCommentIconDisplay ( cslpValue , false ) ;
167-
217+ }
218+ async function handleFieldSchemaAndIndividualFields (
219+ params : HandleBuilderInteractionParams ,
220+ eventDetails : any ,
221+ fieldMetadata : any ,
222+ editableElement : Element
223+ ) {
224+ const { content_type_uid, fieldPath } = fieldMetadata ;
168225 const fieldSchema = await FieldSchemaMap . getFieldSchema (
169226 content_type_uid ,
170227 fieldPath
171228 ) ;
172229
173230 if ( fieldSchema ) {
174- // after field schema is available re-add disabled overlay
175231 const { isDisabled } = isFieldDisabled ( fieldSchema , eventDetails ) ;
176232 if ( isDisabled ) {
177233 addOverlay ( {
@@ -183,37 +239,39 @@ async function handleBuilderInteraction(
183239 }
184240 }
185241
186- // This is most probably redundant code, as the handleIndividualFields function
187- // takes care of this
188- // TODO: Remove this
189- // if (
190- // fieldSchema.data_type === "block" ||
191- // fieldSchema.multiple ||
192- // (fieldSchema.data_type === "reference" &&
193- // // @ts -ignore
194- // fieldSchema.field_metadata.ref_multiple)
195- // ) {
196- // handleAddButtonsForMultiple(eventDetails, {
197- // editableElement: editableElement,
198- // visualBuilderContainer: params.visualBuilderContainer,
199- // resizeObserver: params.resizeObserver,
200- // });
201- // } else {
202- // removeAddInstanceButtons({
203- // eventTarget: params.event.target,
204- // visualBuilderContainer: params.visualBuilderContainer,
205- // overlayWrapper: params.overlayWrapper,
206- // });
207- // }
208242 visualBuilderPostMessage ?. send ( VisualBuilderPostMessageEvents . FOCUS_FIELD , {
209243 DOMEditStack : getDOMEditStack ( editableElement ) ,
210244 } ) ;
211245
212246 await handleIndividualFields ( eventDetails , {
213- visualBuilderContainer : params . visualBuilderContainer ,
247+ visualBuilderContainer : params . visualBuilderContainer ! ,
214248 resizeObserver : params . resizeObserver ,
215- lastEditedField : previousSelectedElement ,
249+ lastEditedField :
250+ VisualBuilder . VisualBuilderGlobalState . value
251+ . previousSelectedEditableDOM ,
216252 } ) ;
217253}
254+ function observeEditableElementChanges (
255+ params : HandleBuilderInteractionParams ,
256+ editableElement : Element
257+ ) {
258+ const focusElementObserver = new MutationObserver ( ( mutations ) => {
259+ mutations . forEach ( ( mutation ) => {
260+ if (
261+ mutation . type === "attributes" &&
262+ mutation . attributeName === "data-cslp"
263+ ) {
264+ focusElementObserver ?. disconnect ( ) ;
265+ VisualBuilder . VisualBuilderGlobalState . value . focusElementObserver =
266+ null ;
267+ handleBuilderInteraction ( { ...params , reEvaluate : true } ) ;
268+ }
269+ } ) ;
270+ } ) ;
271+
272+ VisualBuilder . VisualBuilderGlobalState . value . focusElementObserver =
273+ focusElementObserver ;
274+ focusElementObserver . observe ( editableElement , { attributes : true } ) ;
275+ }
218276
219277export default handleBuilderInteraction ;
0 commit comments