Skip to content

Instantly share code, notes, and snippets.

@linkarys
Created March 27, 2013 14:14
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 linkarys/5254470 to your computer and use it in GitHub Desktop.
Save linkarys/5254470 to your computer and use it in GitHub Desktop.
javascript: extend
/**************************************************************
author: linkarys
description: framework of javascript
date begin: 2012-9-8
**************************************************************/
/* =============================================================================
Shortcuts
========================================================================== */
// shortcup for console.log
function log(mes, des) {
if (!des) {
console.log(mes);
} else {
console.log(des + ' is: ' + mes);
}
}
function logi() {
console.log(arguments)
}
function logf(mes, des, end) {
if (des) console.log('============================= ' + des + ' start =============================');
console.log(mes);
if (end) console.log('============================== ' + des + ' end ==============================');
}
function logn(mes, des) {
// IE7 does not support HTMLCollection
var collect = typeof HTMLCollection === 'undefined' ? 1 : HTMLCollection;
// des is no defined
if (!des) {
if (mes.constructor === Array || mes.constructor === collect) {
var len = mes.length;
(function() {
for (var i = 0; i < len; i++) {
console.log(mes[i]);
}
})();
} else {
console.log(mes);
}
} else {
if (mes.constructor === Array || mes.constructor === collect) {
var len = mes.length;
(function() {
for (var i = 0; i < len; i++) {
console.log(des + '_' + (i + 1) + ':');
console.log(mes[i]);
}
})();
} else {
console.log(des + ': ');
console.log(mes);
}
}
console.log('');
}
// shortcup for alert
function at(mes, des) {
if (!des) {
alert(mes);
} else {
alert(des + ' is: ' + mes);
}
}
// log message after 'time'-milliseconds
function dlog(mes, time, des) {
time = !time ? 0 : time;
setTimeout(function() {
log(mes, des);
}, time);
}
// alert message after 'time'-milliseconds
function dat(mes, time, des) {
time = !time ? 0 : time;
setTimeout(function() {
at(mes, des);
}, time);
}
function sub(str) {
return str.substring(1, str.length);
}
/* =============================================================================
DOM method
========================================================================== */
function html(node, text) {
// clean childNodes
while (node.firstChild) {
node.removeChild(node.firstChild);
}
// append new elements
node.appendChild(document.createTextNode(text));
}
function bindEvent(el, eventName, eventHandler) {
if (el.addEventListener) {
el.addEventListener(eventName, eventHandler, false);
} else if (el.attachEvent) {
el.attachEvent('on' + eventName, eventHandler);
}
}
function makeUnselectable(node) {
if (node.nodeType == 1) {
node.setAttribute("unselectable", "on");
}
var child = node.firstChild;
while (child) {
makeUnselectable(child);
child = child.nextSibling;
}
}
//files operation
function include(path) {
if (path) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = path;
document.getElementsByTagName('head')[0].appendChild(script);
}
}
function stopBubble(e) {
if (e && e.stopProgagation) e.stopProgagation();
else window.event.cancelBubble = true;
}
function preDef(e) {
if (e && e.preventDefault) e.preventDefault();
else window.event.returnValue = false;
}
// animation
function slideDown(elem, speed) {
elem.style.overflow = 'hidden';
var speed = speed || 400;
animate(elem, 'height', elem.offsetHeight, speed, true);
}
function slideUp(elem, speed) {
elem.style.overflow = 'hidden';
var speed = speed || 400;
animate(elem, 'width', elem.offsetHeight, speed, true);
}
function slideRight(elem, speed) {
}
function animate(elem, property, range, speed, show) {
for (var i = 0; i <= speed;) {
(function() {
var pos;
if (show) {
pos = i;
elem.style[property] = 0;
} else {
pos = speed - i;
elem.style[property] = range;
}
setTimeout(function() {
switch (property) {
case 'height':
elem.style.height = move(pos, speed, range);
break;
case 'width':
elem.style.width = move(pos, speed, range);
break;
}
}, ++i);
function move(pos, speed, range) {
return (pos / speed) * range + 'px';
}
})();
};
}
function fadeIn(elem, level, speed, show) {
level = level || 100;
speed = speed || 700;
show = show || true;
elem.style.opacity = show ? 0 : 1;
for (var i = 0; i <= speed;) {
(function() {
var curr = show ? i : speed - i;
setTimeout(function() {
setOpacity(elem, parseInt((curr / speed) * level));
}, ++i)
})();
}
}
function setOpacity(elem, level) {
if (elem.filters) elem.style.filter = 'alpha(opacity="' + level + '")';
else elem.style.opacity = level / 100;
}
// show message loading
/*function showLoading(elem, msg){
msg = msg || 'loading';
var i = 0,
speed = 500;
setTimeout(function(){
log(i);
i++;
if(i % speed === 1){
elem.innerText = msg + '..';
}else if(i % speed === 2){
elem.innerText = msg + '...';
i = 0;
}
}, speed)
}*/
/* =============================================================================
Position
========================================================================== */
function getMPos(e) {
e = e || window.event;
return {
x: e.pageX || e.clientX + document.body.scrollLeft,
y: e.pageY || e.clientY + document.body.scrollTop,
log: function() {
log('(' + this.x + ', ' + this.y + ')');
},
logIE: function() {
log(e.clientX, 'e.clientX');
log(document.body.scrollLeft, 'document.body.scrollLeft');
log(e.clientY, 'e.clientY');
log(document.body.scrollTop, 'document.body.scrollTop');
}
}
}
// get element offset (only ie)
function getOffsetIE() {
// offsetX start at content area
if (window.event) return {
x: window.event.offsetX,
y: window.event.offsetY,
log: function() {
log('(' + this.x + ', ' + this.y + ')');
}
}
}
// get element offset
function getOriOffset(el) {
// important
var x = 0,
y = 0;
while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
x += el.offsetLeft - el.scrollLeft;
y += el.offsetTop - el.scrollTop;
el = el.parentNode;
}
return {
x: x,
y: y,
log: function() {
log('(' + this.x + ', ' + this.y + ')');
}
}
}
// get element offset
function getOffset(el) {
var x = 0,
y = 0;
if (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
x = el.offsetLeft - el.scrollLeft;
y = el.offsetTop - el.scrollTop;
}
return {
x: x,
y: y,
log: function() {
log('(' + this.x + ', ' + this.y + ')');
}
}
}
// get window scroll position
function getScroll() {
var de = document.documentElement;
return {
x: self.pageXOffset || de.scrollLeft || document.body.scrollLeft,
y: self.pageYOffset || de.scrollTop || document.body.scrollTop,
log: function() {
log('(' + this.x + ', ' + this.y + ')');
}
}
}
function ReplaceDemo() {
var r, re; // 声明变量。
var ss = "The rain in Spain falls mainly in the plain.";
re = /(\S+)(\s+)(\S+)/g; // 创建正则表达式模式。
r = ss.replace(re, "$3$2$1"); // 交换每一对单词。
return (r); // 返回结果字符串。
}
// remove element's specific class
function removeClass(elem, className) {
var rclass = /[\n\r\t]/,
value;
if (elem && elem.nodeType === 1 && elem.className) {
if (className) {
value = (' ' + elem.className + ' ').replace(rclass, ' ').replace(className + ' ', '');
elem.className = value.trim();
}
}
}
// add specific class
function addClass(elem, className) {
var rclass = /[\n\r\t]/,
value;
if (elem && elem.nodeType === 1 && className && !hasClass(elem, className)) {
value = elem.className + ' ' + className;
elem.className = value.trim();
}
}
// check if element has class className
function hasClass(elem, className) {
var cname = elem ? elem.className : '',
reg = new RegExp('(\\s|^)' + className + '(\\s|$)*');
return reg.test(cname);
}
/* =============================================================================
Query
========================================================================== */
function I(selector) {
var firstElem = selector.charAt(0);
if (firstElem === '.' || firstElem === '#') {
selector = selector.substring(1, selector.length);
// handle id
if (firstElem === '#') return document.getElementById(selector);
// handle class
else {
var result = [],
elements = document.body.childNodes;
for (var i = 0; len = elements.length, i < len; i++) {
var e = elements[i];
log(e);
if (hasClass(e, selector)) {
result.push(e);
}
}
return result;
}
} else
// handle tag
return document.getElementsByTagName(selector);
}
function next(elem) {
do {
elem = elem.nextSibling;
} while (elem && elem.nodeType != 1)
return elem;
}
function prev(elem) {
if (elem) {
var parent = elem.parentNode;
}
}
function first(elem) {
var first = elem.firstChild;
return elem & elem.nodeType != 1 ? next(elem) : elem;
}
// parent node
function parent(elem, num) {
num = num || 1;
for (var i = 0; i < num; i++) {
elem = elem.parentNode || elem;
}
return elem;
}
/* =============================================================================
Data struct
========================================================================== */
function Hash() {
var key = [],
value = [];
this.add = function(ikey, ivalue) {
key.push(ikey);
value.push(ivalue);
}
this.log = function() {
var len = key.length;
for (var i = 0; i < len; i++) {
log('error_' + i + ':');
log(key[i]);
log(value[i] + '\n');
}
}
}
/* =============================================================================
Extend method
========================================================================== */
// er...
Function.prototype.method = function(name, func) {
if (!this.prototype[name]) this.prototype[name] = func;
return this;
}
if (Object.beget !== Function) {
Object.beget = function(f) {
var F = function() {};
F.prototype = f;
return new F();
}
}
// get interger
Number.method('int', function(ceil) {
return Math[ceil ? 'ceil' : 'floor'](this);
})
// logs
/*Number.method('log', function(msg) {
result = msg ? msg + ': ' + this['valueOf'](this) : this.valueOf();
console.log(result);
return this;
})
String.method('log', function(msg) {
result = msg ? msg + ': ' + this.toString() : this.toString();
console.log(result);
return this;
})*/
Object.method('log', function(msg) {
if (this === null) return;
var i, result;
if (this.constructor === Number) {
result = this.valueOf();
} else {
result = this.toString();
}
result = msg ? msg + ': ' + result : result;
console.log(result);
return this;
})
String.method('entityify', function() {
var character = {
'<': '&lt',
'>': '&gt',
'&': '$amp',
'"': '&quot'
};
return function() {
return this.replace(/[<>&"]/g, function(c) {
return character[c];
});
}
}());
var count_word = function(text) {
var word, i, count = {},
words = text.toLowerCase().split(/[\s,.]/),
sum = words.length;
for (i = 0; i < sum; i++) {
word = words[i];
if (count[word] && !isNaN(count[word])) {
count[word]++;
} else {
count[word] = 1;
}
}
count.SUM = sum;
return count;
}
// generate string like alpha-connector...-alpha
var constr = function(alpha, connetor, n) {
var str = '',
i = 0;
for (i = 0; i < n; i++) {
str += alpha + connetor;
}
return (str + alpha);
}
// return the sum of arguments
var add = function add() {
var len = arguments.length,
sum = 0;
while (len--) {
if (arguments[len].constructor === Number) {
throw {
name: 'Type Error!',
message: 'Ensure your type is correct!'
};
}
sum += arguments[len];
}
return sum;
}
/* -------------------------------------------------
Extend Array
------------------------------------------------*/
// return index of element in an array
Array.prototype.getIndex = function(elem) {
var i = this.length;
while (i--) {
if (this[i] === elem) {
return i;
}
}
return -1;
}
// generate array with specific initial value
Array.dim = function(dimension, initial) {
var a = [],
i;
for (i = 0; i < dimension; i++) {
a[i] = initial ? initial : 0;
}
return a;
}
// generate matrix with specific initial value
Array.matrix = function(m, n, initial) {
var mat = [];
for (var i = 0; i < m; i++) {
var a = [];
for (var j = 0; j < n; j++) {
a[j] = initial ? initial : 0;
}
mat[i] = a;
}
return mat;
}
Array.method('reduce', function(f, value) {
for (var i = 0; i < this.length; i++) {
value = f(this[i], value);
}
return value;
})
/* -------------------------------------------------
Extend Funtion
------------------------------------------------*/
Function.method('curry', function() {
var that = this,
slice = Array.prototype.slice,
args = slice.apply(arguments);
log(arguments);
return function() {
return that.apply(null, args.concat(slice.apply(arguments)));
};
})
// trim string
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, '');
}
// compare factor
var compare = function() {
return function(a, b) {
if (a === b) return 0;
if (a.constructor === b.constructor) return a < b ? -1 : 1;
return typeof a < typeof b ? -1 : 1;
}
}
// compare factor
var by = function(name, minor) {
return function(o, p) {
var a, b;
if (typeof o === 'object' && typeof p === 'object' && o && p) {
a = o[name];
b = p[name];
if (a === b) return minor.constructor === Function ? minor(o, p) : 0;
if (typeof a === typeof b) return a < b ? -1 : 1;
return typeof a < typeof b ? -1 : 1;
} else {
throw {
name: 'error',
message: 'expected an object when sorting by ' + name
}
}
}
}
var fibonacci = function() {
var memo = [0, 1];
return function fib(n) {
if (typeof memo[n] !== 'number') {
memo[n] = fib(n - 1) + fib(n - 2);
}
return memo[n];
};
}();
var memoizer = function(memo, func) {
return function shell(n) {
if (typeof memo[n] !== 'number') {
memo[n] = func(shell, n);
}
return memo[n];
};
};
// not IE
if (navigator.appVersion.indexOf('MSIE') === -1) {
HTMLElement.prototype.log = function(msg) {
if (msg) {
console.log(msg + ' :');
}
console.log(this);
}
}
/* =============================================================================
Validation
========================================================================== */
// checkies
function checkEmail(email) {
var regex = /^([\w\.\-])+@([\w\-])+\.([\w]{2,4})+$/;
return regex.test(email);
}
function checkUrl(url) {
var regex = /^(https?:\/\/)?([\w]+\.)+[\w]{2,4}$/
return regex.test(url);
}
var checker = {
required: {
msg: 'this filed is required',
test: function(elem) {
if (elem.length) {
return checker.checkNum.test(elem);
}
return elem.value != "" && elem != null;
}
},
email: {
msg: 'invalid email',
test: function(email) {
return /^[\w_\.\-]+@([\w_\-])+\.([\w]{2,4})+$/.test(email.value);
}
},
confmail: {
msg: 'no match',
test: function(confmail) {
var form, email;
// get DOM form
form = confmail.parentNode;
while (form.nodeName != 'FORM' || form.nodeName === 'BODY') {
form = form.parentNode;
}
// get DOM email
for (var key in form.elements) {
var curr = form.elements[key];
if (hasClass(curr, 'email')) email = curr;
}
// validate
return confmail.value === email.value;
}
},
url: {
msg: 'invalid url',
test: function(url) {
return /^(https?:\/\/)?([\w]+\.)+[\w]{2,4}$/.test(url.value);
}
},
checkNum: {
msg: 'check num should not be zero',
test: function(elems) {
var num = 0;
for (var i = 0; i < elems.length; i++) {
if (elems[i].checked) num++;
}
return num;
}
}
}
function validateForm(form) {
var elems = form.elements,
errors = [],
eindex = [],
hash = new Hash;
var j = 0;
for (var i = 0; i < elems.length; i++)
for (var name in checker)
if (elems[i].nodeName != "FIELDSET" && hasClass(elems[i], name) && !checker[name].test(elems[i])) {
hash.add(elems[i], checker[name].msg);
errors.push(elems[i]);
}
var elen = hash.length;
while (elen--) {
(hash[elen].log())
}
return errors;
}
// add error flag
function markErrors(errors, flag) {
flag = flag || 'error';
var collect = typeof HTMLCollection === 'undefined' ? "" : HTMLCollection,
className;
if (errors.constructor === Array || errors.constructor === collect) {
var len = errors.length;
while (len--) {
className = errors[len].className + ' ' + flag;
errors[len].className = className.trim();
}
} else if (errors.constructor === String) {
className = errors[len].className + ' ' + flag;
errors[len].className = className.trim();
}
}
// remove elems's error flag
function removeError(elems, flag) {
flag = flag || 'error';
var collect = typeof HTMLCollection === 'undefined' ? "" : HTMLCollection;
if (elems.constructor === Array || elems.constructor === collect) {
var len = elems.length;
while (len--) {
removeClass(elems[len], flag);
}
} else if (elems.constructor === String) {
removeClass(elems, flag);
}
}
// trim input elements
function trimElems(elems) {
var collect = typeof HTMLCollection === 'undefined' ? "" : HTMLCollection;
if (elems.constructor === Array || elems.constructor === collect) {
var len = elems.length;
while (len--) {
if (elems[len].nodeName === "INPUT" && elems[len].getAttribute('type') === 'text') {
elems[len].value = elems[len].value.trim();
}
}
} else if (elems.constructor === String) {
if (elems[len].nodeName === "INPUT" && elems[len].getAttribute('type') === 'text') {
elems[len].value = elems[len].value.trim();
}
}
}
var is_array = function(value) {
return value && typeof value === 'object' && typeof value.length === 'number' && typeof value.splice === 'function' && !(value.propertyIsEnumerable('length'));
}
var hanoi = function(disc, src, aux, dst) {
if (disc > 0) {
hanoi(disc - 1, src, dst, aux);
log('move disc' + disc + ' from ' + src + ' to ' + dst);
hanoi(disc - 1, aux, src, dst);
}
}
var walkDOM = function walk(node, func) {
func(node);
node = node.firstChild;
while (node) {
walk(node, func);
node = node.nextSibling;
}
}
/* =============================================================================
Web
========================================================================== */
// encode data
function serialize(data) {
var result = [];
if (data.constructor === Array) {
for (var i = 0; i < data.length; i++) {
result.push(
data[i].name + '=' + encodeURIComponent(data[i].value))
}
} else {
// assuem this is an object combined with key and value
for (var key in data) {
result.push(
key + '=' + encodeURIComponent(data[key]))
}
}
return result.join('&');
}
function ajax(options, isCORS) {
// if there are some properties not defined, set it by default value
options = {
// type
type: options.type || 'POST',
// request url
url: options.url || '',
// timeout
timeout: options.timeout || 5000,
// call function
complete: options.complete || function() {},
error: options.error || function() {},
success: options.success || function() {},
// data from service
data: options.data || ''
};
var isIE = window.XDomainRequest ? true : false,
xml, timeout = options.timeout,
// check if request success
requestDone = false;
if (isCORS && isIE) {
xml = new window.XDomainRequest;
// if success
xml.onload = function() {
options.success(httpData(this, 'text'))
}
} else {
xml = new XMLHttpRequest;
}
xml.open(options.type, options.url + '?' + serialize(options.data), true);
setTimeout(function() {
requestDone = true;
}, timeout);
// if ready state change
xml.onreadystatechange = function() {
if (xml.readyState === 4 && !requestDone) {
// check if success
if (httpSucc(xml)) {
options.success(httpData(xml));
} else {
options.error();
}
options.complete();
xml = null;
}
}
xml.send();
// check if XMLHttpRequest success
function httpSucc(r) {
try {
return !r.status && (location.protocol === 'file:' || navigator.userAgent.indexOf("Safari") >= 0) ||
// status between 200 to 300
(r.status >= 200 && r.status < 300) ||
// not modify
r.status === 304;
} catch (e) {}
return false;
}
// inteprete data
function httpData(r, type) {
var data;
switch (type) {
case 'text':
data = r.responseText;
break;
case 'xml':
data = r.responseXML;
break;
default:
{
// get header
var ct = r.getResponseHeader('content-type'),
data = !type && ct && ct.indexOf('xml') >= 0;
data = type === 'xml' || data ? r.responseXML : r.responseText;
}
}
// if script
if (type === 'script') eval.call(window, data);
return data;
}
}
// toggle selection
function toggleSel(elem) {
if (typeof elem != undefined) {
if (!elem.hasClass('unsel')) {
elem.addClass('unsel');
// for IE < 10 and Opera
$('div', elem).each(function() {
var context = $(this);
context.attr('unselectable', 'on');
});
} else {
elem.removeClass('unsel');
// for IE < 10 and Opera
$('div', elem).each(function() {
var context = $(this);
context.attr('unselectable', 'off');
});
}
}
}
var json_parse = function() {
var at, // current index
ch, // current charater
escapee = {
'"': '"',
'\\': '\\',
'/': '/',
b: 'b',
f: '\f',
n: '\n',
r: '\r',
t: '\t'
},
text,
error = function(m) {
throw {
name: 'SyntaxError',
message: m,
at: at,
text: text
};
},
next = function(c) {
if (c && c !== ch) {
error('Expected "' + c + '" instead of "' + ch + '"');
}
ch = text.charAt(at);
at++;
return ch;
},
number = function() {
var number, string = '';
if (ch === '-') {
string = '-';
next('-');
}
while (ch >= '0' && ch <= '9') {
string += ch;
next();
}
if (ch === '.') {
string += '.';
while (next() && ch >= '0' && ch <= '9') {
string += ch;
}
}
if (ch === 'e' || ch === 'E') {
string += ch;
next();
if (ch === '-' || ch === '+') {
string += ch;
next();
}
}
while (ch >= '0' && ch <= '9') {
string += ch;
next();
}
number = +string;
if (isNaN(number)) {
error('Bad number');
} else {
return number;
}
},
string = function() {
var hex, i, string = '',
uffff;
if (ch === '"') {
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment