Saving and reloading a DIV structure with values on page load/unload - javascript

I have a <div id="populated"> element on the page which receives dynamically created content, including populated DIVs, text areas, input texts and check boxes. Moreover, there are some elements with addEventListener.
My question is: how to save this "populated" DIV and reload it when a user returns to the page?
What I've tried, by using localStorage:
Save the entire DIV as a serialised object (got tips from here). Problem: "Uncaught TypeError: Accessing selectionDirection on an input element that cannot have a selection."
Save the entire DIV as innerHTML. Problems: 1) bind events are lost 2) already entered data in textareas/inputs is lost.
I can rebind the events, but parsing the DIV structure and storing/restoring .value for each element seemed too complicated.
I'm using "pure" JavaScript (no frameworks) and without AJAX. Any ideas, keywords?

There are basically three ways to persist data on the web:
Server-Side
Local Storage
Cookies
Now cookies have a finite limit to how much they can store (and IIRC that limit varies by browser), so if your DIV has a decent amount of stuff in it, cookies won't cut it. Local storage works for newer browsers ... if it works at all that is (you should really post your storage error as a separate SO post of its own).
As for what to store, you can basically give up on storing bound events ... unless you want to convert every one to an in-line attribute (eg. "onclick='...") and save all the HTML ... but that would be a terrible idea because inline events quickly become a nightmare. (If you only have one or two this might be an option ... but I wince at suggesting it.)
What is commonly done instead is that you serialize your data in to an structure that just contains the data (no DOM, no events, etc.). You store that (however you choose), and then when you want to "load" it you deserialize it, building any DOM elements you need and hooking up any events you want at that point. JSON.stringify (present in newer browser's, or available via Crockford's JSON library if you want to support older ones) is one option for doing this serialization, as is jQuery's serialize and serializeArray methods. Or you can roll your own solution.
So in short:
Serialize just the data you want to save (via JSON.stringify, $.serialize or $.serializeArray, or your own function)
Choose from server-side (the common approach), cookies (limited space) or local storage (only on newer browsers and you'll have to solve your error) to store it
When you get it out of storage, deserialize it, building DOM elements and binding events to those elements as needed.
Hope that helps.

It took some redesign, but I managed to solve the problem:
The structure of the DIV is stored as innerHTML on onpageonload in localStorage.
The values of the fields inside the DIV are serialised and stored in localStorage.
The binding function is independent and can be called so it parses the whole DIV.
On onbeforeunload the scrips goes through the DIV as saves the "inner HTML" and the values. While loading, the scripts checks if localStorage is empty: if not, populates the DIV, loads the values and rebind the events.

Related

Is it possible to resize the temp event added with selectMirror in FullCalendar v5.7.2?

I managed to get a temporary event making use of selectMirror in FullCalendar v5.7.2.
I was wondering if there is a way to dynamically resize this event based on user preference. I tried to access the last element of the calendar.getEvents() but this returned an already validated event.
Any feedback would be very useful for this. Thanks!
I managed to get a temporary event
...it's not really a temporary event, it's just showing you the currently selected area in a more emphatic way than the default display. (The documentation calls it a "placeholder event" but that's a bit of a misnomer really compared to its actual functionality.) Therefore none of the event-related functions are any use to you here.
The easiest way to resize it is simply for the user to go back and drag again to select a different area. However if you want to do it programmatically based on some other input from the user (e.g. via a separate datepicker control, or something like that) then you can use the select() function to change the current selection, e.g.
calendar.select(start, end)
where start and end are valid Date objects or date-parseable strings.
More info: https://fullcalendar.io/docs/Calendar-select

How to make updates in DOM elements more efficient?

I'm making a collaborative browser text editor and I have some optimizations concerns. The goal is to allow users to edit files arbitrarily long. When someone updates the file, everyone receives an update notification, which updates the editor content.
I'm interested to know what happens under the hood with the code bellow: does the program deallocates the old value content and allocates the new one every time this function is called? Ideally, what I would like to do is to have something like a 'file buffer', then I would just move the contents around as the users insert new data into it. But I don't want to lose the convenience of using the textarea element with its events and stuff.
function updateTextAreaValue(new_value) {
var my_textarea = document.querySelector("#my_textarea");
my_textarea.value = new_value;
}
The contents of a textarea are just a string. Setting a new value releases the string it used to contain (making it eligible for garbage collection), and stores the new one.
You've said you don't want to lose the convenience of a textarea element because of its "events and stuff," but a contenteditable div will have the same events, and also a DOM structure within it that you can adjust rather than replacing the entire string. And since it's HTML, it has styling, etc.
But of course, if a textarea serves your needs...

Populate big array list to drop down using Angular

I am facing an issue. I have a collection of object with size around 22K records. I need to bind this to an select element. Binding is working fine for small collection but such a big collection is freezing UI until its bind completely.
Please suggest the best I can do here....
First thing that pops to mind is using one-way data binding. That is accomplished by appending :: in front of your HTML variables like so
{{::someVar}}
This way, angular will not include someVar in its watchers.
If that is still not enough for you then you might consider writing a special type of select for your own purposes which can use something like ClusterizeJS behind it.
ClusterizeJS allows only rendering a few elements on the screen and re-rendering on scroll such that the user will never know that not all the elements already exist in the select. Couple this with a search bar and you've got yourself a very fast select.
In general it is not wise to populate a <select> element with such a huge number of records. That applies no matter which framework you are using (although it would be especially bad with Angular and two way data binding).
Where you want the user to be able to select from a large number of options, I would recommend using an 'autocomplete' style of interface, where the user types a few characters and the client fetches options that match what they have typed so far.
For example, you could use Angular-UI select

removing iframe will cause memory leaks?

I have a single page application which create and remove a number of iframe based on user input. each iframe could contain a jqgrid, a form for input submission with jquery.validate plugin etc...
the main page could access all the iframes to retrieve current operation status and some data to rebuild the main menu.
is safe to just remove the iframes or i need to .empty() the body before removing them?
EDIT:
when i say "retrieve current operation status and some data" i actually access the iframe properties using something like this
jqueryFrameObject[0].contextWindow.myCoolProperty
but never cache the object in the main page
No : jQuery takes care of removing the elements which could lead to memory leaks :
In addition to the elements themselves, all bound events and jQuery data associated with the elements are removed.
If you don't keep other pointers (including hidden ones based for example on closures), you'll be safe. Be careful not to use the native addEventListener if you don't want to keep hidden links to your removed elements.

Is it more efficient to keep DOM elements on the page or to re-render them as needed?

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.

Categories

Resources