PDA

View Full Version : loadScripts -- unlimited document growth?



toastr
10 Nov 2006, 7:14 AM
Can someone clarify the _parseScripts function in update?

It appears that upon each update of an element a <script> tag is added to the document. is that correct? If so, isn't it an issue if an element is constantly updated with html that contains javascript?

thanks

Animal
10 Nov 2006, 8:13 AM
Good point. If a user stays on a page a long time (as we expect him to in the new way of web apps), then there might be a lot of UpdateManager.update() calls adding scripts to the document head.

The only thing I can think of is to assign them ids in your markup, and then _loadScripts could remove any currently present scripts with that id.

jack.slocum
10 Nov 2006, 8:21 AM
Only if you set loadScripts to true and your HTML blob has script elements in it. Even then it only moves the script elements you loaded anyway. Is it a problem? No, it shouldn't be. script elements go in the head, have no rendering overhead and should be fine. If the same page ran for a week with lots of script loading and no refresh it could slow things down, but otherwise it shouldn't cause a problem. As an example the grid can render 2000 DOM elements in under a second. These are elements that have rendering overhead. So the number of elements isn't really much of an issue. If it is, then I would recommend a different approach than innerHTML for loading scripts anyway.

jack.slocum
10 Nov 2006, 8:24 AM
Animal, once the scripts themselves have ran and are no longer needed or referenced by other code the garbage collector will throw away the actual script part.

toastr
10 Nov 2006, 8:27 AM
I don't think it's too unique. Consider tabbed panels and setURL, if the content of that panel is loaded and contains javascript, then just clicking back and forth between tabs will eventually (I assume) crash the browser from runaway dom growth. Or a timed refresh.

I think prototype (which I'm in the middle of trying to replace with YUI/ext to solve my layout headaches) just does an eval on the content.

Do you know why the script is kept around rather than just being evaluated?

I haven't considered if the eval vs dom addition would change the semantics of unscoped variables or functions ( I would assume not), nor have I considered the timing issues that you seem to have hit elsewhere.

Well, I should say I haven't considered and probably don't fully appreciate JS enough yet to come to the right conclusion.

toastr
10 Nov 2006, 8:32 AM
Animal, once the scripts themselves have ran and are no longer needed or referenced by other code the garbage collector will throw away the actual script part.


But DOM performance continuously degrades, no?

jack.slocum
10 Nov 2006, 8:50 AM
I don't know. It's possible but in my experience, it doesn't. But then again I don't use global getElementsByClassName calls or stuff like that that is affected by the number of nodes in the document. getElementById would not be affected. getElementsByTagName might be if you called in on the document, but then again that is bad practice too.

On the flip side, what happens if you remove a script block while that script is still referenced?

How often are you searching for nodes in the head?

If the number of scripts appended is a concern, why are you using XHR to load scripts anyway?

toastr
10 Nov 2006, 9:21 AM
I don't know. It's possible but in my experience, it doesn't. But then again I don't use global getElementsByClassName calls or stuff like that that is affected by the number of nodes in the document.
...
On the flip side, what happens if you remove a script block while that script is still referenced?
...
If the number of scripts appended is a concern, why are you using XHR to load scripts anyway?

Well, I'm not familiar with the various implementations of the DOM. Other than Mozilla, I probably won't ever have an opportunity to be either.

Having said that, dom performance is poor enough in some browsers to make me wonder if the implementation isn't doing something dumb. Take, for example, the continuous inserts into the head. Assuming that the list of child nodes for the head is a linked list then it's not a big deal for inserts, but if it's something which must potentially do a copy as part of the insert then eventually you're going to run into noticeable performance issues just refreshing elements with embedded javascript nodes. I wasn't considering the performance implications for those parts of the tree outside the head.

Maybe I'm oversimplifying things, but with regard tp removing a script block I don't understand why the block is kept around in the first place. Let the javascript engine worry about maintaining references to the code blocks that are evaluated rather than imposing (what I would have thought are) unnecessary changes to the DOM. Those functions which are evaluated at from a XHR load will be kept around as necessary by the Javscript engine.

I have been doing this up until now with Prototype which does not appear to modify the DOM in order to provide this functionality and therefore avoids the unbound resource growth. (Who knows maybe it has other issues). However, I've really gotten addicted to the yui ext layout.

In my case it's convenient to package small amounts of markup and behavior to provide encapsulation for a particular view. That is, a page which contains its own HTML and javascript. If that page needs to change I can work directly within that page rather than digging through my own core libraries.

For example I use HTML and javascript to create forms (loaded into a dialog) which have dropdowns that are dynamically populated based on the state of a webapp (that spits out JSON). The javascript is necessary to provide initial dropdown population and cascading behavior. It's likely that a form will be loaded quite frequently throughout the life of the session.

I certainly don't need to use the load javascript functionality and I can just create my own panel to do the right thing here, I just wanted to make sure that I understood the limitation of the existing code correctly before I spend time doing the development.

jack.slocum
10 Nov 2006, 10:20 AM
You can always provide your own Renderer object to the UpdateManager that strips and evals the scripts (like prototype) instead of appending them to the head. You can even set it as the default renderer. It could be done in less than 10-15 lines of reusable JS.

Doing this you would be replacing immediate performance for long term stability with frequent script loads. That choice is yours. If you are making a large HTML update, regex'ing and the eval'ing the scripts could be expensive. The existing code lets the browser parse and render the HTML like normal and moves a dom node. Does it perform better? I would think it would, but I could be wrong.

To be honest I didn't write this code. It provided by someone and was added because so many people requested it. I think the actual implementation is better than eval'ing and regex. Why? because the actual overhead of a DOM node is not what you might think. Take a look at my DomHelper benchmark page. 3000 elements (elements that actually have a UI no less) in about 250-300 milliseconds. That's creating and inserting them 1 by 1. , not just moving them.

Does that mean I think it's ok to insert 3000 script elements in the head? Probably not the best idea. If you want to submit a patch that does clean up on those script elements and provide a test page that I can see it working in all browsers, I'd be happy to plug it in.

Personally, I have written HUGE applications that are loaded with js, ajax and widgets and I have never once loaded a single <script> element through XHR. Mixing JS in with markup is a bad idea and there is always a better solution. But, that's just my opinion.

Animal
10 Nov 2006, 10:54 AM
Mixing JS in with markup is a bad idea and there is always a better solution. But, that's just my opinion.

Yes, it's not that elegant, but what is the alternative?

Some kind of declarative (but still valid) markup which is then scanned by a javascript function which massages the DOM tree in the appropriate way to create the needed widgets?

My loaded content contains scripts which create widgets in the loaded element. The loading code knows nothing about this.

The loaded content though, is written to know that it's part of a ListManager. So part of the script written to it is setting a variable myList to it's owning ListManager. It can then call functions on it.

Like



myList.createList("where _this.code >= 'CA'")


Which is exactly what CountrySubEntity.jsp does when you type "CA" into the code field - an onchange handler is coded into the input field.

That starts the list from there. The list's load selects the first row, the onselect fires which updates all detail panels content from the selected row id.

toastr
10 Nov 2006, 11:46 AM
You can always provide your own Renderer object to the UpdateManager that strips and evals the scripts (like prototype) instead of appending them to the head. You can even set it as the default renderer. It could be done in less than 10-15 lines of reusable JS.
.....
I have never once loaded a single <script> element through XHR. Mixing JS in with markup is a bad idea and there is always a better solution. But, that's just my opinion.


I'll probably end up doing that, if for no other reason that to better understand JS. I appreciate your desire to separate presentation from execution, and in general I believe it's a good idea. For various reasons I don't think it is in my particular case.

Thanks for the time responding here (as well as the library), it's very much appreciated.

stonecracker
10 Nov 2006, 4:40 PM
Mixing JS in with markup is a bad idea and there is always a better solution. But, that's just my opinion.

Yes, it's not that elegant, but what is the alternative?



What I'm trying to do is mimic iframe with div by XHR(sometimes two level mimic with dialog div) to avoid the overhead of transfer 3rd party library again and again(loading speed of the page is critical). I can't avoid JS load at runtime. I have minor we development experience and I don't know if I doing the things so wrong.

+1 to jack's script unload concern when leaving the page.