How to Change the HTML Content as It's Loading on the Page

How to change the HTML content as it's loading on the page

The docs on MDN have a generic incomplete example and don't showcase the common pitfalls.
Mutation summary library provides a human-friendly wrapper, but like all wrappers it adds overhead.
See Performance of MutationObserver to detect nodes in entire DOM.

Create and start the observer.

Let's use a recursive document-wide MutationObserver that reports all added/removed nodes.

var observer = new MutationObserver(onMutation);
observer.observe(document, {
childList: true, // report added/removed nodes
subtree: true, // observe any descendant elements
});

Naive enumeration of added nodes.

Slows down loading of enormously big/complex pages, see Performance.

Sometimes misses the H1 elements coalesced in parent container, see the next section.

function onMutation(mutations) {
mutations.forEach(mutation, m => {
[...m.addedNodes]
.filter(node =>
node.localName === 'h1' && /foo/.test(node.textContent))
.forEach(h1 => {
h1.innerHTML = h1.innerHTML.replace(/foo/, 'bar');
});
});
}

Efficient enumeration of added nodes.

Now the hard part. Nodes in a mutation record may be containers while a page is being loaded (like the entire site header block with all its elements reported as just one added node): the specification doesn't require each added node to be listed individually, so we'll have to look inside each element using querySelectorAll (extremely slow) or getElementsByTagName (extremely fast).

function onMutation(mutations) {
for (var i = 0, len = mutations.length; i < len; i++) {
var added = mutations[i].addedNodes;
for (var j = 0, node; (node = added[j]); j++) {
if (node.localName === 'h1') {
if (/foo/.test(node.textContent)) {
replaceText(node);
}
} else if (node.firstElementChild) {
for (const h1 of node.getElementsByTagName('h1')) {
if (/foo/.test(h1.textContent)) {
replaceText(h1);
}
}
}
}
}
}

function replaceText(el) {
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
for (let node; (node = walker.nextNode());) {
const text = node.nodeValue;
const newText = text.replace(/foo/, 'bar');
if (text !== newText) {
node.nodeValue = newText;
}
}
}

Why the two ugly vanilla for loops? Because forEach and filter and ES2015 for (val of array) could be very slow in some browsers, see Performance of MutationObserver to detect nodes in entire DOM.

Why the TreeWalker? To preserve any event listeners attached to sub-elements. To change only the Text nodes: they don't have child nodes, and changing them doesn't trigger a new mutation because we've used childList: true, not characterData: true.

Processing relatively rare elements via live HTMLCollection without enumerating mutations.

So we look for an element that is supposed to be used rarely like H1 tag, or IFRAME, etc. In this case we can simplify and speed up the observer callback with an automatically updated HTMLCollection returned by getElementsByTagName.

const h1s = document.getElementsByTagName('h1');

function onMutation(mutations) {
if (mutations.length === 1) {
// optimize the most frequent scenario: one element is added/removed
const added = mutations[0].addedNodes[0];
if (!added || (added.localName !== 'h1' && !added.firstElementChild)) {
// so nothing was added or non-H1 with no child elements
return;
}
}
// H1 is supposed to be used rarely so there'll be just a few elements
for (var i = 0, h1; (h1 = h1s[i]); i++) {
if (/foo/.test(h1.textContent)) {
// reusing replaceText from the above fragment of code
replaceText(h1);
}
}
}

How to change html content, when the page has fully loaded

You're calling the function in the setup for your "load" event.

Did you mean:

window.addEventListener("load", MyFunction);

??

How to edit a website's HTML and then have it be there when you reload but only for you?

The easiest way to do something like this would be to install a userscript manager like Tampermonkey. Then you can create a userscript for the site that changes the HTML to how you want it to be, and (if you've written the code properly) it'll automatically run every time you load the site.

For example, due to a bug in Stack Exchange's CSS/Javascript, quickly double-clicking on a snippet when it's loading results in errors, so I currently have the following userscript to fix it:

// ==UserScript==
// @name Stack Snippet Modal Fixer
// @description Prevents snippet double-clicking from breaking the snippet interface
// @author CertainPerformance
// @version 1.0.0
// @include /^https://(?:(?:(?:codereview|gamedev|codegolf|meta)\.)(?:[^/]+\.)?stackexchange\.com|(?:[^/]+\.)?stackoverflow\.com)/(?:questions/(?:\d|ask/)|posts/\d+/edit|review/(?:reopen|helper|low-quality-posts|suggested-edits)(?:/\d+|$))/
// @grant none
// ==/UserScript==

document.body.appendChild(document.createElement('style')).textContent = `
.snippet-modal {
pointer-events: auto !important;
}
`;

This uses Javascript to append a <style> tag to the document, but you can make whatever other changes you want to the document as well (like changing HTML of a page, or removing style rules of an existing inline <style>, etc).

The only limits to a userscript are the limitations of Javascript on a page, but most things one would want to tweak can probably be achieved with Javascript.

Personally, I would have a hard time browsing many of the sites I frequent without the ability to write userscripts to customize sub-optimal interfaces.

Change HTML code after page load (w/ jQuery ?)

You forgot to add ')' to your Javascript.
but i really cant realize what you are trying to do here.
any way

$(document).ready(function () { // my RegEx works well, verified it on regex101
let col_let_num = $('body').html().replace(/\bcol\b(\-[a-z]{0,2})?(\-)?([0-9]{0,2})?/i, 'col-12')
$('body').html(col_let_num)
})

Edited
here you go

$('[class*="col"]').each((i, e) => {
let classes = $(e).attr('class').split(/\s+/);

classes.forEach(v => {
let col_let_num = v.replace(/\bcol\b(\-[a-z]{0,2})?(\-)?([0-9]{0,2})?/i, 'col-12')
$(e).attr('class', col_let_num)
})
})

this should work.

Change HTML code without refreshing the page

Using jQuery (a JavaScript library) you can utilize the load() function to load the contents of another HTML file on your server and place it anywhere you want on the current page without refreshing (so you can even replace the current HTML if you like).

jQuery:

http://jquery.com/

jQuery load():

http://api.jquery.com/load/


Alternative Suggestion:

However, I know you say you can't refresh the page, but, if the only reason is because you need to keep the text in the textbox, you could use a form to POST that text to another .jsp page (or even the same .jsp page, depending on how you go about it) where it will be available to you to use at your own discretion (to put it in another textbox, for example).



Related Topics



Leave a reply



Submit