-
-
Save nutbread/58f73919109a100cb481 to your computer and use it in GitHub Desktop.
Custom node generation function (and other common functions)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
Custom node generation function | |
Format: | |
$(string:tag_name, [string:classname], [any:extra, ...]) | |
tag_name | |
The name of the HTML tag to create | |
[classname] | |
The className of the node | |
[extra]: | |
This depends on the type of the node: | |
string: | |
Adds a textNode containing the next argument's string to the node | |
object: (not an array) | |
Iterates over each property of the object and sets an attribute on the node | |
array: | |
Treats each entry in the array as a DOM node and appends it to the node | |
number: (from constant list) | |
$.A, $.AFTER: | |
Insert the new node after the node specified in the following argument | |
$.B, $.BEFORE: | |
Insert the new node before the node specified in the following argument | |
$.P, $.PARENT: | |
Append the new node to the node specified in the following argument | |
$.ON, $.EVENT: | |
Add an event listener to the node. The following argument should an array in the form: | |
[ string:event_name, function:callback [, bool:use_capture [, binding_args ]] ] | |
If specified, binding_args is an array of argument values to be used in binding the function: | |
binding_args[0] = (the this object) | |
binding_args[1] = (arguments[0]) | |
binding_args[2] = (arguments[1]) | |
... | |
If any of these values are set to $.node, then this value is replaced with the new node. | |
$.T, $.TEXT: | |
The following argument (text) will be appended as a textNode | |
General usage: | |
$("span", { "data-test": "attr value" }, [ child_node0, child_node1 ]); | |
$("span", { "data-test": "attr value" }, "This is the textContent", $.P, parent_node); | |
$("span", { "data-test": "attr value" }, "This is the textContent", $.ON, [ "click", function (this_is_true, event) {}, false, [ $.node, true ] ]); | |
$("span", "classname"); | |
$("span", null, "This is the textContent"); | |
$("span", $.TEXT, "This is the textContent"); | |
$("span", [ $.text("This is the textContent") ]); | |
*/ | |
var $ = (function () { | |
var typeof_str = typeof(""), | |
typeof_object = typeof({}), | |
d = document; | |
var $ = function (tag) { | |
var arg_count = arguments.length, | |
node = (typeof(tag) === typeof_str ? d.createElement(tag) : tag), | |
i = 1, | |
a, j, k, t; | |
// Done | |
if (i >= arg_count) return node; | |
// Classname | |
t = typeof(a = arguments[i]); | |
if (t === typeof_str) { | |
// Use | |
node.setAttribute("class", a); | |
// Next | |
if (++i >= arg_count) return node; | |
t = typeof(a = arguments[i]); | |
} | |
// Children, attributes, text, custom | |
while (true) { | |
if (t === typeof_object) { | |
// Children or attributes | |
if (Array.isArray(a)) { | |
// Children | |
for (j = 0; j < a.length; ++j) { | |
if (a[j] !== null) { | |
node.appendChild(a[j]); | |
} | |
} | |
} | |
else if (a !== null) { | |
// Attributes | |
for (k in a) { | |
node.setAttribute(k, a[k]); | |
} | |
} | |
} | |
else if (t === typeof_str) { | |
// Text | |
node.appendChild(d.createTextNode(a)); | |
} | |
else { | |
// Number | |
if (a === PARENT) { | |
// Parent | |
arguments[++i].appendChild(node); | |
} | |
else if (a === PREPEND) { | |
// Prepend | |
a = arguments[++i]; | |
k = a.firstChild; | |
if (k === null) { | |
a.appendChild(node); | |
} | |
else { | |
a.insertBefore(node, k); | |
} | |
} | |
else if (a === BEFORE) { | |
// Insert before a node | |
a = arguments[++i]; | |
k = a.parentNode; | |
if (k !== null) { | |
k.insertBefore(node, a); | |
} | |
} | |
else if (a === AFTER) { | |
// Insert after a node | |
a = arguments[++i]; | |
k = a.parentNode; | |
if (k !== null) { | |
a = a.nextSibling; | |
if (a !== null) { | |
k.insertBefore(node, a); | |
} | |
else { | |
k.appendChild(node); | |
} | |
} | |
} | |
else if (a === EVENT) { | |
// Event | |
a = arguments[++i]; | |
k = a[1]; // function | |
if (a.length >= 4) { | |
// Bind | |
k = bind_event_listener(node, k, a[3]); | |
} | |
node.addEventListener(a[0], k, a[2] || false); | |
} | |
else if (a === TEXT) { | |
// Text | |
node.appendChild(d.createTextNode(arguments[++i])); | |
} | |
} | |
// Next | |
if (++i >= arg_count) return node; | |
t = typeof(a = arguments[i]); | |
} | |
}; | |
var Rect = function (left, top, right, bottom, width, height) { | |
this.left = left; | |
this.top = top; | |
this.right = right; | |
this.bottom = bottom; | |
this.width = width; | |
this.height = height; | |
}; | |
var bind_event_listener = function (node, callback, args) { | |
// Bind | |
if (args && args.length > 0) { | |
var new_args = [], | |
self, a, i; | |
// Form new array | |
a = args[0]; | |
self = (a === NODE) ? node : a; | |
for (i = 1; i < args.length; ++i) { | |
a = args[i]; | |
new_args.push((a === NODE) ? node : a); | |
} | |
a = null; | |
args = null; | |
// Return new callback | |
if (new_args.length > 0) { | |
var slice = Array.prototype.slice, | |
push = Array.prototype.push; | |
return function () { | |
var full_args = slice.call(new_args); | |
push.apply(full_args, arguments); | |
return callback.apply(self, full_args); | |
}; | |
} | |
else { | |
return function () { | |
return callback.apply(self, arguments); | |
}; | |
} | |
} | |
else { | |
// No change | |
return callback; | |
} | |
}; | |
var regex_escape = function (text) { | |
return text.replace(/[\$\(\)\*\+\-\.\/\?\[\\\]\^\{\|\}]/g, "\\$&"); | |
}; | |
var AFTER = 1; | |
var BEFORE = 2; | |
var PARENT = 3; | |
var PREPEND = 4; | |
var EVENT = 5; | |
var TEXT = 6; | |
var NODE = {}; | |
$.A = $.AFTER = AFTER; | |
$.B = $.BEFORE = BEFORE; | |
$.P = $.PARENT = PARENT; | |
$.PP = $.PREPEND = PREPEND; | |
$.ON = $.EVENT = EVENT; | |
$.T = $.TEXT = TEXT; | |
$.NODE = NODE; | |
$.text = function (str) { | |
return d.createTextNode(str || ""); | |
}; | |
$.ns = function (namespace, tag) { | |
var args = [ d.createElementNS(namespace, tag) ]; | |
Array.prototype.push.apply(args, Array.prototype.slice.call(arguments, 2)); | |
return $.apply(null, args); | |
}; | |
$.id = function (id) { | |
return d.getElementById(id); | |
}; | |
$.sel = function (selector, context) { | |
if (!context) return d.querySelector(selector); | |
return context.querySelector(selector); | |
}; | |
$.all = function (selector, context) { | |
if (!context) return d.querySelectorAll(selector); | |
return context.querySelectorAll(selector); | |
}; | |
$.regex_escape = regex_escape; | |
$.class_contains = function (node, class_name) { | |
if (node.classList) { | |
// classList mode | |
return node.classList.contains(class_name); | |
} | |
else { | |
// Regex mode | |
return (new RegExp("(\\s|^)" + regex_escape(class_name) + "(\\s|$)")).test(node.getAttribute("class") || ""); | |
} | |
}; | |
$.class_add = function (node, class_name) { | |
if (node.classList) { | |
// classList mode | |
node.classList.add(class_name); | |
} | |
else { | |
// Regex mode | |
var cn = node.getAttribute("class") || ""; | |
if (!(new RegExp("(\\s|^)" + regex_escape(class_name) + "(\\s|$)")).test(cn)) { | |
if (cn.length > 0) cn += " "; | |
cn += class_name; | |
node.setAttribute("class", cn); | |
} | |
} | |
}; | |
$.class_remove = function (node, class_name) { | |
if (node.classList) { | |
// classList mode | |
node.classList.remove(class_name); | |
} | |
else { | |
// Regex mode | |
var cn = node.getAttribute("class") || "", | |
cn_new = cn.replace((new RegExp("(\\s|^)" + regex_escape(class_name) + "(\\s|$)", "g")), " ").trim(); | |
if (cn_new.length !== cn.length) { | |
node.setAttribute("class", cn_new); | |
} | |
} | |
}; | |
$.doc_rect = function () { | |
var win = window, | |
doc = d.documentElement, | |
left = (win.pageXOffset || doc.scrollLeft || 0) - (doc.clientLeft || 0), | |
top = (win.pageYOffset || doc.scrollTop || 0) - (doc.clientTop || 0), | |
w = (doc.clientWidth || win.innerWidth || 0), | |
h = (doc.clientHeight || win.innerHeight || 0); | |
return new Rect( | |
left, | |
top, | |
left + w, | |
top + h, | |
w, | |
h | |
); | |
}; | |
$.node_rect = function (obj) { | |
var bounds = obj.getBoundingClientRect(), | |
win = window, | |
doc = d.documentElement, | |
left = (win.pageXOffset || doc.scrollLeft || 0) - (doc.clientLeft || 0), | |
top = (win.pageYOffset || doc.scrollTop || 0) - (doc.clientTop || 0); | |
return new Rect( | |
left + bounds.left, | |
top + bounds.top, | |
left + bounds.right, | |
top + bounds.bottom, | |
bounds.width, | |
bounds.height | |
); | |
}; | |
$.bind = function (callback, self) { | |
if (arguments.length > 2) { | |
var slice = Array.prototype.slice, | |
push = Array.prototype.push, | |
args = slice.call(arguments, 2); | |
return function () { | |
var full_args = slice.call(args); | |
push.apply(full_args, arguments); | |
return callback.apply(self, full_args); | |
}; | |
} | |
else { | |
return function () { | |
return callback.apply(self, arguments); | |
}; | |
} | |
}; | |
$.on_ready = (function () { | |
// Vars | |
var callbacks = [], | |
check_interval = null, | |
check_interval_time = 250; | |
// Check if ready and run callbacks | |
var callback_check = function () { | |
if ( | |
(document.readyState === "interactive" || document.readyState === "complete") && | |
callbacks !== null | |
) { | |
// Run callbacks | |
var cbs = callbacks, | |
cb_count = cbs.length, | |
i; | |
// Clear | |
callbacks = null; | |
for (i = 0; i < cb_count; ++i) { | |
cbs[i].call(null); | |
} | |
// Clear events and checking interval | |
window.removeEventListener("load", callback_check, false); | |
window.removeEventListener("readystatechange", callback_check, false); | |
if (check_interval !== null) { | |
clearInterval(check_interval); | |
check_interval = null; | |
} | |
// Okay | |
return true; | |
} | |
// Not executed | |
return false; | |
}; | |
// Listen | |
window.addEventListener("load", callback_check, false); | |
window.addEventListener("readystatechange", callback_check, false); | |
// Callback adding function | |
return function (cb) { | |
if (callbacks === null) { | |
// Ready to execute | |
cb.call(null); | |
} | |
else { | |
// Delay | |
callbacks.push(cb); | |
// Set a check interval | |
if (check_interval === null && callback_check() !== true) { | |
check_interval = setInterval(callback_check, check_interval_time); | |
} | |
} | |
}; | |
})(); | |
return $; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment