mirror of
				https://github.com/Theodor-Springmann-Stiftung/lenz-web.git
				synced 2025-10-31 02:05:32 +00:00 
			
		
		
		
	Finsihed xml model & small bugfixes
This commit is contained in:
		
							
								
								
									
										144
									
								
								views/assets/js/head-support.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								views/assets/js/head-support.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| //========================================================== | ||||
| // head-support.js | ||||
| // | ||||
| // An extension to add head tag merging. | ||||
| //========================================================== | ||||
| (function(){ | ||||
|  | ||||
|     var api = null; | ||||
|  | ||||
|     function log() { | ||||
|         //console.log(arguments); | ||||
|     } | ||||
|  | ||||
|     function mergeHead(newContent, defaultMergeStrategy) { | ||||
|  | ||||
|         if (newContent && newContent.indexOf('<head') > -1) { | ||||
|             const htmlDoc = document.createElement("html"); | ||||
|             // remove svgs to avoid conflicts | ||||
|             var contentWithSvgsRemoved = newContent.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim, ''); | ||||
|             // extract head tag | ||||
|             var headTag = contentWithSvgsRemoved.match(/(<head(\s[^>]*>|>)([\s\S]*?)<\/head>)/im); | ||||
|  | ||||
|             // if the  head tag exists... | ||||
|             if (headTag) { | ||||
|  | ||||
|                 var added = [] | ||||
|                 var removed = [] | ||||
|                 var preserved = [] | ||||
|                 var nodesToAppend = [] | ||||
|  | ||||
|                 htmlDoc.innerHTML = headTag; | ||||
|                 var newHeadTag = htmlDoc.querySelector("head"); | ||||
|                 var currentHead = document.head; | ||||
|  | ||||
|                 if (newHeadTag == null) { | ||||
|                     return; | ||||
|                 } else { | ||||
|                     // put all new head elements into a Map, by their outerHTML | ||||
|                     var srcToNewHeadNodes = new Map(); | ||||
|                     for (const newHeadChild of newHeadTag.children) { | ||||
|                         srcToNewHeadNodes.set(newHeadChild.outerHTML, newHeadChild); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|  | ||||
|  | ||||
|                 // determine merge strategy | ||||
|                 var mergeStrategy = api.getAttributeValue(newHeadTag, "hx-head") || defaultMergeStrategy; | ||||
|  | ||||
|                 // get the current head | ||||
|                 for (const currentHeadElt of currentHead.children) { | ||||
|  | ||||
|                     // If the current head element is in the map | ||||
|                     var inNewContent = srcToNewHeadNodes.has(currentHeadElt.outerHTML); | ||||
|                     var isReAppended = currentHeadElt.getAttribute("hx-head") === "re-eval"; | ||||
|                     var isPreserved = api.getAttributeValue(currentHeadElt, "hx-preserve") === "true"; | ||||
|                     if (inNewContent || isPreserved) { | ||||
|                         if (isReAppended) { | ||||
|                             // remove the current version and let the new version replace it and re-execute | ||||
|                             removed.push(currentHeadElt); | ||||
|                         } else { | ||||
|                             // this element already exists and should not be re-appended, so remove it from | ||||
|                             // the new content map, preserving it in the DOM | ||||
|                             srcToNewHeadNodes.delete(currentHeadElt.outerHTML); | ||||
|                             preserved.push(currentHeadElt); | ||||
|                         } | ||||
|                     } else { | ||||
|                         if (mergeStrategy === "append") { | ||||
|                             // we are appending and this existing element is not new content | ||||
|                             // so if and only if it is marked for re-append do we do anything | ||||
|                             if (isReAppended) { | ||||
|                                 removed.push(currentHeadElt); | ||||
|                                 nodesToAppend.push(currentHeadElt); | ||||
|                             } | ||||
|                         } else { | ||||
|                             // if this is a merge, we remove this content since it is not in the new head | ||||
|                             if (api.triggerEvent(document.body, "htmx:removingHeadElement", {headElement: currentHeadElt}) !== false) { | ||||
|                                 removed.push(currentHeadElt); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 // Push the tremaining new head elements in the Map into the | ||||
|                 // nodes to append to the head tag | ||||
|                 nodesToAppend.push(...srcToNewHeadNodes.values()); | ||||
|                 log("to append: ", nodesToAppend); | ||||
|  | ||||
|                 for (const newNode of nodesToAppend) { | ||||
|                     log("adding: ", newNode); | ||||
|                     var newElt = document.createRange().createContextualFragment(newNode.outerHTML); | ||||
|                     log(newElt); | ||||
|                     if (api.triggerEvent(document.body, "htmx:addingHeadElement", {headElement: newElt}) !== false) { | ||||
|                         currentHead.appendChild(newElt); | ||||
|                         added.push(newElt); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 // remove all removed elements, after we have appended the new elements to avoid | ||||
|                 // additional network requests for things like style sheets | ||||
|                 for (const removedElement of removed) { | ||||
|                     if (api.triggerEvent(document.body, "htmx:removingHeadElement", {headElement: removedElement}) !== false) { | ||||
|                         currentHead.removeChild(removedElement); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 api.triggerEvent(document.body, "htmx:afterHeadMerge", {added: added, kept: preserved, removed: removed}); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     htmx.defineExtension("head-support", { | ||||
|         init: function(apiRef) { | ||||
|             // store a reference to the internal API. | ||||
|             api = apiRef; | ||||
|  | ||||
|             htmx.on('htmx:afterSwap', function(evt){ | ||||
|                 let xhr = evt.detail.xhr; | ||||
|                 if (xhr) { | ||||
|                     var serverResponse = xhr.response; | ||||
|                     if (api.triggerEvent(document.body, "htmx:beforeHeadMerge", evt.detail)) { | ||||
|                         mergeHead(serverResponse, evt.detail.boosted ? "merge" : "append"); | ||||
|                     } | ||||
|                 } | ||||
|             }) | ||||
|  | ||||
|             htmx.on('htmx:historyRestore', function(evt){ | ||||
|                 if (api.triggerEvent(document.body, "htmx:beforeHeadMerge", evt.detail)) { | ||||
|                     if (evt.detail.cacheMiss) { | ||||
|                         mergeHead(evt.detail.serverResponse, "merge"); | ||||
|                     } else { | ||||
|                         mergeHead(evt.detail.item.head, "merge"); | ||||
|                     } | ||||
|                 } | ||||
|             }) | ||||
|  | ||||
|             htmx.on('htmx:historyItemCreated', function(evt){ | ||||
|                 var historyItem = evt.detail.item; | ||||
|                 historyItem.head = document.head.outerHTML; | ||||
|             }) | ||||
|         } | ||||
|     }); | ||||
|  | ||||
| })() | ||||
		Reference in New Issue
	
	Block a user
	 Simon Martens
					Simon Martens