351 lines
7.8 KiB
JavaScript
351 lines
7.8 KiB
JavaScript
/**
|
|
* Utility functions:
|
|
* addListener, removeListener, onDomReady, stopEvent
|
|
* http_build_query, GET, POST, json_decode
|
|
* getOffset, String.trim, plural_ru, htmlspecialchars, unmg
|
|
*
|
|
* Version: 2016-03-06
|
|
*/
|
|
|
|
// Cross-browser add/remove event listeners
|
|
window.addListener = (function() {
|
|
return window.addEventListener
|
|
? function(el, type, fn) { el.addEventListener(type, fn, false); }
|
|
: function(el, type, fn) { el.attachEvent('on'+type, fn); };
|
|
})();
|
|
|
|
window.removeListener = (function() {
|
|
return window.removeEventListener
|
|
? function(el, type, fn) { el.removeEventListener(type, fn, false); }
|
|
: function(el, type, fn) { el.detachEvent('on'+type, fn); };
|
|
})();
|
|
|
|
// Cancel event bubbling and/or default action
|
|
window.stopEvent = function(ev, cancelBubble, preventDefault)
|
|
{
|
|
if (cancelBubble)
|
|
{
|
|
if (ev.stopPropagation)
|
|
ev.stopPropagation();
|
|
else
|
|
ev.cancelBubble = true;
|
|
}
|
|
if (preventDefault && ev.preventDefault)
|
|
ev.preventDefault();
|
|
ev.returnValue = !preventDefault;
|
|
return !preventDefault;
|
|
};
|
|
|
|
// Remove leading and trailing whitespace
|
|
if (!String.prototype.trim)
|
|
{
|
|
String.prototype.trim = function()
|
|
{
|
|
return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
|
};
|
|
}
|
|
|
|
window.onDomReady = (function()
|
|
{
|
|
var readyBound = false;
|
|
var bindReady = function()
|
|
{
|
|
if (readyBound)
|
|
return;
|
|
readyBound = true;
|
|
if (document.addEventListener)
|
|
{
|
|
document.addEventListener("DOMContentLoaded", function()
|
|
{
|
|
document.removeEventListener("DOMContentLoaded", arguments.callee, false);
|
|
ready();
|
|
}, false);
|
|
}
|
|
else if (document.attachEvent)
|
|
{
|
|
document.attachEvent("onreadystatechange", function()
|
|
{
|
|
if (document.readyState === "complete")
|
|
{
|
|
document.detachEvent( "onreadystatechange", arguments.callee );
|
|
ready();
|
|
}
|
|
});
|
|
if (document.documentElement.doScroll && window == window.top)
|
|
{
|
|
(function()
|
|
{
|
|
if (isReady)
|
|
return;
|
|
try
|
|
{
|
|
document.documentElement.doScroll("left");
|
|
}
|
|
catch(error)
|
|
{
|
|
setTimeout(arguments.callee, 0);
|
|
return;
|
|
}
|
|
ready();
|
|
})();
|
|
}
|
|
}
|
|
if (window.addEventListener)
|
|
window.addEventListener('load', ready, false);
|
|
else if (window.attachEvent)
|
|
window.attachEvent('onload', ready);
|
|
else
|
|
window.onload = ready;
|
|
};
|
|
var isReady = false;
|
|
var readyList = [];
|
|
var ready = function()
|
|
{
|
|
if (!isReady)
|
|
{
|
|
isReady = true;
|
|
if (readyList)
|
|
{
|
|
var fn_temp = null;
|
|
while (fn_temp = readyList.shift())
|
|
fn_temp.call(document);
|
|
readyList = null;
|
|
}
|
|
}
|
|
};
|
|
return function(fn) {
|
|
bindReady();
|
|
if (isReady)
|
|
fn.call(document);
|
|
else
|
|
readyList.push(fn);
|
|
return this;
|
|
};
|
|
})();
|
|
|
|
(function() {
|
|
var createRequestObject = function()
|
|
{
|
|
if (typeof XMLHttpRequest === 'undefined')
|
|
{
|
|
XMLHttpRequest = function() {
|
|
try { return new ActiveXObject("Msxml2.XMLHTTP"); }
|
|
catch(e) {}
|
|
try { return new ActiveXObject("Microsoft.XMLHTTP"); }
|
|
catch(e) {}
|
|
throw new Error("This browser does not support XMLHttpRequest.");
|
|
};
|
|
}
|
|
return new XMLHttpRequest();
|
|
};
|
|
var setCallback = function(r, cb)
|
|
{
|
|
r.onreadystatechange = function()
|
|
{
|
|
if (r.readyState == 4)
|
|
{
|
|
var d;
|
|
if (r.getResponseHeader('Content-Type') && r.getResponseHeader('Content-Type').indexOf('/json') > 0)
|
|
{
|
|
d = json_decode(r.responseText);
|
|
}
|
|
cb(r, d);
|
|
}
|
|
};
|
|
};
|
|
var build_array_query = function(data, prefix)
|
|
{
|
|
var s = '', k;
|
|
for (var i in data)
|
|
{
|
|
k = prefix ? prefix+'['+encodeURIComponent(i)+']' : encodeURIComponent(i);
|
|
if (typeof data[i] == 'object')
|
|
s += build_array_query(data[i], k);
|
|
else
|
|
s = s+'&'+k+'='+(data[i] === false || data[i] === null || data[i] === undefined ? '' : encodeURIComponent(data[i]));
|
|
}
|
|
return s;
|
|
};
|
|
window.http_build_query = function(data)
|
|
{
|
|
return build_array_query(data).substr(1);
|
|
};
|
|
|
|
window.GET = function(url, data, cb)
|
|
{
|
|
var r = createRequestObject();
|
|
r.withCredentials = true;
|
|
url = url + (url.indexOf('?') >= 0 ? '&' : '?') + http_build_query(data);
|
|
r.open('GET', url);
|
|
setCallback(r, cb);
|
|
r.send();
|
|
};
|
|
window.POST = function(url, data, cb)
|
|
{
|
|
var r = createRequestObject();
|
|
r.withCredentials = true;
|
|
r.open('POST', url);
|
|
setCallback(r, cb);
|
|
if (!window.FormData || !(data instanceof FormData))
|
|
{
|
|
r.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
data = http_build_query(data);
|
|
}
|
|
r.send(data);
|
|
};
|
|
|
|
window.cloneObject = function(o)
|
|
{
|
|
if (!o || 'object' !== typeof o)
|
|
return o;
|
|
if (o instanceof Date)
|
|
return new Date(+o);
|
|
var c = o instanceof Array ? [] : {};
|
|
var p, v;
|
|
for (p in o)
|
|
if (o.hasOwnProperty(p))
|
|
c[p] = cloneObject(o[p]);
|
|
return c;
|
|
}
|
|
|
|
// Get element position using getBoundingClientRect()
|
|
var getOffsetRect = function(elem)
|
|
{
|
|
var box = elem.getBoundingClientRect();
|
|
|
|
var body = document.body;
|
|
var docElem = document.documentElement;
|
|
|
|
var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
|
|
var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
|
|
var clientTop = docElem.clientTop || body.clientTop || 0;
|
|
var clientLeft = docElem.clientLeft || body.clientLeft || 0;
|
|
var top = box.top + scrollTop - clientTop;
|
|
var left = box.left + scrollLeft - clientLeft;
|
|
|
|
return { top: Math.round(top), left: Math.round(left) };
|
|
};
|
|
|
|
// Get element position using sum of offsetTop/offsetLeft
|
|
var getOffsetSum = function(elem)
|
|
{
|
|
var top = 0, left = 0;
|
|
while(elem)
|
|
{
|
|
top = top + parseInt(elem.offsetTop);
|
|
left = left + parseInt(elem.offsetLeft);
|
|
elem = elem.offsetParent;
|
|
}
|
|
return { top: top, left: left };
|
|
};
|
|
|
|
// Get element position, relative to the top-left corner of page
|
|
window.getOffset = function(elem)
|
|
{
|
|
if (elem.getBoundingClientRect)
|
|
return getOffsetRect(elem);
|
|
else
|
|
return getOffsetSum(elem);
|
|
};
|
|
|
|
window.getEventCoord = function(e)
|
|
{
|
|
if (!e)
|
|
e = window.event;
|
|
if (e && e.pageX == null && e.clientX != null)
|
|
{
|
|
var html = document.documentElement;
|
|
var body = document.body;
|
|
e.pageX = e.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0);
|
|
e.pageY = e.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0);
|
|
}
|
|
if (e && !e.which && e.button)
|
|
{
|
|
if (e.button & 1) e.which = 1;
|
|
else if (e.button & 4) e.which = 2;
|
|
else if (e.button & 2) e.which = 3;
|
|
}
|
|
return e;
|
|
}
|
|
|
|
})();
|
|
|
|
window.json_decode = function(text)
|
|
{
|
|
if (!text)
|
|
{
|
|
return null;
|
|
}
|
|
try
|
|
{
|
|
if (JSON)
|
|
{
|
|
return JSON.parse(text);
|
|
}
|
|
return eval(text);
|
|
}
|
|
catch(e)
|
|
{
|
|
if (window.console)
|
|
{
|
|
console.log(e);
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
window.plural_ru = function(count, one, few, many)
|
|
{
|
|
var sto = count % 100;
|
|
if (sto >= 10 && sto <= 20)
|
|
return many;
|
|
switch (count % 10)
|
|
{
|
|
case 1: return one;
|
|
case 2:
|
|
case 3:
|
|
case 4: return few;
|
|
}
|
|
return many;
|
|
};
|
|
|
|
window.htmlspecialchars = function(text)
|
|
{
|
|
return (''+text).replace(/&/g, '&')
|
|
.replace(/'/g, ''') // '
|
|
.replace(/"/g, '"') // "
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>');
|
|
};
|
|
|
|
window.unmg = function(id, str)
|
|
{
|
|
str = decodeURIComponent(str.replace(/([\x20-\x24\x26-\x79])|(%..)/g, function(m, m1, m2) { return m2 || ('%'+(159-m1.charCodeAt(0)).toString(16)); }));
|
|
document.getElementById(id).innerHTML = '<a href="ma'+'ilt'+'o:'+str+'">'+str+'</a>';
|
|
};
|
|
|
|
window.curStyle = function(e)
|
|
{
|
|
return window.getComputedStyle ? getComputedStyle(e) : e.currentStyle;
|
|
};
|
|
|
|
window.addStylesheet = function(url)
|
|
{
|
|
var s = document.createElement('link');
|
|
s.setAttribute('rel', 'stylesheet');
|
|
s.setAttribute('type', 'text/css');
|
|
s.setAttribute('href', url);
|
|
document.getElementsByTagName('head')[0].appendChild(s);
|
|
};
|
|
|
|
window.addCSS = function(css)
|
|
{
|
|
var s = document.createElement('style');
|
|
s.setAttribute('type', 'text/css');
|
|
s.innerHTML = css;
|
|
document.getElementsByTagName('head')[0].appendChild(s);
|
|
};
|
|
|
|
window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
|
|
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
|