Skip to content

Instantly share code, notes, and snippets.

@hlfbt
Last active September 7, 2016 12:07
Show Gist options
  • Save hlfbt/7f2ca2468a51adb70cf5 to your computer and use it in GitHub Desktop.
Save hlfbt/7f2ca2468a51adb70cf5 to your computer and use it in GitHub Desktop.
A stupid simple framework just like jquery that mainly grew out of procrastination. I use this wherever the jquery way is much more elegant/easier but there is no jquery available (i.e. in a userscript before the page completely loaded). May be expanded every now and then as I deem fit.
/*/
* This simulates JQuery's constructor functionality as best as easiest possible
* Some minor things that I never really use (like calling select() without arguments,
* or some ambiguous css paths not being interpreted by querySelectorAll correctly)
* might not really work, but I personally don't see much need to make it more complicated
* to work around them currently.
/*/
var select = function (s, c) {
if (!c || c == null)
c = document;
if (s instanceof HTMLElement)
return new Array(s);
if (s instanceof HTMLCollection || s instanceof NodeList || s instanceof Array)
return [].slice.call(s);
if (typeof s === "string") {
try {
if(s == '') s = '*';
return c.querySelectorAll(s);
} catch(e) {
try {
return s.toDOM();
} catch(e) {}
}
}
throw new TypeError("Invalid argument '" + ({}).toString.call(s) + "'");
};
// Turn a string into DOM Elements
String.prototype.toDOM = function() {
var i, d = document,
r = d.createDocumentFragment(),
e = d.createElement('div');
e.innerHTML = this;
while (i = e.firstChild)
r.appendChild(i);
delete i, e;
return r.childNodes;
};
// Do some JQuery style autoconstructor shenanigans
var s = function (__, c) {
return new s.init(__, c);
};
// The actual constructor
s.init = function (__, c) {
this._ = (__ instanceof s.init) ? __._ : [].slice.call(select(__, c)); this.î();
};
// Turns the object into an array-like
s.init.prototype.î = function() {
var o = this._.reduce(function(o, v, i) {
o[i] = v; return o;
}, {});
for (var i in o)
o[i] = {
value: o[i],
configurable: true
};
this.length = this._.length;
Object.defineProperties(this, o);
};
// Correct splicing!
s.init.prototype.splice = function() {
return s([].splice.apply(this._, arguments));
};
// Correct slicing!
s.init.prototype.slice = function() {
return s([].slice.apply(this._, arguments));
};
// Arrays!
s.init.prototype.toArray = function () {
return this._;
};
/*/
* At first I mistakingly designed all functions to modify the selected Elements in-place
* Only later on have I noticed that that wouldn't let one do stuff like:
* > var sel = s('div');
* > sel.children().remove();
* > sel.append(newChildren);
* Since sel's selection will have shifted over to the children (which get deleted).
* So for most functions I adapted it to always return a new s() Object instead,
* which seems to be what JQuery does as well.
* There are still some functions that "need" in-place modifications though, like clone() or add(),
* because I'm not sure myself (due to lack of using JQuery enough) which functions exactly do in-place
* and which don't, I've gone by what would seem most natural to me.
* If you spot anything that works differently in JQuery, feel free to point it out to me!
/*/
/*/
* IN-PLACE
/*/
s.init.prototype.each = function (_f, _t) {
for (var _i = 0, _e = null; _e = this[_i]; _i++)
_f.call((_t == null) ? _e : _t, _i, _e);
return this;
};
s.init.prototype.add = function (_s) {
s(_s).each(function (i, e) {
if (this._.indexOf(e) < 0)
this._.push(e);
}, this);
this.î();
return this;
};
s.init.prototype.clone = function (o) {
this.each(function (i, e) {
var n = e.cloneNode();
n.innerHTML = e.innerHTML;
if (o !== undefined)
for (var a in o)
n[a] = o[a];
this._[i] = n;
}, this);
this.î();
return this;
};
s.init.prototype.append = function (e) {
s(e).each(function (i, e) {
this.each(function(j){
this._[j].appendChild(s(e).clone()[0]);
}, this);
}, this);
this.î();
return this;
};
s.init.prototype.prepend = function (e) {
s(e).each(function (i, e) {
this.each(function (j) {
this._[j].insertBefore(s(e).clone()[0], this._[j].firstChild);
}, this);
}, this);
this.î();
return this;
};
s.init.prototype.remove = function () {
this.each(function () {
this.parentNode.removeChild(this);
});
this.length = 0;
return this;
};
/*/
* REPRODUCTIVE
/*/
s.init.prototype.replaceWith = function (e) {
var _ = [];
this.each(function (j) {
e = s(e).clone();
var p = this._[j].parentNode;
p.replaceChild(e[0], this._[j]);
_.push(e);
e.slice(1).each(function (k, ei) {
p.insertBefore(ei, _.slice(-1)[0].nextSibling);
_.push(ei);
}, this);
}, this);
return s(_);
};
s.init.prototype.parent = function (_s) {
var _ = [];
this.each(function (i, e) {
if (!_s || _s == null) {
_.push(e.parentElement);
} else if (typeof _s === "function") {
s(e).parent().each(function (ii, ee) {
if (_s.call(ee, ii, ee))
_.push(ee);
}, this);
} else if (typeof _s === "number") {
for (var j = _s; j > 0; j--)
e = (e.parentElement) ? e.parentElement : e;
_.push(e);
} else {
s(_s, e.parentElement).each(function (ii, ee) {
if (ee == e.parentElement)
_.push(ee);
}, this);
}
}, this);
return s(_);
};
s.init.prototype.children = function (_s) {
var _ = [];
this.each(function (i, e) {
if (!_s || _s == null) {
_ = _.concat([].slice.call(e.children));
} else if (typeof _s === "function") {
s(e).children().each(function (ii, ee) {
if (_s.call(ee, ii, ee))
_.push(ee);
}, this);
} else if (typeof _s === "number") {
e = s(e);
for (var j = _s; j > 0; j--)
e = e.children();
_.push(e);
} else {
s(_s, e).each(function (ii, ee) {
if (ee.parentElement == e)
_.push(ee);
}, this);
}
}, this);
return s(_);
};
s.init.prototype.find = function (_s) {
var _ = [];
this.each(function (i, e) {
_ = _.concat(s(_s, e).toArray());
}, this);
return s(_);
};
s.init.prototype.filter = function (_f) {
var _ = [];
this.each(function (i, e) {
if (!_f || _f == null) {
return this;
} else if (typeof _f === "function") {
if (_f.call(e, i, e))
_.push(e);
} else {
s(_f, e).each(function (ii, ee) {
if (ee == e)
_.push(e);
}, this);
}
}, this);
return s(_);
};
var select = function (s, c) { if(!c || c == null) c = document; if(s instanceof HTMLElement) { return new Array(s); } if(s instanceof HTMLCollection || s instanceof NodeList || s instanceof Array) { return [].slice.call(s); } if(typeof s === "string") { try { if(s == '') s = '*'; return c.querySelectorAll(s); } catch(e) { try { return s.toDOM(); } catch(e) {} } } throw new TypeError("Invalid argument '" + ({}).toString.call(s) + "'"); };
String.prototype.toDOM = function() { var i, d = document, r = d.createDocumentFragment(), e = d.createElement('div'); e.innerHTML = this; while(i = e.firstChild) r.appendChild(i); delete i, e; return r.childNodes; };
var s = function (__, c) { return new s.init(__, c); };
s.init = function (__, c) { this._ = (__ instanceof s.init)? __._ : [].slice.call(select(__, c)); this.î(); };
s.init.prototype.î = function() { var o = this._.reduce(function(o, v, i) { o[i] = v; return o; }, {}); for(var i in o) o[i] = {value: o[i], configurable: true}; this.length = this._.length; Object.defineProperties(this, o); };
s.init.prototype.splice = function() { return s([].splice.apply(this._, arguments)); };
s.init.prototype.slice = function() { return s([].slice.apply(this._, arguments)); };
s.init.prototype.each = function (_f, _t) { for (var _i=0, _e=null; _e=this[_i]; _i++) _f.call((_t==null)?_e:_t, _i, _e); return this; };
s.init.prototype.toArray = function () { return this._; };
s.init.prototype.add = function (_s) { s(_s).each(function(i, e){ if(this._.indexOf(e) < 0) this._.push(e); }, this); this.î(); return this; };
s.init.prototype.clone = function (o) { this.each(function(i, e){ var n = e.cloneNode(); n.innerHTML = e.innerHTML; if(o !== undefined) for (var a in o) n[a] = o[a]; this._[i] = n; }, this); this.î(); return this; };
s.init.prototype.replaceWith = function (e) { var _ = []; this.each(function (j){ e = s(e).clone(); var p = this._[j].parentNode; p.replaceChild(e[0], this._[j]); _.push(e); e.slice(1).each(function (k, ei){ p.insertBefore(ei, _.slice(-1)[0].nextSibling); _.push(ei); }, this); }, this); return s(_); };
s.init.prototype.append = function (e) { s(e).each(function(i, e){ this.each(function(j){ this._[j].appendChild(s(e).clone()[0]); }, this); }, this); this.î(); return this; };
s.init.prototype.prepend = function (e) { s(e).each(function(i, e){ this.each(function(j){ this._[j].insertBefore(s(e).clone()[0], this._[j].firstChild); }, this); }, this); this.î(); return this; };
s.init.prototype.remove = function () { this.each(function(){ this.parentNode.removeChild(this); }); this.length = 0; return this; };
s.init.prototype.parent = function (_s) { var _ = []; this.each(function(i, e){ if(!_s || _s == null) { _.push(e.parentElement); } else if(typeof _s === "function") { s(e).parent().each(function(ii, ee){ if(_s.call(ee, ii, ee)) _.push(ee); }, this); } else if(typeof _s === "number") { for(var j=_s; j>0; j--) e = (e.parentElement)? e.parentElement : e; _.push(e); } else { s(_s, e.parentElement).each(function(ii, ee){ if(ee == e.parentElement) _.push(ee); }, this); } }, this); return s(_); };
s.init.prototype.children = function (_s) { var _ = []; this.each(function(i, e){ if(!_s || _s == null) { _ = _.concat([].slice.call(e.children)); } else if(typeof _s === "function") { s(e).children().each(function(ii, ee){ if(_s.call(ee, ii, ee)) _.push(ee); }, this); } else if(typeof _s === "number") { e = s(e); for(var j=_s; j>0; j--) e = e.children(); _.push(e); } else { s(_s, e).each(function(ii, ee){ if(ee.parentElement == e) _.push(ee); }, this); } }, this); return s(_); };
s.init.prototype.find = function (_s) { var _ = []; this.each(function(i, e){ _ = _.concat(s(_s, e).toArray()); }, this); return s(_); };
s.init.prototype.filter = function (_f) { var _ = []; this.each(function(i, e){ if(!_f || _f == null) { return this; } else if(typeof _f === "function") { if(_f.call(e, i, e)) _.push(e); } else { s(_f, e).each(function(ii, ee){ if(ee == e) _.push(e); }, this); } }, this); return s(_); };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment