开发者

How JQuery could extend an element with another one containing event handlers?

Is there a solution to create a dummy element with its properties, methods and event handlers and extend an existing element with it ? For example :

var dummyElement = $('<div />', {
  // properties
  ...
  // methods
  ...
  // event handlers
  ...
});

and then,

$.extend( $('#myElement'), dummyElement );

Now, $('#m开发者_开发百科yElement') has the dummyElement's properties, methods and event handlers, in addition to its own.

Is it possible? How could I do that with JQuery ?

Thank you


IMO you don't need a dummy element at all. In following example I demonstrates a simple way to create an element in pure javascript.

Source Code

createElement: function (options) {
    /// <summary>Creates a document object model (DOM) element.</summary>
    /// <param name="options" type="Object">An object that contains tag name, attributes, events, properties and children.</param>

    var clone = this.extend({}, options);

    // Create element
    var e = document.createElement(clone.tag);
    delete clone.tag;

    // Assign attributes
    if (clone.attributes) {

        for (var attrib in clone.attributes) {
            e.setAttribute(attrib.replace('$', ''), clone.attributes[attrib]);
        }

        delete clone.attributes;
    }

    // Create and append children if has
    if (clone.children) {

        for (var idx in clone.children) {
            e.appendChild(this.createElement(clone.children[idx]));
        }

        delete clone.children;
    }

    // Assign event handlers
    if (clone.events) {

        for (var en in clone.events) {

            var handler = clone.events[en];

            if (handler instanceof Function)
                this.addHandler(e, en, handler);
        }

        delete clone.events
    }

    // Assign properties
    for (var prop in clone) {
        e[prop] = clone[prop];
    }

    return e;

},

addHandler: function (element, eventName, handler) {

    // Firefox is first, Of cource after chrome :p
    if (element.addEventListener) {
        element.addEventListener(eventName, handler, false);
    }
    else if (element.attachEvent) {
        element.attachEvent('on' + eventName, handler);
    }

},

extend: function (expando, properties, override) {

    if (properties && typeof (properties) == 'object') {

        for (var prop in properties) {

            var val = properties[prop];

            if (!expando[prop] || override)
                expando[prop] = val;

        }

    }

    return expando;

}

You can rewrite the above code with jQuery to extend your element, instead of creating a new one.

Usage

Util.createElement({
    tag: 'input',
    type: 'checkbox',
    checked: this.checked,
    events: {
        change: function(e) { // ... }
    }
});


Check out jQuery's clone() method. In conjunction with replaceWith(), I think you can accomplish something close to (but not exactly) what you're looking for:

// 1- create dummy
var dummy - $('<div />');

// 2- add stuff to dummy...
// ex: adding a click handler, and an "alt" attribute
dummy.click(function(evt) { console.log("click"); }
dummy.attr("alt", "this is the alt text for dummy");

// 3- clone dummy, and the replace `#myElement` with the clone
$('#myElement').replaceWith( dummy.clone(true) );

Note: the code you've used when creating dummyElement in your example, is not a valid form of the jQuery function. As far as I know, you can't add properties, methods, and handlers by just passing them as a second argument to the jQuery function. If you do pass a second argument, jQuery will interpret this as a context in which to resolve the selector. I've shown an example of adding a click handler, and an attribute.


Edit: If you're just trying to copy object properties (as you said: "properties", "methods", and "event handlers") from one HTML Element to another, then $.extend(...) is the tool for the job. Just be sure you're operating on the HTML Elements themselves, not the Jquery set objects. That'll look something like this:

var dummy = $('<div />');
var myElement = $('#myElement');
$.extend(myElement.get(0), dummy.get(0));


Ok. Thanks to the different answers, particularly from Lee. It seems that the $.extend(...) jQuery method is not designed to extend a DOM element from another one. But it can extend a DOM element from an object. Here is a solution to do that :

1) First I create the extension objects. Each of these extensions must have an initExtension() method defined. Here is an example for creating two extension objects :

var myObjExtension1 = {
  // constructor
  initExtension : function() {
    // Add some data properties
    this.something = 'something';

    // Add some method properties
    this.doSomething = function() { alert(this.something); };

    // Add some DOM elements
    $(this).append('<div>element created from extension 1</div>');  

    // Add some event handlers
    $(this).click(
      function(evt) {
        $(this).append('<div>element created from extension 1 click event</div>');
      }
    );
  }
};

var myObjExtension2 = {
  // constructor
  initExtension : function() {
    // Add some data properties
    this.more = 'more';

    // Add some method properties
    this.doMore = function() { alert(this.more); };

    // Add some DOM elements
    $(this).append('<div>element created from extension 2</div>');  

    // Add some event handlers
    $(this).click(
      function(evt) {
        $(this).append('<div>element created from extension 2 click event</div>');
      }
    );
  }
};

2) In order to extend easily all the elements I need to extend, I created a little jQuery plug-in. This plug-in contains one method that extend the source element with the specified extension:

(function($){
  $.fn.extendWith = function( objExtension ) {
    this.each( 
      function(index) {
        $.extend( this, objExtension );
        this.initExtension();
      }
    );
    return this; // jQuery chaining
  }
})(jQuery);

3) Finally, I extend some jQuery elements. Note that in the following example, I extend the elements that match the someElement class, first with the myObjExtension1 and then with the myObjExtension2, by chaining the extendWith(...) plug-in method:

$('.someElement').extendWith( myObjExtension1 ).extendWith( myObjExtension2 );

Now, all the myObjExtension1 and myObjExtension2 data properties, method properties and event handlers are available from my $('.someElement') elements. Example:

$('.someElement').each( function() {
  this.doSomething();
  this.doMore();
});
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜