开发者

preventing effects to be applied to the same object twice when adding objects with ajax

I'm having a little issue with an application I'm making. I have a page where the user edits a document via dragging modules into the page or "canvas" area.

http://thinktankdesign.ca/temp_img.jpg

When the page is loaded, javascript haves the modules collapsible (like above). However after the user drags in a new module the effect is applied again some new modules can collapse as well. here is the problem. each time a module loads the same effect gets applied to the modules that already can collapse. It ends up breaking their animations.

heres the code that gets executed on page load.

//make colapsible
$("h1.handle").click(function() {
    var object = $(this);
    v$(this).next().toggle("fast", colapsible_class(object));
    vreturn false;
}).addClass("open");

and heres the code that gets executed in the creation of a module via ajax

function get_module(id){
    var template = $('input[name=template]').val();
    $.post(window开发者_如何学运维.location.href, { template: template, module: id, mode: 'create' },
        function(data){
            $(data).insertBefore(".target_wrapper");

            //enable deletion of module
            $(".js_no_modules").slideUp("slow");
            $(enable_module_deletion());

            //show delete button
            $("button[name=delete]").show();

            //make colapsible
            $("h1.handle").click(function() {
                var object = $(this);
                $(this).next().toggle("fast", colapsible_class(object));
                return false;
            }).addClass("open");

        }
    );
}

I need a solid way of preventing the toggle effect to be applied to the same module twice


Use jQuery 1.3 live events instead.

//make colapsible
$("h1.handle").live("click", function() {
    var object = $(this);
    v$(this).next().toggle("fast", colapsible_class(object));
    vreturn false;
}).addClass("open");

and then eliminate the click declaration in the second block of code, changing it to $("h1.handle").addClass("open");

Live events bind all current and future matching elements with an event.


In your Ajax success handler try the following:

//make collapsible
        $("h1.handle:not(.open)").click(function() {
            var object = $(this);
            $(this).next().toggle("fast", colapsible_class(object));
            return false;
        }).addClass("open");


The best way to solve your problem is, instead of using $("h1.handle") on the AJAX callback, go for $(data).find("h1.handle"). Something like,

var x = $(data);
x.insertBefore(...);
/* your other code */
x.find('h1.handle').click(...).addClass(...);

Like that, only the newly added items will have the event bounded. The already present ones will not be touched.

If we want to answer your question instead of just solving your problem, then we have several alternatives, such as:

  • store, in your objects, that the onclick event handler has been set so that you don't set it twice
  • always bind the onclick event, but always unbind it first
  • use jQuery's live events and the addClass open only on the newly created items.

IMO, the first one is the easiest. You can accomplish it by using jQuery's data(). Then you could do something like:

$("h1.handle").each(function() {
  var me = $(this);

  // if already has click handler, don't do anything
  if (me.data('click_set') != null) { return true; }
  // otherwise, store the data and bind the click event
  me.data('click_set', true).click(function() {
   /* the code you already have on the click handler */
  }).addClass('open');
}

The second alternative involves storing the function that you pass inline to the click event binder in a variable, and then using jQuery's unbind to disable it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜