开发者

jQuery: inserting DOM elements and attaching events

I'm working on a JQuery plugin and I am having a problem when creating DOM elements and attaching a click event to them. My code for creating the DOM elements is shown below:

    return this.each(function () {
        $this = $(this);

        $("<div class=\"" + settings.headingClass + "\">" + $this.attr("title") + "</div>").insertBefore($this).click(function () {
            alert($this.attr("title"));
        });
    });

The values of $this.attr("title") are correct when rendered on the page and the click event fires on each element however, the alert box always displays the value of $this.attr("title") for the last element.

Example:

My plugin is being applied to 3 elements with titles "Title1", "Title2" and "Title3". The generated HTML displays these titles correctly but the alert box only displays "Title3" no matter what title element I click on.

Any ideas?

Extra Information

I'm providing some extra information to help with this. I'm creating a basic expander plugin to try and get to grips with JQuery plugin development.

Example of HTML element:

<div class="MyExpander" title="Title1">
    This is my expanders content
</div>

JS to create JQuery expander:

$(".QuizExpander").expander({
    "headingClass": "ExpanderHeading"
});

Plugin code so far:

(function ($) {
$.fn.e开发者_运维百科xpander = function (options) {
    var settings = {
        "headingClass": "",
    };

    if (options) {
        $.extend(settings, options);
    }

    return this.each(function () {
        $this = $(this);

        $("<div class=\"" + settings.headingClass + "\">" + $this.attr("title") + "</div>").insertBefore($this).click(function () {
            alert($this.attr("title"));
        });
    });
};

})(jQuery);


EDIT: The reason you get this behavior is forgetting to use var with function-local variables. Failing to use var creates global variables instead.

Consequently, your $this in the click() function was the global one, not the one you defined in each().


Original answer: There are some obvious issues with your code, but in principle it should work (at least it does for me, see http://jsfiddle.net/CpeNM/).

Your code sample is either missing the relevant part, or I misunderstood the question. Anyway - here is what I think is wrong with your code in general:

return this.each(function () {
  // ALWAYS!!! use the var keyword for local variables (or global ones will be created)
  var $this = $(this);
  // use the jQuery functions to modify new DOM objects, avoid string-building
  var $div  = $("<div>").addClass(settings.headingClass).attr("title", $this.attr("title"));

  $div.insertBefore($this).click(function () {
    // theoretically you could use 'alert($(this).text());' here
    alert($this.attr("title"));
  });
});​


In every walk-trough of this.each(), $this gets overridden. So you have to say something like this (if the following this is a jQuery object, else you'll have to wrap a $() around it):

return this.before(
  $('<div class="' + settings.headingClass + '">' + this.attr("title") + '</div>')
  .click(function() {
     alert(this.attr("title"));
  });
});


return this.each(function () {
    $this = $(this);
    $("div", $(this)).live('click', function () {
        alert($this.attr("title"));
    });

    $("<div class=\"" + settings.headingClass + "\">" + $this.attr("title") + "</div>").insertBefore($this);
});

Basically, I'm splitting it up into two calls. live() doesn't require the DOM element to exist for the event to apply.

http://api.jquery.com/live/

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜