Replaying scroll events for every element in iframe - javascript

I maintain a library, react-to-print. The library provides a React component that at its core has two inputs: a trigger (usually a button), and content. When the trigger is clicked, the library will copy the entire DOM representation of the content and put it into an iframe. It will also copy all style links on the page to ensure the content is styled correctly within the iframe.
A while ago, someone raised an issue (the end of the thread explains the core problem) concerning the library's seaming inability to print content that was horizontally scrolled, in this case, within a table. It turns out that what is actually happening is that a component within the content is virtualizing its render, meaning only content this is visible on the screen is actually being rendered. So the issue is that react-to-print is not maintaining the scroll positions of child elements when it copies them into the iframe.
I know how to scroll the entire page itself inside of an iframe, but do not know how to maintain the scroll of individually scrolled DOM elements that are children of the window. Is there a way to do that?
While an ideal solution would of course be just turn on a setting or something and done, I'm guessing that, if a solution is possible, it will look something like:
Iterate over every element on the page
If the element has a scroll, save its scroll position in a map
Copy over the elements into the iframe (as is currently done)
Iterate over every element in the iframe and apply a scroll if one is found for it in the map

Related

Scroll problems with too many elements in the DOM

I am having problems with scrolling on a project I am working on. I have a large number of images in the DOM which I think is causing the scrolling to be slow and making the page judder.
I dont want to remove any of these images from the DOM, I would like to know if there is a way that I can replace these images with a temporary placeholder and then only render the correct image as soon as the element scrolls into view.

Display how css is being added inline from javascript

I am trying to find out how some inline css is being added to my html when the page is scrolled down.
I am using chrome dev tools. I think it is supposed to be in console, but I don't see anything show up in there when I scroll the page and know that the javascript is being fired. I assume it is javascript.
When I scroll down the page the header size shrinks to a set amount of pixels. I want to change that number but I can't find the source of what is causing the change.
Inspect element that gets inline styles set.
Right click on it in the Elements tab.
Choose Break on.. -> Attributes Modification.
Scroll the page.
JavaScript execution will stop on line that modifies any of the attributes (including 'style').
If you'll end up in the middle of jQuery/Angular/etc. - look at the Call Stack in the Sources Panel. It should reveal the higher-level code that modifies the styles.

Absolutely positioned block againt any element in the document

Example code: http://jsfiddle.net/ZAm2A/3/
The goal is to position certain popup(div.absolute-block) window against(relative to) any dom element on any page with different html structure.
In order to be able to position popup absolutely, we need to embed it into that dom element, having previously wrapped div.absolute-block with relatively or absolutely positioned block (div.relative1 in our example).
The trouble is that if dom element, we embedded popup in, has block with overfillw: hidden (div.overflow1) among it's ancestors, div.overflow1 will probably crop popup. div.overflow1 may be positioned relatively and we cannot influence it in our situation.
The second approach is to append our popup to page body. In this case we face problem of positioning our popup relatively to certain dom element. We can calculate and set top and left properties for popup on document ready event. But in case of window resizing, ajax content changes or any events changing position of tracked element we have to recalculate popup position.
I think whether there could be some new html 5 features that will let me position popup without embedding it into dom element, i want to position popup relative to? Any other ideas are appreciated.
There's no way to have a child element escape a parent element that has overflow set to hidden. If you want to have an element positioned exactly over the top of a certain element on the page, your safest option is to put it at the root of the document, use Javascript to calculate and adjust the position, and update on window resize, etc. You might be interested in using jQuery's position() (relative to parent) or offset() (relative to entire document) methods to help calculate this.
Also, here's a somewhat-related question on the overflow: hidden issue which might help: Make child visible outside an overflow:hidden parent

Performance with infinite scroll or a lot of dom elements?

I have a question on a big # of dom elmenets and performance.
Let's say I have 6000 dom elements on a page and the number of the elements can be increased as a user interact with the page (user scrolls to create a new dom element) like twitter.
To improve the performance of the page, I can think of only two things.
set display to none to invisible items to avoid reflow
remove invisible items from the dom then re-add them as needed.
Are they any other ways of improving a page with a lot of dom elements?
We had to deal with a similar problem on FoldingText. As the document grew larger, more line elements and associated span elements were created. The browser engine just seemed to choke, and so a better solution needed to be found.
Here's what we did, may or may not be useful for your purposes:
Visualize the entire page as a long document, and the browser viewport as the lens for a specific part of the long document. You really only have to show the part within the lens.
So the first part is to calculate the visible view port. (This depends on how your elements are placed, absolute / fixed / default)
var top = document.scrollTop;
var width = window.innerWidth;
var height = window.innerHeight;
Some more resources to find a more cross-browser based viewport:
How to get the browser viewport dimensions?
Cross-browser method for detecting the scrollTop of the browser window
Second, you need a data structure to know which elements are visible in that area
We already had a balanced binary search tree in place for text editing, so we extended it to manage line heights too, so this part for us was relatively easy. I don't think you'll need a complex data structure for managing your element heights; a simple array or object might do fine. Just make sure you can query heights and dimensions easily on it. Now, how would you get the height data for all your elements. A very simple (but computationally expensive for large amounts of elements!)
var boundingRect = element.getBoundingClientRect()
I'm talking in terms of pure javascript, but if you're using jQuery $.offset, $.position, and methods listed here would be quite helpful.
Again, using a data structure is important only as a cache, but if you want, you could do it on the fly (though as I've stated these operations are expensive). Also, beware of changing css styles and calling these methods. These functions force redraw, so you'll see a performance issue.
Lastly, just replace the elements offscreen with a single, say <div> element with calculated height
Now, you have heights for all the elements stored in your Data structure, query all the elements that lie before the visible viewport.
Create a <div> with css height set (in pixels) to the sum of the element heights
Mark it with a class name so that you know its a filler div
Remove all the elements from the dom that this div covers
insert this newly created div instead
Repeat for elements that lie after the visible viewport.
Look for scroll and resize events. On each scroll, you will need to go back to your data structure, remove the filler divs, create elements that were previously removed from screen, and accordingly add new filler divs.
:) It's a long, complex method, but for large documents it increased our performance by a large margin.
tl;dr
I'm not sure I explained it properly, but the gist of this method is:
Know the vertical dimensions of your elements
Know the scrolled view port
Represent all off-screen elements with a single div (height equal to the sum of all element heights it covers for)
You will need two divs in total at any given time, one for elements above the visible viewport, one for elements below.
Keep track of the view port by listening for scroll and resize events. Recreate the divs and visible elements accordingly
No experience myself with this, but there are some great tips here: http://engineering.linkedin.com/linkedin-ipad-5-techniques-smooth-infinite-scrolling-html5
I had a look at Facebook and they don't seem to do anything in particular on Firefox. As you scroll down, the DOM elements at the top of the page don't change. Firefox's memory usage climbs to about 500 meg before Facebook doesn't allow you to scroll further.
Twitter appears to be the same as Facebook.
Google Maps is a different story - map tiles out of view are removed from the DOM (although not immediately).
It's 2019. The question is really old, but I think it is still relevant and interesting and maybe something changed as of today, as we all now also tend to use React JS.
I noticed that Facebook's timeline seems to use clusters of content which is hidden with display: none !important as soon as the cluster goes out of view, so all the previously rendered elements of the DOM are kept in the DOM, it's just that those out of view are hidden with display: none !important.
Also, the overall height of the hidden cluster is set to the parent div of the hidden cluster.
Here are some screenshots I've made:
As of 2019, what do you think about this approach? Also, for those who use React, how could it be implemented in React? It would be great to receive your opinions and thoughts regarding this tricky topic.
Thank you for the attention!

Is there a search/find event in browsers?

I'm in the middle of building a not scrollable, fixed layout website, but as usual, non conventional websites tend to have shortages. There is a scrollable news element in the page, which scrolls a div container's div childs up and down by the mousewheel. The problem arises, when someone tries to search in the page, pressing CTRL+F and the content is out of the viewport (not scrolled into view). Is there any common event, which handles the find/search inside browsers?
Im not completely certain about this, but I dont think DOM has any events that fire when a uses searches and that it a browser function that you can not hook on.
http://en.wikipedia.org/wiki/DOM_events

Categories

Resources