views:

64

answers:

3

I have a DIV with many elements that are all clickable. Each one with it's own unique event. This DIV has a "docked" mode where it shows in some other place and layout on the page, when the mode is toggled.

I have to note that my main target browser is IE8. Many of the problems I'm facing here (SSSLLLLLOOOOWWWWW) just go away when I test on Chrome.

I was trying to use the $(...).html() method to move the HTML content to the new location. This works but the events are lost. I can use the .live() instead of .bind() but this makes all event responses about 10 time slower (remember I have MANY elements in that DIV).

Another thing I tried, is to just create content into both DIVs and bind events to both. Then I can toggle the main DIV visibility. That made the DOM creation much slower than before (still an instant on Chrome, but not on IE).

I'm looking for the "classic" way (if it exist) to perform this relocation of content on the page, while keeping the events intact.

UPDATE Think of this docking action as something similar to docking a floating window to one side of the screen in visual studio.

+2  A: 

If you are using jquery 1.4 you can use detach:

The .detach() method is the same as .remove(), except that .detach() keeps all jQuery data associated with the removed elements. This method is useful when removed elements are to be reinserted into the DOM at a later time.
<body>
    <div id='container1'>...elements with bound events...</div>
    <div id='container2'></div>
</body>
<script>
    var divs = $("#container1").children().detach(); // removes the node from the DOM
    $("#container2").empty().append(divs);
</script>

or use clone(true) if you want both divs displayed at the same time:

var divs = $("#container1").clone(true);
$("#container2").empty().append(divs);

About $.fn.live() being too slow:
You can try modifying "live" to be a little more efficient so that it would work like this:

// $.live(selector,    context,         event,   fn);
   $.live("a.explode", "div.container", "click", function(){
       alert("boom"); return false;
   });

What this should do is bind the event type to the context element WITHOUT looking for the selector elements first. Don't know if it will be useful in your case but I thought it was worth mentioning.

To speed things up even more use mousedown instead of click:

$("a").mousedown(function(){
    // do stuff...
}).click(function(){return false;});
David Murdoch
Thanks. .detach() works perfectly. Thanks for the great summary of options. Great info. I would vote up more than once if it was possible :)
Ron Harlev
+1  A: 

If you are concerned about slowness, you could just use css and move the div around to where you want?

Soufiane Hassou
I agree. This is probably what should be done.
David Murdoch
+1  A: 

If you have piles of elements that you need to attach events to, then the most efficient way is to use event delegation. .live() will work, but as you've seen, this can be slow with many elements.

Here is a simple example of listening for a click event inside a div, and checking to see if an anchor triggered it:

$("#container").click(function(e) {

  var $target = $(e.target);
  if ($target.is("a")) {
    // do some
  }

});
ScottE
Note that using $target.closest("a",this)[0] instead of $target.is("a") _may_ be better in some cases.
David Murdoch
Interesting, I'll have to profile that.
ScottE