2

I'm just testing out replacing a whole page with another page using JavaScript and I found this answer with document.write. As to why document.write, I needed to replace the entire HTML, including scripts and styles using the same page.

It does what I want but i can't seem to have consistency with my event handlers. My handlers are all attached to document using:

$(document).delegate(...);

Currently, I have weird results. In a fiddle I made, it attaches a handler. When clicked, the event fires, rewrites the page, runs the function again - but it doesn't attach the handler.

However in my project, I'm doing the same routine (d.w(), then add handlers). It does reattach once and handlers work, but after doing a second routine (still on the same page), it doesn't attach anymore.

So my questions are:

  • When using d.w(), do existing handlers get erased from document?
  • Are window as well as document the same after subsequent d.w()s? or are they somehow "renewed"
  • Do scripts that are already parsed stay in memory and run after subsequent d.w()s? Or do they get erased as well?
Community
  • 1
  • 1
Joseph
  • 117,725
  • 30
  • 181
  • 234
  • 1
    `$(document).find("span")` returns `1` in both cases when `patch` is run, but somehow `.delegate` does not work the second time. – pimvdb May 26 '12 at 13:58

2 Answers2

6

(The following applies to google chrome)

Only the document is cleared, the scripts in memory still stay the same. You can easily test it by setting something to a variable and see if it exists after clearing out the document with .open.

The old native handler is therefore lost from the document, but jQuery still thinks that the handler exists in its own event model. You can see it by editing the log to:

console.log('patch', JSON.stringify($.cache ));

jQuery only ever attaches a single native handler per event, so if you have a "click" event registered on document, further handlers attached with jQuery don't attach a new native handler, instead the handler is pushed into the jQuery internal handlers array.

Now, because document.open removed the native handler, but doesn't clear javascript, jQuery still thinks the native handler exists, and further .delegate only goes to the jQuery internal handler array. If you replace your handler with plain old document.onclick you will see it starts working.

You can also keep using jQuery if you add $(document).unbind() (or more robust $.cache = {};, but this is internal and subject to change) before the .delegate, so that jQuery is again synced. Otherwise it won't be, since it has no idea you called document.open.

So:

  1. Yes
  2. They are still the same objects, can be tested by saving a reference and checking that agaist document after a .open
  3. They stay in memory.

http://jsfiddle.net/wphzt/4/

Esailija
  • 138,174
  • 23
  • 272
  • 326
  • +1, thanks for the informational post. I did some debugging - the relevant code seems to be [here](https://github.com/jquery/jquery/blob/master/src/event.js#L109). The queue is still in jQuery's memory, so it won't call `addEventListener` again, but in reality the handler *has* been removed because the document is cleared. As a result, further clicks are not registered at all. – pimvdb May 26 '12 at 14:26
  • Ahh, I see. So jQuery still thinks it's there due to it's own records. That explains alot. Thanks! – Joseph May 26 '12 at 14:28
  • Interestingly, if I delete the `document` entry from `jQuery.cache` before assigning the handler... `var cache_idx = document[$.expando]; if ($.cache[cache_idx]) { delete $.cache[cache_idx]; }` ...the next attempt to invoke the handler results in an Error in Firefox `attempt to run compile-and-go script on a cleared scope @ jquery.min.js:3` Not sure what that means. http://jsfiddle.net/wphzt/5/ –  May 26 '12 at 14:33
  • ...and does the same if I delete the expando too... `delete document[$.expando];` http://jsfiddle.net/wphzt/6/ –  May 26 '12 at 14:34
  • @amnotiam would need to use unminified jQuery to debug it, but after some quick googling it seems to be a quirk with document.write in firefox. – Esailija May 26 '12 at 14:36
  • @Esailija: Ah yes, I see it behaves properly in Chrome. –  May 26 '12 at 14:38
  • @amnotiam yeah I have added a disclaimer, I cannot even use `document.write()` in firefox without getting some security error – Esailija May 26 '12 at 14:43
0

The only reason it stops working from second time onwards is because in your function you have written

document.write('<span>'+(++i)+'</span>');

In which case, next time the document doesn't have the delegate function to increment the span value but has only what you have written in the code snippet I have highlighted above. Thus, as you doubted, yes they get erased as well. Hope this helps.

Shant
  • 237
  • 1
  • 3
  • 16