22
loading...
This website collects cookies to deliver better user experience
If I click the copy button, I want a copy of what we see on the browser now, after the change we made. But if the style in-liner is running when I click copy button, some most surprising things can happen, because Copy With Style is nice enough to await defer_to_UI()
at intervals I've managed to change the element while it's running. Turns out that if I time this right I can get a copy that is half how the element was, and half how it is. A kind of chimera element.
To help visualise this, in a standard use-case of mine I might be presenting a whole pile of tables (they'd be leaderboards in games in case it's important, lists of players and scores), and I might want to highlight certain players, or add or remove columns from these boards and the site has plenty of options to do just that. If I make such a change within 40 odd seconds of the page being presented (during which the initial render of a very large number of such leaderboards is having their styles in-lined ready to arm a copy button) and then click the copy button, I get this chimera of a copy. The first half before the change and the last half after depending on exactly when I change options, or how many times even.
So we need to watch the element for changes, and if it changes, we have to start style in-lining process a new.
If we're making changes though and every change we make kick fires a new in-lining of styles, we could see an explosion of in-lining jobs on the event queue. And so we need not just to start style in-lining again we also need some way of telling any running style in-liner to finish, quit, stop, bail.
Copy_With_Style
, #observe_element
instantiates this MutationObserver and associates it with the element (this.element
). The observer is stored as #observer
and #mutation_handler
is the handler called when #observer
notices that element
changed.#schedule_preparation
which schedules the style in-liner to start when the DOM is ready and #schedule_observation
which schedules an observer to start when the DOM is ready. These are started by the constructor
based on the configured triggers
in Copy With Style.Copy_With_Style
instance. #is_being_prepared
which is set to true when the in-liner (prepare_copy
) starts.#is_prepared
which is set to true when it's completed successfully and this.HTML
and this.text
are set and ready to copied to the clipboard.#bail
which is set by the observer when this.element
changes and the style in-liner is running (#is_being_prepared
is true), to ask it to drop what it's doing and bail.#bailed
is set by the style in-liner to let the observer know it's done that (which it was requested to do).await defer_to_UI()
which takes on a broader meaning now, and could rightly be thought of, or called, defer_to_others()
as we use it for one function to communicate with another function.#bail
then await defer_to_UI()
to re-queue itself and give the style in-liner a chance to run and and it in turn checks #bail
whenever it continues after an await defer_to_UI()
. If it sees #bail
set, it bails, setting #bailed
first then returns (and thus comes off the queue and is no longer awaiting, has stopped processing elements). Eventually the observer's turn comes up again and it can check if #bailed
is set. If not of course it can await defer_to_UI()
again as often as needed until it is. In practice I have never seen it not honoured immediately - when the observer defers to UI it goes to the end of the queue and by definition a callback to the awaiting style in-liner is already on the queue ahead of it. #bailed
is if the in-liner fails to check #bail
and act on it when it is called back after it's deferral to UI.