Skip to content

Instantly share code, notes, and snippets.

@Witiko
Last active December 22, 2015 10:58
Show Gist options
  • Save Witiko/6462082 to your computer and use it in GitHub Desktop.
Save Witiko/6462082 to your computer and use it in GitHub Desktop.
An unfinished DOM interfacing library employing an API similar to that of the jQuery library.
/*
DOM(String Query[, DOM Node / Window Context])
DOM(Wrappable1[, Wrappable2[, Wrappable3[, ... WrappableN]]]) -> DOM Object Wrapper
DOM.searchEngine([Function searchEngine]) -> Sets / Resets the search function
DOM.plugins = {};
new DOM[.Prototype].Fragment([Wrapped Node(s) / Node[, Wrapped Node(s) / Node ...]])
new DOM[.Prototype].Element(String Element1Name[, String Element2Name[, String ElementNName]])
new DOM[.Prototype].Text(String Text1[, String Text2[, String TextN]])
new DOM.Ajax([{
[headers: Object,] // default -> null
[method: String,] // default -> "GET"
[address: String,] // default -> "about:blank"
[async: Boolean,] // default -> true
[auth: {
user: String,
pass: String
}] // default -> none
}]) / DOM.Ajax(String address)
new DOM.Window([{
address: String,
name: String,
toolbar: Boolean,
location: Boolean,
directories: Boolean,
status: Boolean,
menubar: Boolean,
scrollbars: Boolean,
resizable: Boolean,
fullscreen: Boolean,
width: Number,
height: Number,
top: Number,
left: Number
}]) / DOM.Window(String address)
new DOM.XML(String XML)
DOM.html / head / body / document / window / forms / all - Shorthands
DOM.prototype.wrappee
DOM.prototype.find(String Query // [, Boolean KeepAlive] //) -> Returns a new object
DOM.prototype.on / no(String EventHandler[, Function Handler]) -> Fires / Attaches / Removes an event listener
DOM.prototype.remove() -> Removes all the Elements from the document
DOM.prototype.append / prepend / replace / before(Wrapped Node(s) / Node[, Wrapped Node(s) / Node]) -> Appends the nodes and clones them for each next parent
DOM.prototype.add(Wrapped Node(s) / Node[, Wrapped Node(s) / Node]) -> Adds new nodes to the current collection
DOM.prototype.children(Boolean elementsOnly / function filter) -> Returns a new object containing all children
DOM.prototype.all([Function filter(item), [Function callback(item)]])
DOM.prototype.first([Function filter(item), [Function callback(item)]])
-> Calls the function on the first / all subsequent objects (return true to break) OR returns the first / an Array of all subsequent objects
DOM.prototype.clone(Boolean CopySubNodes) -> Returns an object with cloned nodes
// DOM.prototype.item(Number Index) -> Returns a Node at the given index
DOM.prototype.css(Object / Array declaration) -> Changes the style declaration for given elements
.css(String name[, String value / null]) -> Retrieves for given element
DOM.prototype.attr(Object / Array declaration) -> Changes the attributes for given elements
.attr(String name[, String value / null]) -> Retrieves for given elements
DOM.prototype.send([String Data]) -> Sends the XMLHttpRequest
DOM.prototype.abort() -> Aborts the XMLHttpRequest
DOM.prototype.document() -> Returns a new object containing documents in place of DOM Windows
// DOM.prototype.window() -> Returns a new object containing windows in place of (i)Frames
DOM.prototype.close() -> Closes all open DOM Windows in the collection
DOM.prototype.context(nothing (2d) / "2d" / "3d") -> Gets the contexts canvas element(s)
DOM.prototype.toString() -> Turns a XML document into a string representation
DOM.prototype.prev(Boolean elementsOnly / function filter) /
next(Boolean elementsOnly / function filter) -> Gets the previous / next Node in a XML / HTML DOM structure
([{
include / exclude: NodeType Number / NodeTypes Array
}])
DOM.prototype.text([String innerText]) -> Gets (firstOnly) / sets nodeValue for TextNodes and textContent / innerText / text for elements
DOM.prototype.html([String innerHTML]) -> Gets (firstOnly) / sets innerHTML for elements
DOM.prototype.val([String value]) -> Gets (firstOnly) / sets the value of an element
DOM.prototype.checked([String value]) -> Gets (firstOnly) / sets the checkedness of an element
DOM.features = {
canvas: Boolean,
XmlToDoc: Boolean,
ajax: Boolean
};
*/
var DOM = (function(Function, defSearch, nextSibling, nextEleSibling, prevSibling, prevEleSibling, listen, unlisten, map, some, string, bool, array, toArray, uConcat, fire, contains, fromXML, toXML, xhr, XHR, extend, iterable, canvas, CANVAS, ele, document, fragment, hasTextContent, attachable, implementsGEBN, innerText, innerTextFallback, node, win, undefined) {
var args, global = this,
doc = global.document, find = defSearch;
DOM.searchEngine = function(func) {
find = func instanceof Function?func:defSearch;
};
extend(DOM, DOM.plugins = {});
DOM.prototype.find = function(query) {
if(!query || !string(query)) return this;
var results = [];
$iterate(this, implementsGEBN, function(node) {
results = uConcat(results, find(query, node));
}); return DOM.apply(DOM, results);
}; DOM.prototype.remove = function() {
$iterate(this, node, function(node) {
if(node.parentNode)
node.parentNode.removeChild(node);
}); return this;
}; DOM.prototype.append = function() {
if(!arguments.length) return this; var that = this;
iterate(arguments, node, function(child) { var first = fragment(child)?!that.iterable:true;
$iterate(that, function(parent) {
return attachable(parent, child);
}, function(parent) {
parent.appendChild(first?(first = false) || child:
child.cloneNode(true));
});
}); return this;
}; DOM.prototype.prepend = function() {
if(!arguments.length) return this; var that = this;
iterate(arguments, node, function(child) { var first = fragment(child)?!that.iterable:true;
$iterate(that, function(parent) {
return attachable(parent, child);
}, function(parent) {
child = first?(first = false) || child:
child.cloneNode(true);
parent.hasChildNodes()?parent.insertBefore(child, parent.firstChild):
parent.appendChild( child);
});
}); return this;
}; DOM.prototype.replace = function() {
if(!arguments.length) return this;
var prevNode, replace, parent, first = true, args = arguments;
$iterate(this, node, function(replacee) {
replace = true;
if(!(parent = replacee.parentNode)) return;
iterate(args, node, function(replacement) {
if(replace) {
parent.replaceChild(first && !fragment(replacement)?replacement:
replacement.cloneNode(true), replacee);
prevNode = replacement; replace = false;
} else {
var nextSibling = prevNode.nextSibling,
nextNode = first && !fragment(replacement)?replacement:
replacement.cloneNode(true);
if(nextSibling) parent.insertBefore(nextNode, nextSibling);
else if(attachable(parent, nextNode)) parent.appendChild( nextNode);
}
}); prevNode = null; if(first) first = false;
}); return this;
}; DOM.prototype.before = function() {
if(!arguments.length) return this; var that = this;
iterate(arguments, node, function(child) { var first = fragment(child)?!that.iterable:true;
$iterate(that, node, function(pivot) {
var parent;
if((parent = pivot.parentNode) && !document(parent))
parent.insertBefore(first?(first = false) || child:
child.cloneNode(true), pivot);
});
}); return this;
}; DOM.prototype.clone = function(copyChildren) {
var results = [];
$iterate(this, node, function(node) {
results.push(node.cloneNode(copyChildren));
}); return DOM.apply(DOM, results);
}; DOM.prototype.all = function(filter, callback) {
var func = callback instanceof Function,
result = func?this:[];
$iterate(this, filter, func?function(item) {
return callback(item);
}:function(item) {
result.push(item);
}); return result;
}; DOM.prototype.first = function(filter, callback) {
var first, func = callback instanceof Function;
if(func) first = this;
$first(this, filter, function(item) {
func?callback(item):first = item;
}); return first;
}; DOM.prototype.on = function(handler, func) {
var firing = !(func instanceof Function);
$iterate(this, function(ele) {
return "on" + handler in ele;
}, function(ele) {
(firing?fire:listen)(ele, handler, func, false);
}); return this;
}; DOM.prototype.no = function(handler, func) {
$iterate(this, function(ele) {
return "on" + handler in ele;
}, function(ele) {
unlisten(ele, handler, func, false);
}); return this;
}; DOM.prototype.send = function(data) {
if(!xhr) return this;
$iterate(this, xhr, function(xhr) {
xhr.send(data);
}); return this;
}; DOM.prototype.abort = function() {
if(!xhr) return this;
$iterate(this, xhr, function(xhr) {
xhr.abort();
}); return this;
}; DOM.prototype.close = function() {
$iterate(this, win, function(window) {
if(!window.closed)
window.close();
}); return this;
}; DOM.prototype.document = function() {
var results = [];
$iterate(this, win, function(window) {
if(window.document) results.push(
window.document
);
}); return DOM.apply(DOM, results);
}; DOM.prototype.context = function(type) {
var results = []; type = type || "2d";
$iterate(this, canvas, function(canvas) {
results.push(canvas.getContext(type));
}); return DOM.apply(DOM, results);
}; DOM.prototype.add = function(query, context) {
wrap.call(this, uConcat(
this.wrappee, string(query)?find(query, context):
toArray(arguments)
)); return this;
}; DOM.prototype.children = function(filter) { var results = [];
filter = filter instanceof Function?
filter:(filter?ele:null);
$iterate(this, node, function(node) {
children(node, filter, function(child) {
results.push(child);
});
}); return DOM.apply(DOM, results);
}; DOM.prototype.next = function(filter) {
var results = [], next = filter === true?
nextEleSibling:nextSibling;
filter = filter instanceof Function?
filter:null;
$iterate(this, node, function(node) {
while((node = next(node)) && filter && !filter(node));
if(node) results.push(node);
}); return DOM.apply(DOM, results);
}; DOM.prototype.prev = function(filter) {
var results = [], next = filter === true?
prevEleSibling:prevSibling;
filter = filter instanceof Function?
filter:null;
$iterate(this, node, function(node) {
while((node = next(node)) && filter && !filter(node));
if(node) results.push(node);
}); return DOM.apply(DOM, results);
}; DOM.prototype.css = function(key, value) {
if(!arguments.length) return this;
var that = this, i, l, result,
callee = arguments.callee;
if(key instanceof Object) {if(array(key))
for(i = 0, l = key.length; i !== l; i++) {
callee.call(that, key[i], null);
} else for(i in key) {
callee.call(that, i, key[i], value);
}} else $iterate(this, ele,
arguments.length === 1 && (result = [])?function(element) {
result.push(element.style[key]);
}:(value === null?function(element) {
element.style[key] = "";
}:function(element) {
element.style[key] = value;
})); return result || this;
}; DOM.prototype.attr = function(key, value) {
if(!arguments.length) return this;
var that = this, i, l, result,
callee = arguments.callee;
if(key instanceof Object) {if(array(key))
for(i = 0, l = key.length; i !== l; i++) {
callee.call(that, key[i], null);
} else for(i in key) {
callee.call(that, i, key[i], value);
}} else $iterate(this, ele, arguments.length === 1 && (result = [])?function(element) {
result.push(element[key] ||
element.getAttribute(key));
}:(value === null?function(element) {
element.removeAttribute(key);
}:function( element) {
if(key in element) element[key] = value;
else element.setAttribute(key, value);
})); return result || this;
}; DOM.prototype.toString = function() { var text;
$first(this, document, function(xml) {
text = fromXML(xml);
}); return text;
}; DOM.prototype.text = function(value) {
var result;
if(!arguments.length) {
$first(this, hasTextContent, function(node) {
result = ele(node)?node[innerText] || node.text:
node.nodeValue || node.data;
}); return result;
} $iterate(this, hasTextContent, function(node) {
if(ele(node)) {
if(innerText in node)
node[innerText] = value ;
else innerTextFallback(node, value);
} else node.nodeValue = value ;
}); return this;
}; DOM.prototype.html = function(value) {
var result;
if(!arguments.length) {
$first(this, ele, function(node) {
result = node.innerHTML;
}); return result;
} $iterate(this, ele, function(node) {
node.innerHTML = value;
}); return this;
}; DOM.prototype.val = function(newVal) {
return arguments.length?this.attr("value", newVal):
this.attr("value");
}; DOM.prototype.checked = function(newVal) {
return arguments.length?this.attr("checked", !!newVal):
!!this.attr("checked");
};
DOM.html = new DOM(doc.documentElement || doc.getElementsByTagName("html")[0]);
DOM.head = new DOM(doc.getElementsByTagName("head")[0]);
DOM.body = new DOM(doc.body || doc.getElementsByTagName("body")[0]);
DOM.document = new DOM(doc);
DOM.window = new DOM(global);
DOM.forms = new DOM(doc.forms);
DOM.all = new DOM(doc.all || doc.getElementsByTagName("*"));
DOM.features = {
canvas: CANVAS,
XmlToDoc: !!toXML,
ajax: !!XHR
};
if(toXML) DOM.XML = function(xml) {
return DOM.call(this, toXML(xml));
};
if(XHR) DOM.Ajax = function(opts) {
var xhr = XHR(), auth = opts && opts.auth;
if(opts.headers) for(var name in opts.headers)
xhr.setRequestHeader(name, opts.headers[name]);
xhr.open.apply(xhr, string(opts)?[ "GET", opts, true]:
[opts.method || "GET",
opts.address,
opts.async || true,
auth?opts.user:undefined,
auth?opts.pass:undefined]);
return DOM.call(this, xhr);
}; DOM.Window = function(opts) {
if(!arguments.length) return DOM.call(this, global.open());
if(string(opts)) return DOM.call(this, global.open(opts));
var attr = new Array(3);
attr[2] = [];
for(var item in opts) {
switch(item) {
case "address": attr[0] = opts[item]; break;
case "name": attr[1] = opts[item]; break;
default: attr[2].push(
bool(opts[item])?item + "=" + (opts[item]?"yes":"no"):
item + "=" + opts[item]
);
}
} attr[2] = attr[2].join(",");
return DOM.call(this, Function.prototype.apply.call(global.open, global, attr));
}; DOM.Fragment = function() {
var frag = (document(this)?this:doc).createDocumentFragment();
iterate(arguments, node, function(element) {
frag.appendChild(element);
}); return DOM.call(this, frag);
};
(function() {
DOM.Element = create(doc, "createElement" );
DOM.Text = create(doc, "createTextNode");
function create(context, func) {
return function(name) {
context = document(this)?this:context;
name = arguments.length > 1?map(arguments, function(name) {
return context[func](name);
}): context[func](name);
return new DOM(name);
};
};
})(DOM);
(function() {
DOM.prototype.Fragment = applyOnDoc(DOM.Fragment);
DOM.prototype.Element = applyOnDoc(DOM.Element );
DOM.prototype.Text = applyOnDoc(DOM.Text );
function applyOnDoc(func) {
return function() {
var args = arguments, result;
$first(this, document, function(document) {
result = func.apply(document, args);
}); return result;
};
};
})();
if(DOM.Ajax) extend(DOM.Ajax, DOM.prototype);
extend(DOM.Window, DOM.prototype);
extend(DOM.Fragment, DOM.prototype);
extend(DOM.Element, DOM.prototype);
extend(DOM.Text, DOM.prototype);
return(DOM);
function $first($, filter, callback) {
$iterate($, filter, function(item) {
callback(item); return true;
});
}; function $iterate($, filter, callback) {
if(!$.wrappee ) return;
if( $.iterable)
return iterate($.iterable === 2?
$.wrappee:toArray(
$.wrappee), filter, callback);
else if(!filter || filter($.wrappee))
callback($.wrappee);
}; function iterate($, filter, callback) {
return some($, function(item) {
if(!item) return;
if( item instanceof DOM) return $iterate(item, filter, callback);
if(iterable(item)) return iterate(item, filter, callback);
if(!filter || filter( item)) return callback(item);
});
}; function wrap(query, context) {
if(query instanceof DOM && !context) {
this.wrappee = query.wrappee;
this.iterable = query.iterable;
} else { var length, isArr,
wrappee = string(query)?find(query, context):
arguments.length > 1?toArray(arguments):
arguments[0];
wrappee = (isArr = array(wrappee))?
(!(length = wrappee.length)
?null:(length === 1?wrappee[0]:
wrappee)):
wrappee;
this.iterable = iterable(Object(wrappee))?
(isArr?2:1):0;
this.wrappee = wrappee ;
}
}; function children(node, filter, callback) {
var next = node.firstChild;
while(node = next) {
if(!filter || filter(node)) callback(node);
next = node.firstChild || node.nextSibling;
while(!next && (node = node.parentNode))
next = node.nextSibling;
}
}; function DOM() {
if(!(this instanceof arguments.callee)) {
args = arguments;
return new arguments.callee;
} wrap.apply(this, args || arguments);
if(args) args = null;
};
})(this.Function, (function(string) {
return function(query, context) {
if(!string(query)) return;
context = context?(context.document || context || this.document):
this.document;
return query.charAt(0) === "#"?(
"getElementById" in context?
context.getElementById(query.substr(1)):
this.document.getElementById(query.substr(1))
):(
"getElementsByTagName" in context?
context.getElementsByTagName(query):
this.document.getElementsByTagName(query)
);
}
})(this.String.isString),
function(child) {
return child.nextSibling;
},
(function() {
return "nextElementSibling" in document.createElement("span")?function(child) {
return child.nextElementSibling;
}:function(child) {
while((child = child.nextSibling) && child.nodeType !== 1);
return child;
}
})(),
function(child) {
return child.previousSibling;
},
(function() {
return "previousElementSibling" in document.createElement("span")?function(child) {
return child.previousElementSibling;
}:function(child) {
while((child = child.previousSibling) && child.nodeType !== 1);
return child;
}
})(),
"addEventListener" in this?
function(element, event, func) {
element.addEventListener(event, func, false);
}:function(element, event, func) {
element.attachEvent("on" + event, func);
}, "removeEventListener" in this?
function(element, event, func) {
element.removeEventListener(event, func);
}:function(element, event, func) {
element.detachEvent("on" + event, func);
},
this.Array.map,
this.Array.some,
this.String.isString,
this.Boolean.isBoolean,
this.Array.isArray,
this.Array.from,
this.Array.uConcat,
this.document.createEventObject?function(ele, event) {
ele.fireEvent("on" + event, this.document.createEventObject());
}:function(ele, event) {
var evt = this.document.createEvent("HTMLEvents");
evt.initEvent(event, true, true);
ele.dispatchEvent(evt);
},
document.createElement("span").contains?function(x, y) {
return x.contains?
x.contains(y):false;
}:function(x, y) {
return x.compareDocumentPosition(y) & 16;
},
"XMLSerializer" in this?(function() {
var serializer = new XMLSerializer;
return function(xml) {
return serializer.serializeToString(xml);
}
})():function(xml) {
return xml.xml;
},
(function() {
if("DOMParser" in this) return (function() {
var parser = new DOMParser;
return function(xml) {
return parser.parseFromString(xml, "text/xml");
}
})(); else try {
new ActiveXObject("Microsoft.XMLDOM"); return function(xml) {
var parser = new ActiveXObject("Microsoft.XMLDOM");
parser.async = false;
parser.loadXML(xml);
return parser;
}
} catch (e) {}
})(),
(function() {
if(this.XMLHttpRequest) return function(obj) {
return obj instanceof this.XMLHttpRequest;
};
if(this.ActiveXObject) return function(obj) {
return obj instanceof this.ActiveXObject;
};
})(),
(function() {
if("XMLHttpRequest" in this) return function() {
return new XMLHttpRequest;
}; else try{
new ActiveXObject("Msxml2.XMLHTTP"); return function() {
return new ActiveXObject("Msxml2.XMLHTTP");
}} catch (e) {try {
new ActiveXObject("Microsoft.XMLHTTP"); return function() {
return new ActiveXObject("Microsoft.XMLHTTP");
}} catch (e) {}}
})(), function(func, obj) {
func.prototype = Object.create(obj);
func.prototype.constructor = func;
}, function(obj) {
var length;
return !!( obj !== this &&
obj.window !==
obj &&
!("nodeType" in obj) &&
typeof obj === "object" &&
"length" in obj && (
!(length = obj.length) ||
length - 1 in obj))
}, function(obj) {
return obj.nodeType === 1 &&
obj.tagName === "CANVAS";
}, (function(obj) {
return "getContext" in document.createElement("canvas");
})(), function(obj) {
return obj.nodeType === 1;
}, function(obj) {
return obj.nodeType === 9;
}, function(obj) {
return obj.nodeType === 11;
}, function(obj) {
return obj.nodeType === 3 ||
obj.nodeType === 1 ||
obj.nodeType === 8;
}, (function(Node) {
Node = this.Node || {
ELEMENT_NODE: 1,
ATTRIBUTE_NODE: 2,
TEXT_NODE: 3,
CDATA_SECTION_NODE: 4,
ENTITY_REFERENCE_NODE: 5,
ENTITY_NODE: 6,
PROCESSING_INSTRUCTION_NODE: 7,
COMMENT_NODE: 8,
DOCUMENT_NODE: 9,
DOCUMENT_TYPE_NODE: 10,
DOCUMENT_FRAGMENT_NODE: 11,
NOTATION_NODE: 12
}; function contains(parent, nodeType) {
var node;
if( !(node = parent.firstChild) ) return false;
do if(node.nodeType === nodeType) return true;
while(node = node.nextSibling ) return false;
}; return function(parent, child) {
if(!"nodeType" in parent ||
!"nodeType" in child ||
parent.nodeType === Node.TEXT_NODE ||
parent.nodeType === Node.CDATA_SECTION_NODE ||
parent.nodeType === Node.PROCESSING_INSTRUCTION_NODE ||
parent.nodeType === Node.COMMENT_NODE ||
parent.nodeType === Node.DOCUMENT_TYPE_NODE ||
parent.nodeType === Node.NOTATION_NODE) return false;
switch(parent.nodeType) {
case Node.DOCUMENT_NODE:
return (child.nodeType === Node.ELEMENT_NODE && !contains(parent, Node.ELEMENT_NODE)) ||
(child.nodeType === Node.DOCUMENT_TYPE_NODE && !contains(parent, Node.DOCUMENT_TYPE_NODE)) ||
child.nodeType === Node.PROCESSING_INSTRUCTION_NODE ||
child.nodeType === Node.COMMENT_NODE;
case Node.DOCUMENT_FRAGMENT_NODE:
case Node.ENTITY_REFERENCE_NODE :
case Node.ELEMENT_NODE :
case Node.ENTITY_NODE :
return child.nodeType !== Node.ATTRIBUTE_NODE &&
child.nodeType !== Node.ENTITY_NODE &&
child.nodeType !== Node.DOCUMENT_NODE &&
child.nodeType !== Node.DOCUMENT_TYPE_NODE
child.nodeType !== Node.NOTATION_NODE;
case Node.ATTRIBUTE_NODE:
return child.nodeType === Node.TEXT_NODE ||
child.nodeType === Node.ENTITY_REFERENCE_NODE;
} return false;
};
})(), function(obj) {
return obj.window ===
obj ||
obj.nodeType === 1 ||
obj.nodeType === 9;
}, "textContent" in document.createElement("span")?
"textContent":"innerText", function(node, text) {
while(node.hasChildNodes()) node.removeChild(node.firstChild);
node.appendChild(node.ownerDocument.createTextNode(text));
}, function( obj) {
return "nodeType" in obj;
}, function( obj) {
return obj.window ===
obj;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment