I am currently using backbone to render a view. I have set an interval to update and pull the latest json, it then appends the changes and updates the corresponding DOM elements.
The problem I seem to be facing is that whenever it empties the container and then re-populates it with the updated info, it jumps to the top of the page. Is there something I can change in my view to make sure it doesnt jump after I append?
You can override your view's render() method, or you can register an event handler for the appropriate change event to handle an incremental render. Without examples, it's hard to be more specific.
I think what's happening is the content is momentarily removed, making the page shorter. The browser window is pushed up for a tiny moment, then the new content is appended, making the page longer again.
To test, try making your browser window very short and triggering the update. If the page doesn't jump, this is your issue.
I'm dealing with the same thing myself right now. My solution is to read the height of the parent element before removal, set it, then clear the set height when the new content is appended.
Related
I have a web page which is dynamically built by the client. It generates dozens of list items each with its own named anchor. The side of the page has a fixed table of contents (TOC) with hyperlinks that point to the named anchors. This allows the user to click a TOC entry a jump to the item.
The trouble I am encountering is that on the initial page load the page is dynamically generated and so it cannot scroll to the item in the initial hash of the URL using the default behavior of a browser. Additionally, when the user switches to a different book the page is completely regenerated with new content and a new starting hash. Same problem: since the hash preexists the content, it doesn't situate itself with the item already in view.
I nearly solved this with JavaScript by awaiting the rendering and then jumping to the hash using scrollIntoView method on the appropriate element.
The next problem is that the stylesheet is not fully applied by the time scrollIntoView is called and so the final position of the item is unknown. I see the unstyled item scroll into view, but once styling is applied the positioning is lost. I put a 1 second setTimeout in place to delay the scrollIntoView call. This works but feels fragile.
Are there reliable techniques for jumping to a named anchor when the content comes after the hash is in place? If I knew when the CSS was done styling content that might help. Alternately, it might be useful to trigger an event once the height of the page stabilizes (thus signaling the finalization of CSS styling).
I had a similar problem, although in my case only the table of contents and named anchors were autogenerated in the onload handler - not the rest of the page content. I solved the initial hash problem by adding the following code to my onload handler after generating the anchors:
if (location.hash)
{
var requested_hash = location.hash.slice(1);
location.hash = '';
location.hash = requested_hash;
}
I had to set the hash to '' before setting it back to the requested name to make the browser respond. This seemed to work in all the browsers I tried (Opera, Chrome, Edge, IE, FF).
You can use jQuery if you will always know the name of the element you want to set focus to. You can run this after your page has loaded:
$( "#targetElementGoesHere" ).focus();
Edit: To scroll to that, check out https://github.com/flesler/jquery.scrollTo
I think the answer you require was answered by this guy...
How to wait until a web page is loaded with javascript?
So, something like this...
document.onload = function(){
scrollIntoView...
}
In my current app there are quite some complex calculations to do after $routeChangeSuccess before the new page is really fully shown. This causes a bit of "flickering" as the content changes position and size. I'm already preloading the needed JSON and images before the route changes (via resolve in the $routeProvider).
My idea to prevent this is to stop ngView from deleting the old content before the new one gets inserted. Instead I want to insert the new content with display:none set, so the newly compiled directives can execute their linking procedures while the old route content is still showing. After this is all finished, the old content would be deleted and the new content would be displayed which would happen instantly with no flickering.
Is there a way to do this? I didn't find any option in the docs or in google where you could define such a behaviour. The only option I see now is a custom build of ngRoute where I change the ngViewFactory to my needs. But I don't really like that idea as this will be stressful when I want to upgrade my angular version etc. Maybe there's a better way?
I'm currently working on a Chrome extension that modifies content on a user's Tumblr dashboard, which uses infinite scrolling. However whenever the use scrolls down, a function needs to run again.
Here's a basic run-down of how I've got it working right now:
User loads page
Extensions modifies elements on page
User scrolls down
Triggers infinite scrolling
Next page loads below current one
More content loads
After that final step, I need step 2 to trigger again and have the new content modified.
I've tried .binding elements such as the entire <body>, the container div around the elements, and to no avail.
How do I trigger a function so that it runs when the content of a page changes (specifically the Tumblr dashboard)?
jQuery is fine, by the way.
You should set up a MutationObserver in your content script to watch for insertions of elements you want to modify.
See this question for more details.
Also, the Mutation Summary library might work well in your case.
You can try jQuery.ajaxComplete. It runs whenever there is an ajax request completed. You could have something like
$( document ).ajaxComplete(function( event, xhr, settings ) {
if (settings.url === 'tumblr.com/update') { //obviously change the update url
//do your thing
}
});
Of course the best way would be to find the actual function that gets fired on the scroll and modify it to fire yours on its success. But give that a shot.
I have a dialog box that has settings associated with it. When the user clicks the "settings" button, a form is displayed so they can modify them.
What is more efficient:
to have the settings div exist hidden on the page and display when needed
OR
to create the settings div and populate it with data when needed?
In the first scenario you don't need to create the DOM elements and populate them every time, but if there are many dialog boxes open at once (a common situation) then the amount of elements on the page is pretty large and many of them are not going to be used often. But in the second situation, elements are created and appended to the DOM which gets expensive.
I'd suggest you to "cache" your html on the page, but enforce browser to do not render it until necessary (until user request the data, or simply scroll to it). The main idea is to add your html (with data) to the page, but comment it out. For example,
<div id="cached-html">
<!--
<div>
...some custom html here
</div>
-->
</div>
Then once user requested the html, you can do the following:
var html = document.getElementById('cached-html'),
inner = html.innerHTML;
html.innerHTML = inner.substring(4, inner.length - 4);
Pros. is that you don't bother your browser with initial rendering (later you can simply user display:none to hide it again), so your page renders faster.
And another note - if your data (and as a consequence inner html) changes frequently, then it will be better to re-render it each time user request it, but if it is almost static, then hide/show should be more effective.
There can be problems either way, it depends on your page. If you already have a lot of elements on the page, it may be better load add them when you need them. If your page is already very "scripty" you may want to load the elements and show them when needed.
The real question is what would be better for your page, more script, or more dom elements.
When you have to display same setting div at multiple places.
Keeping that hidden is a better solution.
Remember that creating a new dom element or cloning a existing dom element gives almost same performance, but for code clarity/maintainence cloning or template is better.
Implementation using template: Make a template of div setting and keep that hidden:
<div class="template_setting">
Your settings(children of template_setting)
</div>
Javascript/Jquery code:
-Whenever someone opens a dialogue box, make a clone of childrens of template_setting and append to div_dialogue.
-As you may have multiple templates on the same page( which is not always true).
Apply a custom event on the id of newly created setting div.( keep id of each setting div different, you can increment each one by some character/number).
$('#dialogue_opener').click(function(event){
$('.template_setting').children().clone().appendTo(div_dialogue)
.trigger('adjustSettingID');
Consider a hybrid solution. Load the "settings" div after the page is ready. This way, the user won't feel the extra "expense", and you'll have the div ready for when you need it.
I've typically seen that rendering from JavaScript is pretty darn fast. I've built lots of "just in time" menus, grids, and forms and the users can't tell the difference. The nice thing about it is that you don't have to keep a form current, just blow it away and default everything to the data in you settings object. Makes for cleaner code in my opinion.
I'm having trouble with the drop-down navigation being flattened and completely shown for several seconds while a page is loading. It usually only shows on pages that are more info-heavy, so I'm assuming its loading the navigation really fast.
Is there a way to delay loading the navigation bar until after all of the info is loaded? I tried writing a javascript onLoad function, but that just led me to a bunch of form errors for some reason.
One simple method could be wrapping your navigation in an HTML element with attribute display:none;, then when the DOM is loaded you could remove the attribute. I think that should keep it hidden from the beginning.