I am using a Squarespace website with a specific template that uses an index page and sub pages as the contents of the index page. (The pages are scrollable one after the other). I guess anchors are being used by Squarespace to scroll to relevant page from the index page.
I added a javascript to show the current time and update it every second (moment.js and moment-timezone). I am updating the time every second with SetInterval(function_name,1000);
The time is updating correctly every second. However, this causes the particular page where I am updating the time to keep coming into focus when trying to scroll up or down (it happens every second). So If i try to scroll up or down from that particular page where the time is updating, it keep scrolling automatically back to that page every second!!.
It seems there is an event triggering every second which causes this. The actual function that I am calling every second is the following:
function showLocalTime() {
var momentLondon = moment().tz("Europe/London").format('HH:mm:ss z');
// The location label HTML
var locationHTML = '<strong>Location</strong><br>';
// The HTML string for london, England
var londonHTML = 'London, England';
$( "p:contains('London, England')" ).html(locationHTML + londonHTML + ' (' + momentLondon + ')');
}
Therefore, All I am doing is changing the innerHTML of a particular HTML element to show the current time.
I am calling the above function as follows:
<script>
$(function() {
document.addEventListener("DOMSubtreeModified", function(){
return;});
window.setInterval(showLocalTime, 1000); // update it periodically
});
</script>
However, as I said, the repeated call to the above function through SetInterval causes the webpage to keep autoscrolling to this section of the website (Contacts Page) every second!!.
I can see that there is an event DOMSubtreeModified being triggered every time I call the above function. I added a custom listener to DOMSubtreeModified event, but still I am still getting the same issue.
It could be that this is due to some sort of redraw event? Anyway, I cannot seem to locate the issue and I am unable to overcome this problem.
Any help would be appreciated!!
Thanks
No significant effect at all, setTimeout runs in an event loop, it doesn't block or harm execution.
setTimeout allows us to run a function once after the interval of time. setInterval allows us to run a function repeatedly, starting after the interval of time, then repeating continuously at that interval.
Set timeout would not cause stack overflow, because it is asynchronous. It will just put the callback to the event queue and not block the execution.
setInterval() The setInterval() method, offered on the Window and Worker interfaces, repeatedly calls a function or executes a code snippet, with a fixed time delay between each call. This method returns an interval ID which uniquely identifies the interval, so you can remove it later by calling clearInterval() .
You are removing and adding two DOM nodes (<strong>
and <br>
) every second with $.html()
. And this action triggers the mentioned DOMSubtreeModified
event, check the test below:
go.onclick = function() {
document.addEventListener('DOMSubtreeModified', function() {
alert('Modified');
});
test.innerHTML = '<strong>Location</strong><br>';
};
<button id=go>Test</button>
<p id=test></p>
Instead of setting html and concatenating strings with:
.html(locationHTML + londonHTML + ' (' + momentLondon + ')');
You should create a DOM node (<span>
element as example) to change only necessary things using the textContent
attribute:
go.onclick = function() {
wrapper.removeChild(go);
document.addEventListener('DOMSubtreeModified', function() {
alert('Modified');
});
setInterval(function() {
test.textContent = new Date;
}, 1000);
};
<p id=wrapper>
<button id=go>Test</button>
<span id=test></span>
</p>
In your case, it will be the momentLondon
value. (Final example at the end)
Since your function will run every second, you should save the maximun execution time as you can.
1.You can declare constant variables outside the function scope like:
var locationHTML = '<strong>Location</strong><br>';
var londonHTML = 'London, England';
function showLocalTime() {
// locationHTML ...
// londonHTML ...
// ...
}
2.Also, if a function will always give the same expected result:
$("p:contains('London, England')")
You can run it only once outside your function scope, and store the result in a variable:
var $p = $("p:contains('London, England')");
function showLocalTime() {
// $p ...
// ...
}
With all that in mind, your code will end up like this:
<script>
$(function() {
// constants
var locationHTML = '<strong>Location</strong><br>';
var londonHTML = 'London, England';
var $p = $("p:contains('London, England')");
// prepare your DOM outside showLocalTime
$p.html(locationHTML + londonHTML + ' (<span></span>)');
var span = $p.find('span')[0];
// do only necessary things within setInterval
setInterval(function showLocalTime() {
span.textContent = moment().tz('Europe/London').format('HH:mm:ss z');
}, 1000);
});
</script>
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With