1

I realized using jQuery for my current project is a bit over-kill as I only used ~10 methods (at most) so I decided to create a much smaller library with the API-style of jQuery.

The function for the library (called Lib), returns 3 properties:

results (contains the results of the query)
selector (contains the selector used to get the results)
length (the length of the results)

The function for the Library looks like this:

function Lib(selector, context) {
  context = context || window.document;
  if(window === this) {
    return new Lib(selector, context);
  }
  this.results = map(context.querySelectorAll(selector));
  this.selector = selector;
  this.length = results.length;
  return this;
}

Map function:

function map(collection) {
  var results = [];
  for(var i = 0; i < collection.length; i++) {
    results.push(collection[i]);
  }
  return results;
}

Every time I access the "this" object from a method in Lib.prototype I have to use this.results to modify the elements this.selector to get the selector and this.length to get the length.

Is it possible to pollute the "this" object with both elements and properties.
E.G: using the "this" object to access the elements,
the "this.selector" property to access the selector and
the "this.length" to access the length of the elements?

Also how do I implement it?

For those of you wondering here is the (COMPLETE) list of Methods:

Lib("div").html("<div id=\"div-one\">Some Awesome HTML</div>")
Lib("div").text("Some Awesome Text")
Lib("div").attr("placeholder", "Search")
Lib("div").attr("placeholder")
Lib("div").css("background-color", "#fff")
Lib("div").css("background-color")
Lib("div").on("type", function(){/* do something when div has been clicked */})
Lib("div").off("type", function(){/* do something when div has been clicked */})
Lib("div").each(function(index, value){/* loop through each div and do something with them */})
Lib("input").blur(function(){/* do something when the focus has left input */})
Lib("input").focus(function(){/* do something when input has been focused on */})

NOTE: please don't bother with support for IE<9 (IE 6-9 needs to die)

3 Answers3

0

That's good practice to assign and access properties like results, length, selector as this.prop within prototype because otherwise you won't be able to get actual values of scope your methods executed on, so basically you can and have to access them only with this.

Useful links:

Community
  • 1
  • 1
Andriy Ivaneyko
  • 20,639
  • 6
  • 60
  • 82
0

Look

var AP = []; //utility
function Lib(selector, context) {
    var me = Object.create(Lib.prototype, {
        selector: { configurable: true, value: selector }, 
        length: {writable: true, value: 0}
    });
    AP.push.apply(me, (context || document).querySelectorAll(selector));
    return me;
}

Lib.prototype.each = function(fn){
  for(var i=0, j=this.length; i<j; ++i)
    //if(false === fn(this[i], i, this)) break;
    fn(this[i], i, this);

  return this;
}
Thomas
  • 3,513
  • 1
  • 13
  • 10
  • Whats the difference between configurable and writeable, and can you explain your for loop (not the for loop's code block) in Lib.prototype.each? for example you wrote "var i=0, j=this.length; ++i" what purpose does "j" serve and why is "i" defined and incremented but not checked against anything? –  Feb 13 '16 at 08:41
  • fixed the loop, a configurable property can be overridden, but is not writable. – Thomas Feb 13 '16 at 15:27
  • Thank you for this answer I've edited it and the final code is the accepted answer below, I'm allowed to award my bounty in 23 hours when I can you'll get it :D –  Apr 05 '16 at 14:28
0

You need to push each element to this using its index like this:

function Lib(selector, context) {
  context = context || window.document;
  if(window === this) {
    return new Lib(selector, context);
  }
  results = context.querySelectorAll(selector);
  this.length = results.length;
  for(var i = 0; i < results.length; i++) {
    this[i] = results[i];
  }
  this.selector = selector;
  this.context = context;
  return this;
}
function map(collection) {
  var results = [];
  for(var i = 0; i < collection.length; i++) {
    results.push(collection[i]);
  }
  return results;
}
Lib.fn = Lib.prototype = {};
window.Lib = window.$ = Lib;

You can now do:

Lib("div") // get all divs in document
Lib("div", document) // also get all divs in document
Lib.fn.getSelector = function() {
  // you can now access individual elements using their index
  alert(this[0].selector);
};