@@ -113,6 +113,29 @@ function RemoteFunctions(config = {}) {
113113 return event . ctrlKey ;
114114 }
115115
116+ /**
117+ * This is a checker function for editable elements, it makes sure that the element satisfies all the required checks
118+ * - When onlyHighlight is false → config.isLPEditFeaturesActive must be true
119+ * - When onlyHighlight is true → config.isLPEditFeaturesActive can be true or false (doesn't matter)
120+ * @param {DOMElement } element
121+ * @param {boolean } [onlyHighlight=false] - If true, bypasses the isLPEditFeaturesActive check
122+ * @returns {boolean } - True if the element is editable else false
123+ */
124+ function isElementEditable ( element , onlyHighlight = false ) {
125+ if ( ! config . isLPEditFeaturesActive && ! onlyHighlight ) {
126+ return false ;
127+ }
128+
129+ if ( element && // element should exist
130+ element . hasAttribute ( "data-brackets-id" ) && // should have the data-brackets-id attribute
131+ element . tagName !== "BODY" && // shouldn't be the body tag
132+ element . tagName !== "HTML" && // shouldn't be the HTML tag
133+ ! _isInsideHeadTag ( element ) ) { // shouldn't be inside the head tag like meta tags and all
134+ return true ;
135+ }
136+ return false ;
137+ }
138+
116139 // helper function to check if an element is inside the HEAD tag
117140 // we need this because we don't wanna trigger the element highlights on head tag and its children
118141 function _isInsideHeadTag ( element ) {
@@ -224,9 +247,9 @@ function RemoteFunctions(config = {}) {
224247 * @param {DOMElement } element - the HTML DOM element that was clicked. it is to get the data-brackets-id attribute
225248 */
226249 function _handleDeleteOptionClick ( event , element ) {
227- const tagId = element . getAttribute ( "data-brackets-id" ) ;
250+ if ( isElementEditable ( element ) ) {
251+ const tagId = element . getAttribute ( "data-brackets-id" ) ;
228252
229- if ( tagId && element . tagName !== "BODY" && element . tagName !== "HTML" && ! _isInsideHeadTag ( element ) ) {
230253 window . _Brackets_MessageBroker . send ( {
231254 livePreviewEditEnabled : true ,
232255 element : element ,
@@ -245,9 +268,9 @@ function RemoteFunctions(config = {}) {
245268 * @param {DOMElement } element - the HTML DOM element that was clicked. it is to get the data-brackets-id attribute
246269 */
247270 function _handleDuplicateOptionClick ( event , element ) {
248- const tagId = element . getAttribute ( "data-brackets-id" ) ;
271+ if ( isElementEditable ( element ) ) {
272+ const tagId = element . getAttribute ( "data-brackets-id" ) ;
249273
250- if ( tagId && element . tagName !== "BODY" && element . tagName !== "HTML" && ! _isInsideHeadTag ( element ) ) {
251274 window . _Brackets_MessageBroker . send ( {
252275 livePreviewEditEnabled : true ,
253276 element : element ,
@@ -267,23 +290,12 @@ function RemoteFunctions(config = {}) {
267290 * @param {DOMElement } element - the HTML DOM element that was clicked. it is to get the data-brackets-id attribute
268291 */
269292 function _handleSelectParentOptionClick ( event , element ) {
270- if ( ! element ) {
293+ if ( ! isElementEditable ( element ) ) {
271294 return ;
272295 }
273296
274297 const parentElement = element . parentElement ;
275- if ( ! parentElement ) {
276- return ;
277- }
278-
279- // we need to make sure that the parent element is not the body tag or the html.
280- // also we expect it to have the 'data-brackets-id'
281- if (
282- parentElement . tagName !== "BODY" &&
283- parentElement . tagName !== "HTML" &&
284- ! _isInsideHeadTag ( parentElement ) &&
285- parentElement . hasAttribute ( "data-brackets-id" )
286- ) {
298+ if ( isElementEditable ( parentElement ) ) {
287299 parentElement . click ( ) ;
288300 } else {
289301 console . error ( "The TagID might be unavailable or the parent element tag is directly body or html" ) ;
@@ -1072,19 +1084,14 @@ function RemoteFunctions(config = {}) {
10721084 * @returns {boolean } - true if we should show the select parent option otherwise false
10731085 */
10741086 function _shouldShowSelectParentOption ( element ) {
1075- if ( ! element || ! element . parentElement ) {
1087+ if ( ! isElementEditable ( element ) ) {
10761088 return false ;
10771089 }
10781090
10791091 const parentElement = element . parentElement ;
1080-
1081- if ( parentElement . tagName === "HTML" || parentElement . tagName === "BODY" || _isInsideHeadTag ( parentElement ) ) {
1082- return false ;
1083- }
1084- if ( ! parentElement . hasAttribute ( "data-brackets-id" ) ) {
1092+ if ( ! isElementEditable ( parentElement ) ) {
10851093 return false ;
10861094 }
1087-
10881095 return true ;
10891096 }
10901097
@@ -1825,7 +1832,7 @@ function RemoteFunctions(config = {}) {
18251832
18261833 _handleSend : function ( event , prompt ) {
18271834 const element = this . element ;
1828- if ( ! element ) {
1835+ if ( ! isElementEditable ( element ) ) {
18291836 return ;
18301837 }
18311838 const tagId = element . getAttribute ( "data-brackets-id" ) ;
@@ -2173,10 +2180,9 @@ function RemoteFunctions(config = {}) {
21732180
21742181 function onMouseOver ( event ) {
21752182 if ( _validEvent ( event ) ) {
2176- // Skip highlighting for HTML, BODY tags and elements inside HEAD
2177- if ( event . target && event . target . nodeType === Node . ELEMENT_NODE &&
2178- event . target . tagName !== "HTML" && event . target . tagName !== "BODY" && ! _isInsideHeadTag ( event . target ) ) {
2179- _localHighlight . add ( event . target , true , false ) ; // false means no-auto scroll
2183+ const element = event . target ;
2184+ if ( isElementEditable ( element ) && element . nodeType === Node . ELEMENT_NODE ) {
2185+ _localHighlight . add ( element , true , false ) ; // false means no-auto scroll
21802186 }
21812187 }
21822188 }
@@ -2205,17 +2211,6 @@ function RemoteFunctions(config = {}) {
22052211
22062212 // helper function to clear element background highlighting
22072213 function clearElementBackground ( element ) {
2208- // make sure that the feature is enabled and also the element has the attribute 'data-brackets-id'
2209- if (
2210- ! config . isLPEditFeaturesActive ||
2211- ! element . hasAttribute ( "data-brackets-id" ) ||
2212- element . tagName === "BODY" ||
2213- element . tagName === "HTML" ||
2214- _isInsideHeadTag ( element )
2215- ) {
2216- return ;
2217- }
2218-
22192214 if ( element . _originalBackgroundColor !== undefined ) {
22202215 element . style . backgroundColor = element . _originalBackgroundColor ;
22212216 } else {
@@ -2235,36 +2230,29 @@ function RemoteFunctions(config = {}) {
22352230 return ;
22362231 }
22372232
2233+ const element = event . target ;
2234+ if ( ! isElementEditable ( element ) || element . nodeType !== Node . ELEMENT_NODE ) {
2235+ return false ;
2236+ }
2237+
22382238 // if _hoverHighlight is uninitialized, initialize it
2239- if ( ! _hoverHighlight && config . isLPEditFeaturesActive && shouldShowHighlightOnHover ( ) ) {
2239+ if ( ! _hoverHighlight && shouldShowHighlightOnHover ( ) ) {
22402240 _hoverHighlight = new Highlight ( "#c8f9c5" , true ) ;
22412241 }
22422242
22432243 // this is to check the user's settings, if they want to show the elements highlights on hover or click
2244- if ( _hoverHighlight && config . isLPEditFeaturesActive && shouldShowHighlightOnHover ( ) ) {
2244+ if ( _hoverHighlight && shouldShowHighlightOnHover ( ) ) {
22452245 _hoverHighlight . clear ( ) ;
22462246
2247- // Skip highlighting for HTML, BODY tags and elements inside HEAD
2248- // and for DOM elements which doesn't have 'data-brackets-id'
2249- // NOTE: Don't remove 'data-brackets-id' check else hover will also target internal live preview elements
2250- if (
2251- event . target &&
2252- event . target . nodeType === Node . ELEMENT_NODE &&
2253- event . target . tagName !== "HTML" &&
2254- event . target . tagName !== "BODY" &&
2255- ! _isInsideHeadTag ( event . target ) &&
2256- event . target . hasAttribute ( "data-brackets-id" )
2257- ) {
2258- // Store original background color to restore on hover out
2259- event . target . _originalBackgroundColor = event . target . style . backgroundColor ;
2260- event . target . style . backgroundColor = "rgba(0, 162, 255, 0.2)" ;
2261-
2262- _hoverHighlight . add ( event . target , false , false ) ; // false means no auto-scroll
2263-
2264- // Create info box for the hovered element
2265- dismissNodeInfoBox ( ) ;
2266- _nodeInfoBox = new NodeInfoBox ( event . target ) ;
2267- }
2247+ // Store original background color to restore on hover out
2248+ element . _originalBackgroundColor = element . style . backgroundColor ;
2249+ element . style . backgroundColor = "rgba(0, 162, 255, 0.2)" ;
2250+
2251+ _hoverHighlight . add ( element , false , false ) ; // false means no auto-scroll
2252+
2253+ // Create info box for the hovered element
2254+ dismissNodeInfoBox ( ) ;
2255+ _nodeInfoBox = new NodeInfoBox ( element ) ;
22682256 }
22692257 }
22702258
@@ -2274,23 +2262,15 @@ function RemoteFunctions(config = {}) {
22742262 return ;
22752263 }
22762264
2277- // this is to check the user's settings, if they want to show the elements highlights on hover or click
2278- if ( _hoverHighlight && config . isLPEditFeaturesActive && shouldShowHighlightOnHover ( ) ) {
2279- _hoverHighlight . clear ( ) ;
2280-
2281- // Restore original background color
2282- if (
2283- event &&
2284- event . target &&
2285- event . target . nodeType === Node . ELEMENT_NODE &&
2286- event . target . hasAttribute ( "data-brackets-id" )
2287- ) {
2288- clearElementBackground ( event . target ) ;
2265+ const element = event . target ;
2266+ if ( isElementEditable ( element ) && element . nodeType === Node . ELEMENT_NODE ) {
2267+ // this is to check the user's settings, if they want to show the elements highlights on hover or click
2268+ if ( _hoverHighlight && shouldShowHighlightOnHover ( ) ) {
2269+ _hoverHighlight . clear ( ) ;
2270+ clearElementBackground ( element ) ;
22892271 }
2290-
2291- // Remove info box when mouse leaves the element
2292- dismissNodeInfoBox ( ) ;
22932272 }
2273+ dismissNodeInfoBox ( ) ;
22942274 }
22952275
22962276 /**
@@ -2300,16 +2280,8 @@ function RemoteFunctions(config = {}) {
23002280 function _selectElement ( element ) {
23012281 // dismiss all UI boxes and cleanup previous element state when selecting a different element
23022282 dismissUIAndCleanupState ( ) ;
2303-
2304- // make sure that the feature is enabled and also the element has the attribute 'data-brackets-id'
2305- if (
2306- ! config . isLPEditFeaturesActive ||
2307- ! element . hasAttribute ( "data-brackets-id" ) ||
2308- element . tagName === "BODY" ||
2309- element . tagName === "HTML" ||
2310- _isInsideHeadTag ( element )
2311- ) {
2312- return ;
2283+ if ( ! isElementEditable ( element ) ) {
2284+ return false ;
23132285 }
23142286
23152287 // make sure that the element is actually visible to the user
@@ -2344,25 +2316,17 @@ function RemoteFunctions(config = {}) {
23442316 */
23452317 function onClick ( event ) {
23462318 dismissAIPromptBox ( ) ;
2319+ const element = event . target ;
23472320
2348- // make sure that the feature is enabled and also the clicked element has the attribute 'data-brackets-id'
2349- if (
2350- config . isLPEditFeaturesActive &&
2351- event . target . hasAttribute ( "data-brackets-id" ) &&
2352- event . target . tagName !== "BODY" &&
2353- event . target . tagName !== "HTML" &&
2354- ! _isInsideHeadTag ( event . target )
2355- ) {
2321+ // when user clicks on the HTML, BODY tags or elements inside HEAD, we want to remove the boxes
2322+ if ( _nodeMoreOptionsBox && ! isElementEditable ( element ) ) {
2323+ dismissUIAndCleanupState ( ) ;
2324+ } else if ( isElementEditable ( element ) ) {
23562325 event . preventDefault ( ) ;
23572326 event . stopPropagation ( ) ;
23582327 event . stopImmediatePropagation ( ) ;
23592328
2360- _selectElement ( event . target ) ;
2361- } else if ( // when user clicks on the HTML, BODY tags or elements inside HEAD, we want to remove the boxes
2362- _nodeMoreOptionsBox &&
2363- ( event . target . tagName === "HTML" || event . target . tagName === "BODY" || _isInsideHeadTag ( event . target ) )
2364- ) {
2365- dismissUIAndCleanupState ( ) ;
2329+ _selectElement ( element ) ;
23662330 }
23672331 }
23682332
@@ -2371,18 +2335,13 @@ function RemoteFunctions(config = {}) {
23712335 * @param {Event } event
23722336 */
23732337 function onDoubleClick ( event ) {
2374- if (
2375- config . isLPEditFeaturesActive &&
2376- event . target . hasAttribute ( "data-brackets-id" ) &&
2377- event . target . tagName !== "BODY" &&
2378- event . target . tagName !== "HTML" &&
2379- ! _isInsideHeadTag ( event . target )
2380- ) {
2338+ const element = event . target ;
2339+ if ( isElementEditable ( element ) ) {
23812340 // because we only want to allow double click text editing where we show the edit option
2382- if ( _shouldShowEditTextOption ( event . target ) ) {
2341+ if ( _shouldShowEditTextOption ( element ) ) {
23832342 event . preventDefault ( ) ;
23842343 event . stopPropagation ( ) ;
2385- startEditing ( event . target ) ;
2344+ startEditing ( element ) ;
23862345 }
23872346 }
23882347 }
@@ -2425,18 +2384,16 @@ function RemoteFunctions(config = {}) {
24252384 }
24262385 }
24272386
2428- // highlight a node
2429- function highlight ( node , clear ) {
2387+ // highlight an element
2388+ function highlight ( element , clear ) {
24302389 if ( ! _clickHighlight ) {
24312390 _clickHighlight = new Highlight ( "#cfc" ) ;
24322391 }
24332392 if ( clear ) {
24342393 _clickHighlight . clear ( ) ;
24352394 }
2436- // Skip highlighting for HTML, BODY tags and elements inside HEAD
2437- if ( node && node . nodeType === Node . ELEMENT_NODE &&
2438- node . tagName !== "HTML" && node . tagName !== "BODY" && ! _isInsideHeadTag ( node ) ) {
2439- _clickHighlight . add ( node , true , true ) ; // 3rd arg is for auto-scroll
2395+ if ( isElementEditable ( element , true ) && element . nodeType === Node . ELEMENT_NODE ) {
2396+ _clickHighlight . add ( element , true , true ) ; // 3rd arg is for auto-scroll
24402397 }
24412398 }
24422399
@@ -2455,12 +2412,7 @@ function RemoteFunctions(config = {}) {
24552412 // select the first valid highlighted element
24562413 var foundValidElement = false ;
24572414 for ( i = 0 ; i < nodes . length ; i ++ ) {
2458- if ( nodes [ i ] . hasAttribute ( "data-brackets-id" ) &&
2459- nodes [ i ] . tagName !== "HTML" &&
2460- nodes [ i ] . tagName !== "BODY" &&
2461- ! _isInsideHeadTag ( nodes [ i ] ) &&
2462- nodes [ i ] . tagName !== "BR"
2463- ) {
2415+ if ( isElementEditable ( nodes [ i ] , true ) && nodes [ i ] . tagName !== "BR" ) {
24642416 _selectElement ( nodes [ i ] ) ;
24652417 foundValidElement = true ;
24662418 break ;
@@ -3015,12 +2967,7 @@ function RemoteFunctions(config = {}) {
30152967
30162968 // Function to handle direct editing of elements in the live preview
30172969 function startEditing ( element ) {
3018- if ( ! config . isLPEditFeaturesActive
3019- || ! element
3020- || element . tagName === "BODY"
3021- || element . tagName === "HTML"
3022- || _isInsideHeadTag ( element )
3023- || ! element . hasAttribute ( "data-brackets-id" ) ) {
2970+ if ( ! isElementEditable ( element ) ) {
30242971 return ;
30252972 }
30262973
@@ -3065,7 +3012,7 @@ function RemoteFunctions(config = {}) {
30653012 // Function to finish editing and apply changes
30663013 // isEditSuccessful: this is a boolean value, defaults to true. false only when the edit operation is cancelled
30673014 function finishEditing ( element , isEditSuccessful = true ) {
3068- if ( ! config . isLPEditFeaturesActive || ! element || ! element . hasAttribute ( "contenteditable" ) ) {
3015+ if ( ! isElementEditable ( element ) || ! element . hasAttribute ( "contenteditable" ) ) {
30693016 return ;
30703017 }
30713018
@@ -3080,17 +3027,15 @@ function RemoteFunctions(config = {}) {
30803027 delete element . _editListeners ;
30813028 }
30823029
3083- if ( element . hasAttribute ( "data-brackets-id" ) ) {
3084- const tagId = element . getAttribute ( "data-brackets-id" ) ;
3085- window . _Brackets_MessageBroker . send ( {
3086- livePreviewEditEnabled : true ,
3087- livePreviewTextEdit : true ,
3088- element : element ,
3089- newContent : element . outerHTML ,
3090- tagId : Number ( tagId ) ,
3091- isEditSuccessful : isEditSuccessful
3092- } ) ;
3093- }
3030+ const tagId = element . getAttribute ( "data-brackets-id" ) ;
3031+ window . _Brackets_MessageBroker . send ( {
3032+ livePreviewEditEnabled : true ,
3033+ livePreviewTextEdit : true ,
3034+ element : element ,
3035+ newContent : element . outerHTML ,
3036+ tagId : Number ( tagId ) ,
3037+ isEditSuccessful : isEditSuccessful
3038+ } ) ;
30943039 }
30953040
30963041 // init
0 commit comments