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 ing 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 overe this problem.
Any help would be appreciated!!
Thanks
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 ing 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 overe this problem.
Any help would be appreciated!!
Thanks
Share Improve this question edited Oct 20, 2016 at 15:00 plawres asked Oct 19, 2016 at 18:36 plawresplawres 3135 silver badges19 bronze badges 10-
Can you include the code which uses
SetInterval
to call this function? – EhsanT Commented Oct 19, 2016 at 20:58 - I've added this to my original post now. – plawres Commented Oct 20, 2016 at 15:01
-
1
try to not change the dom, e.g HTML elements, but only there actual content. A quick test would be to
$( "p:contains('London, England')" ).text(..)
instead of .html() .. and see if it still scrolls. – user5542121 Commented Oct 20, 2016 at 15:07 - also your event listener does nothing, you are not suppressing it way up there on the docu – Boris B. Commented Oct 20, 2016 at 16:13
- 1 Do you have a live version of this page that we can see the problem? or can you make a fiddle of this page? – EhsanT Commented Oct 20, 2016 at 17:41
2 Answers
Reset to default 9 +50The problem
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>
Solution
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)
Performance
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 ...
// ...
}
Final result
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.
I would move the showLocalTime function into the immediately invoked anonymous function, and call it before the setTimeOut call, that way it displays time at load as well as after 1 second.
I made this fiddle of your code to see if I could reproduce your auto scrolling issue, this code does not cause that on JSFiddle.
Here is the JSFiddle: https://jsfiddle/workingClassHacker/xhrfoznj/10/
Here is the code:
$(function() {
var londonP = $("p:contains('London, England')");
var showLocalTime = function() {
timeDisplay.textContent = moment().tz("Europe/London").format('HH:mm:ss z');
}
londonP.html('<strong>Location</strong><br/>London, England (<span></span>)');
var timeDisplay = londonP.find('span')[0];
showLocalTime();
setInterval(showLocalTime, 1000);
});