I am struggling to make the pattern below work. I'm not interested in using a library.
function _createElement(tagNm, attr){
var el = document.createElement(tagNm);
for(var at in attr){
el.setAttribute(at, attr[at]);
}
}
//below function is not correct just for giving you idea
function _append(ele){
this.appendChild(ele)
return this;
}
// I would like to be able to achive following chaining patter with this.
var div = document.getElementById('div');
div._append( _createElement('div', {
id : 'parent', className: 'parent'
})).appendChile( _createElement('div', {
id : 'child', className: 'child'
}));
I am struggling to make the pattern below work. I'm not interested in using a library.
function _createElement(tagNm, attr){
var el = document.createElement(tagNm);
for(var at in attr){
el.setAttribute(at, attr[at]);
}
}
//below function is not correct just for giving you idea
function _append(ele){
this.appendChild(ele)
return this;
}
// I would like to be able to achive following chaining patter with this.
var div = document.getElementById('div');
div._append( _createElement('div', {
id : 'parent', className: 'parent'
})).appendChile( _createElement('div', {
id : 'child', className: 'child'
}));
Share
Improve this question
edited Feb 9, 2011 at 15:39
Anil Namde
asked Feb 9, 2011 at 15:30
Anil NamdeAnil Namde
6,61811 gold badges66 silver badges101 bronze badges
5 Answers
Reset to default 4For something like that to work, you're going to have to have some sort of object to be the focal point of the chained calls. The object would be the value of this
, in other words, in your "_append" function. An alternative would be to have your functions extend the native DOM object prototypes, but that won't work in older IE versions (and maybe not even newer ones; I'm not sure).
You could perhaps root everything in a wrapper around document.getElementById()
. You'd set up a "class" object for all your append()
and appendChild
and whatever other functions you'd like to gather up for this facility. Those functions would all go on the prototype for that:
function chainingWrapper(elem) {
this.targetElement = elem;
}
chainingWrapper.prototype = {
append: function(arg) {
// do the append operation
return this;
},
appendChild: function(arg) {
// do the appendChild operation
return this;
},
// ...
};
Now you'll have a utility to start things off:
function forElement(id) {
return new chainingWrapper(document.getElementById(id));
}
So then you could do:
var div = forElement("myDiv");
div.appendChild(xyz).append(abc);
Inside the functions like "append" you'll be able to refer to that <div>
as this.targetElement
. There are a zillion other interesting things you could do with this sort of structure, of course.
The issue that you're having is that div
(a DOM element) doesn't have a method called _append
. You can't reliably modify the prototype of DOM elements, so you can't add the method (and it would be a bad idea even if you could).
Instead, you need to create a wrapper object, and create the append
method on that:
function Appender(id) {
if (!(this instanceof Appender)) { // if the new keyword wasn't used
return new Appender(el);
}
this.element = document.getElementById(id); // create an instance variable of the element with the id passed
this.append = function(child) { // proxy the appendChild function
this.element.appendChild(child);
return this; // return the Appender object for chaining
};
}
You could then use this as follows:
Appender('div').append(_createElement('div', {
id : 'parent', className: 'parent'
})).append( _createElement('div', {
id : 'child', className: 'child'
}));
NB If you want to follow this approach, you're going to need to learn quite a bit more about Javascript's object model.
Even if you don't want to use it, you should defently take a look at some JavaScript library, like jQuery. They do exactly what you try to achieve.
jQuery does this, by putting the DOMElement inside a Wrapper and then call functions on that wrapper. These functions manipulate the given DOMObject underneath.
Your example would look like this:
var div = document.getElementById('div');
$(div).append( _createElement('div', {id : 'parent', className: 'parent'})...
And your try to implement jQuery's "$" function. The code can be found here.
It's possible to extend the DOM. Here's a working example:
HTMLElement.prototype.append = function(ele) {
return this.appendChild(ele); // returns the new child
}
function _createElement(tagNm, attr){
var el = document.createElement(tagNm);
for (var at in attr) {
el.setAttribute(at, attr[at]);
}
return el;
}
var div = document.getElementById('myDiv');
div.append(_createElement('div', {
id : 'parent', className: 'parent'
})).appendChild( _createElement('div', {
id : 'child', className: 'child'
})).appendChild(document.createTextNode("test"));
But it's probably not a good idea:
In Javascript, can you extend the DOM?
http://perfectionkills./whats-wrong-with-extending-the-dom/
What others are saying is correct. You need to some how add the method _append to your object. For example, jQuery returns a jQuery object after each call. The jQuery object has functions like .each, .ajax etc etc. It's a big wrapper.
Something like this will get you the chaining you're looking for:
function _createElement(tagNm, attr){
var el = document.createElement(tagNm);
for(var at in attr){
el.setAttribute(at, attr[at]);
}
return el;
}
function customObj(Id) {
var obj = document.getElementById(Id);
obj._append = function(el) { this.appendChild(el); return this; }
return obj;
}
// I would like to be able to achive following chaining patter with this.
var div = customObj('test');
div._append( _createElement('div', {
id : 'parent', className: 'parent'
}))._append( _createElement('div', {
id : 'child', className: 'child'
}));
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745674269a4639589.html
评论列表(0条)