Skip to content

Instantly share code, notes, and snippets.

@m93a
Last active December 26, 2015 13:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save m93a/7158856 to your computer and use it in GitHub Desktop.
Save m93a/7158856 to your computer and use it in GitHub Desktop.
A simple and customizable high-level JS framework
(function(){
//Shortands for global variables
window.win = window;
window.doc = win.document;
window.on = win.addEventListener;
window.rmon = win.removeEventListener;
//Underscore function
/* * * *
* How to use:
* * * *
* _(obj).count //Get number of enumerable
*
* _(obj,propertyName).getter = function(){} //Define getter...
* _(obj,propertyName).setter = function(){} //...and setter
*
* _(obj,property1).link(property2) //Link two properties of obj
* _(obj1,prop1).link(obj2,prop2) //Link obj1.prop1 and obj2.prop2
*
* //Note that two linked properties always have the same value
* //Remember which one is the source and which is a link
* //In this case source is obj1.prop1
*
* _(obj2,prop2).unlink() //Does nothing
* _(obj1,prop1).unlink() //Destroys the link
*
*/
win._ = function(){
if(
arguments.length == 2 &&
typeof arguments[0] == "object" &&
typeof arguments[1] == "string"
){
return _(arguments[0]).prop(arguments[1]);
}else if(
arguments.length == 1 &&
typeof arguments[0] == "object"
){
var obj = new (function(origin){
//_().origin
Object.defineProperty(this,"origin",{
"enumerable":true,
"value":origin
});
//_().count
Object.defineProperty(this,"count",{
"enumerable":true,
"get":function(){
var i = 0;
for(x in this.origin){
i++;
}
return i;
}
});
//_().prop
Object.defineProperty(this,"prop",{
"enumerable":true,
"value":function(str){
if(typeof str == "undefined"){return false;}
var obj = {};
//_().prop().origin
Object.defineProperty(obj,"origin",{
"enumerable":true,
"value":this.origin
});
//_().prop().property
Object.defineProperty(obj,"property",{
"enumerable":true,
"value":str
});
//_().prop().getter
Object.defineProperty(obj,"getter",{
"enumerable":true,
"get":function(){
var desc = Object.getOwnPropertyDescriptor(
this.origin,
this.property
)||{};
return desc.get;
},
"set":function(f){
var desc = Object.getOwnPropertyDescriptor(
this.origin,
this.property
)||{};
desc = {
configurable: true,
enumerable: desc.enumerable,
set: desc.set
};
desc.get = f;
Object.defineProperty(this.origin,this.property,desc);
return f;
}
});
//_().prop().setter
Object.defineProperty(obj,"setter",{
"enumerable":true,
"get":function(){
var desc = Object.getOwnPropertyDescriptor(
this.origin,
this.property
)||{};
return desc.set;
},
"set":function(f){
var desc = Object.getOwnPropertyDescriptor(
this.origin,
this.property
)||{};
desc = {
configurable: true,
enumerable: true,
get: desc.get
};
desc.set = f;
Object.defineProperty(this.origin,this.property,desc);
return f;
}
});
//_().prop().link()
Object.defineProperty(obj,"link",{
"enumerable":true,
"value":function(obj,key){
if(typeof obj=="string" && !key){
key = obj;
obj = this.origin;
}
var desc = Object.getOwnPropertyDescriptor(obj,key)
||{"enumerable":true};
Object.defineProperty(this.origin,this.property,{
"configurable":true,
"enumerable":desc.enumerable,
"get":function(){
return obj[key];
},
"set": function(value){
obj[key]=value;
}
});
return obj[key];
}
});
//_().prop().unlink()
Object.defineProperty(obj,"unlink",{
"enumerable":true,
"value":function(){
var desc = Object.getOwnPropertyDescriptor(this.origin,this.property)
||_.defaultDesc;
Object.defineProperty(this.origin,this.property,{
"configurable":true,
"enumerable":desc.enumerable,
"writeable":desc.writeable,
"value": this.origin[this.property]
});
return this.origin[this.property];
}
});
return obj;
}
});
//_().property
Object.defineProperty(
this,
"property",
Object.getOwnPropertyDescriptor(this,"prop")
);
})(arguments[0]);
return obj;
}
};
_.defaultDesc = {
"configurable":true,
"enumerable":true,
"writable":true
};
//Array extensions
/* * * *
* How to use:
* * * *
* arr.last //Get the arr's last element
* arr.last = "foo"; //Push "foo" to arr
*
* arr.last = arr.last; //Duplicate the last element
*
*/
Object.defineProperty(Array.prototype,"last",{
"get":function(){return this[this.length-1];},
"set":function(){return this[this.length]=v;}
});
//CreateElement shortand
/* * * *
* How to use:
* * * *
* doc.mkNode("span"); //New span element
* doc.mkNode("svg","http://www.w3.org/2000/svg");
* //New namespaced svg element
*
* doc.mkNode("span",{ //New span element
* class:"small", //with class attribute set to "small"
* _txt:"Foo Bar" //and "Foo Bar" in text content
* });
*/
doc.mkNode = function(n1,n2,n3){
var node, attrs;
if(typeof n2 == "string"){
node = document.createElementNS(n1,n2);
if(typeof n3 == "object"){
attrs=n3;
}
}else{
node = document.createElement(n1);
if(typeof n2 == "object"){
attrs=n2;
}
}
if(attrs){
for(attr in attrs){
if(attr == "_txt"){
node.txt = attrs[attr];
}else{
node.setAttribute(attr,attrs[attr]);
}
}
}
return node;
}
//Document shortands
doc.on = doc.addEventListener;
doc.rmon = doc.removeEventListener;
doc.query = doc.querySelector;
doc.query.all = function(){return doc.querySelectorAll.apply(doc,arguments);};
doc.exe = function(path){
return doc.body.mkChild("script",{"src":path});
};
//Modify the DOM elements
Element.prototype.rm = Element.prototype.remove;
Element.prototype.clear = function(){this.textContent="";};
Element.prototype.setAttr = Element.prototype.setAttribute;
Element.prototype.getAttr = Element.prototype.getAttribute;
Element.prototype.hasAttr = Element.prototype.hasAttribute;
Element.prototype.addAttr = function(n){this.setAttr(n,"");};
Element.prototype.rmAttr = Element.prototype.removeAttribute;
Element.prototype.on = Element.prototype.addEventListener;
Element.prototype.rmon = Element.prototype.removeEventListener;
Element.prototype.addChild = Element.prototype.appendChild;
Element.prototype.rmChild = Element.prototype.removeChild;
Element.prototype.mkChild = function(ns,tag,attrs){
//Combination of doc.mkNode and node.appendChild
var n = doc.mkNode(ns,tag,attrs);
this.addChild(n);
return n;
};
Element.prototype.putBefore = function(newelem){
return this.parent.insertBefore(newelem,this);
};
Element.prototype.putAfter = function(newelem){
return this.parent.insertBefore(newelem,this.nextSibling);
};
//TODO make this work with _().link
_(Element.prototype,"parent").getter = function(){return this.parentNode; };
_(Element.prototype,"parent").setter = function(v){return this.parentNode=v;};
_(Element.prototype,"txt").getter = function(){return this.textContent;};
_(Element.prototype,"txt").setter = function(value){
value = value+""; //String
if(value.substr(0,this.txt.length) == this.txt){
this.addTxt(value.substr(this.txt.length));
}else{
this.textContent = value;
}
};
Element.prototype.addTxt = function(str){
//this.textContent += str without loosing child elements
if(!this.lastChild){
this.textContent = str;
}else if(this.lastChild instanceof Text){
this.lastChild.textContent += str;
}else{
this.addChild(doc.createTextNode(str));
}
return this.textContent;
}
Element.prototype.hasClass = function(str){
var attr = this.getAttr('class');
try{
attr = attr.split(' ');
if(attr.indexOf(str)+1){
return true;
}
}catch(e){}
return false;
};
Element.prototype.addClass = function(str){
var attr = this.getAttr('class');
try{
attr = attr.split(' ');
if(attr.indexOf(str)+1){
return str;
}else{
attr[attr.length] = str;
attr = attr.join(' ');
this.setAttr('class',attr);
return str;
}
}catch(e){
this.setAttr('class',str);
return str;
}
};
Element.prototype.rmClass = function(str){
var attr = this.getAttr('class');
try{
var i;
attr = attr.split(' ');
if((i=attr.indexOf(str))+1){
attr.splice(i,1);
attr = attr.join(' ');
this.setAttr('class',attr);
}
}catch(e){}
return str;
};
Element.prototype.setClass = function(str){
try{
str = str.join(' ');
}catch(e){}
this.setAttr('class',str);
};
Element.prototype.getClass = function(){
var attr = this.getAttr('class');
try{
return attr.split(' ');
}catch(e){
return [];
}
};
Element.prototype.spliceClass = function(){
var attr = this.getClass();
var result = attr.splice.apply(attr,arguments);
this.setClass(attr);
return result;
}
//Query
win.$ = {};
$.id = function(str){return doc.getElementById(str);};
$.class = function(str){return doc.getElementsByClassName(str);};
$.tag = function(str){return doc.getElementsByTagName(str);};
_($,"head").link(doc,"head");
_($,"body").link(doc,"body");
//Timing
win.wait = function(t,f,o){return {"timeout":win.setTimeout(f,t*1000,o)};};
win.interval = function(t,f,o){return {"interval":win.setInterval(f,t*1000,o)};};
win.stopTime = function(o){
if(o.timeout){
return win.clearTimeout(o.timeout);
}
if(o.interval){
return win.clearInterval(o.interval);
}
return false;
};
win.async = function(f,o){win.setTimeout(f,0,o); return o;}
//Constants
win.inf = Infinity;
win.u = {};
win.u.sec = 1;
win.u.min = 60;
win.u.px = 1;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment