I'm trying to build a Javascript library like jQuery just to learn Javascript more. So far, I've developed this:
window.jsLib = function (selector) {
var about = {
Version: 0.1
};
if (selector) {
if (window === this) {
return new jsLib(selector);
}
if (typeof selector === 'string') {
var nodes = document.querySelectorAll(selector);
for (var i = 0; i < nodes.length; i++) {
this[i] = nodes[i];
}
this.length = nodes.length;
} else if (typeof selector === 'object') {
this[0] = selector;
this.length = 1;
}
return this;
} else {
return about;
}
};
And for methods, I've developed some like:
jsLib.fn = jsLib.prototype = {
css: function (key, value) {
if (value !== undefined) {
for (var i = 0; i < this.length; i++) {
this[i].style[key] = value;
}
return this;
} else {
for (var i = 0; i < this.length; i++) {
return this[i].style[key];
}
}
},
html: function (value) {
if (value !== undefined) {
for (var i = 0; i < this.length; i++) {
this[i].innerHTML = value;
}
return this;
} else {
for (var i = 0; i < this.length; i++) {
return this[i].innerHTML;
}
}
},
on: function (type, callback) {
console.log(window.event);
for (var i = 0; i < this.length; i++) {
this[i].addEventListener(type, callback, false);
}
return this;
},
trigger: function (type) {
var event = new Event(type);
for (var i = 0; i < this.length; i++) {
this[i].dispatchEvent(event);
}
return this;
},
append: function(value) {
var old = this.html();
this.html(old + '' + value);
return this;
}
};
You may have noted that I've defined a method on
like jQuery.
Whenever I'm calling like jsLib('div#foo').on('click', someFunc);
, it is working fine.
But, suppose I have appended some html like jsLib('body').append('<a id="#bar" href="#">Click</a>');
And then I want to provide an API to add event listener to #bar
like jsLib('body').on('click', '#bar', someOtherFunc);
.
But I'm not sure how to implement this listener.
Kindly help.
From your comments I suppose you request a live implementation?
If that is the case, i wold suggest you to add a data method to your object, remember all events to be registered and register them from append method, when content is appended to the current element.
I extended your library with the .data and .live methods and queued an event registration for the next span to be added in body. See the modified code snippet and check out the console to validate.
window.jsLib = function (selector) {
var about = {
Version: 0.1
};
if (selector) {
if (window === this) {
return new jsLib(selector);
}
if (typeof selector === 'string') {
var nodes = document.querySelectorAll(selector);
for (var i = 0; i < nodes.length; i++) {
this[i] = nodes[i];
}
this.length = nodes.length;
this._selector = selector;
} else if (typeof selector === 'object') {
this[0] = selector;
this.length = 1;
}
return this;
} else {
return about;
}
};
jsLib.fn = jsLib.prototype = {
css: function (key, value) {
if (value !== undefined) {
for (var i = 0; i < this.length; i++) {
this[i].style[key] = value;
}
return this;
} else {
for (var i = 0; i < this.length; i++) {
return this[i].style[key];
}
}
},
html: function (value) {
if (value !== undefined) {
for (var i = 0; i < this.length; i++) {
this[i].innerHTML = value;
}
return this;
} else {
for (var i = 0; i < this.length; i++) {
return this[i].innerHTML;
}
}
},
on: function (type, callback) {
for (var i = 0; i < this.length; i++) {
this[i].addEventListener(type, callback, false);
}
return this;
},
trigger: function (type) {
var event = new Event(type);
for (var i = 0; i < this.length; i++) {
this[i].dispatchEvent(event);
}
return this;
},
append: function(value) {
var old = this.html(),
pendingEvents = this.data('jsLib_Future_Events') || [],
registered = {};
this.html(old + '' + value);
// Attach pending events to newly added childs (if any match found)
pendingEvents.forEach(function (evConf, i) {
[].slice.call(jsLib(this._selector + ' ' + evConf.selector), 0).forEach(function (el) {
jsLib(el).on(evConf.type, evConf.callback);
registered[i] = true;
});
}.bind(this));
// Clear list of pending requests of any registered events
this.data('sLib_Future_Events', pendingEvents.filter(function (evConf, i) { return !!registered[i]; }));
return this;
},
_data: {},
data: function (key, value) {
if (arguments.length > 1) this._data[key] = arguments[1]; // Setter
return key ? this._data[key] : this._data; // Getter of key or all
},
live: function (type, selector, callback) {
this.data('jsLib_Future_Events', (this.data('jsLib_Future_Events') || []).concat({type: type, selector: selector, callback: callback}));
return this;
}
};
jsLib('body').live('click', 'span', function () { console.debug('event triggered on appendend content after live registration of event handle'); });
jsLib('body').append('<br><span>dynamic content</span>');
<div>existing content</div>
Considerations: