/**
* Copyright (c) 2008-2011, ASoft Ltd.
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are PROHIBITED.
*
* Common Helper Utilities.
*
*/
//#include "/js/lib/randomUUID.js"
//#include "/js/types.js"
//#include "/js/base64.js"
function isFloat(val) {
if(!val || (typeof val != "number")) {
return(false);
}
var isNumber = !isNaN(val);
if(isNumber) {
// TODO: how locale influences this code?
if (String(val).indexOf('.') != -1) {
return(true);
} else {
return(false);
}
} else {
return(false);
}
}
// Cross-browser keyboard scan codes parser
// Supports Mozilla, IE and Opera
function GetKeyCode(event) {
var evt = Event.extend(event || window.event);
if (evt.keyCode != 0) {
// not IE
if (Prototype.Browser.Mozilla || Prototype.Browser.WebKit) {
return {keyCode: evt.keyCode, charCode: evt.charCode};
}
// IE
if (typeof(evt.which) == "undefined") {
// stupid IE cannot give us character info, only keyCode is accessible
return {keyCode: evt.keyCode}; // charCode is undefined in case of IE
}
// Opera
if (evt.which == 0) {
return {keyCode: evt.keyCode, charCode: evt.charCode}
}
else {
return {keyCode: 0, charCode: evt.which};
}
}
else {
return {keyCode: 0, charCode: evt.charCode};
}
// assert (should not go here)
return null;
}
String.prototype.isDigit = function(){
return /^\d$/.test(this);
}
String.prototype.indicesOf = function(str){
var result = new Array();
for (var currentIndex = this.indexOf(str); currentIndex != -1; currentIndex = this.indexOf(str, currentIndex + 1))
result.push(currentIndex);
return result;
}
Element.clear = function(element){
if (!element) return;
$A(element.childNodes).each(Element.remove);
}
Element.getTextFast = function(element){
if (!element) return "";
return element.innerText || element.textContent || "";
}
Element.scrollContainerTo = function(container, element){
if (!container || !element || !Element.descendantOf(element, container)) return;
var offsetTop = 0;
var elem = element;
while (elem && (elem == container || Element.descendantOf(elem, container))){
offsetTop += elem.offsetTop;
elem = elem.offsetParent;
}
if (elem && elem != container && container.offsetParent == elem) offsetTop -= container.offsetTop;
if (offsetTop < container.scrollTop) container.scrollTop = offsetTop;
else if (offsetTop + element.offsetHeight > container.scrollTop + container.offsetHeight)
container.scrollTop = offsetTop + element.offsetHeight - container.offsetHeight;
}
Event.getKeyCode = function(event){
if (!event) return 0;
if (typeof event.charCode != "undefined") return event.charCode;
if (typeof event.which != "undefined") return event.which;
return event.keyCode;
}
function Extend(oValue, nLength, sEChar) {
var sB = "";
var sT = oValue.toString();
for (var i = 0; i < nLength - sT.length; ++i) sB += sEChar;
return sB+sT;
}
function createElementNS(doc, tag, ns) {
if(!doc.createElementNS) return doc.createNode(1, tag, ns);
else return doc.createElementNS(ns, tag);
}
function createElementAI(doc, tag) {
if(!doc.createElementNS) return doc.createNode(1, tag, AIURI);
else return doc.createElementNS(AIURI, tag);
}
function getSelectionStart(element) {
if(Prototype.Browser.IE) {
var docRange = document.selection.createRange();
if(element.nodeName == "TEXTAREA") {
var eleRange = docRange.duplicate();
eleRange.moveToElementText(element);
eleRange.setEndPoint("EndToStart",docRange);
return eleRange.text.length;
}
else {
var eleRange=element.createTextRange();
docRange.setEndPoint("EndToStart",eleRange);
return docRange.text.length;
}
}
else return element.selectionStart;
}
function getSelectionEnd(element) {
if(Prototype.Browser.IE) {
var docRange=document.selection.createRange();
if(element.nodeName == "TEXTAREA") {
var eleRange = docRange.duplicate();
eleRange.moveToElementText(element);
eleRange.setEndPoint("EndToEnd", docRange);
return eleRange.text.length;
}
else {
var eleRange=element.createTextRange();
docRange.setEndPoint("StartToStart",eleRange);
return docRange.text.length;
}
}
else return element.selectionEnd;
}
// NOTE: does not work correctly for multiline input
function setCaretPosition(element, position) {
if(Prototype.Browser.IE) {
var range = element.createTextRange();
range.collapse(true);//go to beginning of range
range.moveEnd('character', position);
range.moveStart('character', position);
range.select();
}
else {
element.selectionStart=position;
element.selectionEnd=position;
}
}
// NOTE: does not work correctly for multiline input
function setSelectionRange(element, start, end) {
if (typeof element.setSelectionRange == "function")
element.setSelectionRange(start, end);
else if (element.createTextRange){
var range = element.createTextRange();
range.collapse(true);
range.moveStart("character", start);
range.moveEnd("character", end - start);
range.select();
}
}
function replaceSelection(element, newText, selectNewText) {
var scrollTop = element.scrollTop;
if (Prototype.Browser.IE) {
var docRange = document.selection.createRange();
var eleRange = docRange.duplicate();
eleRange.moveToElementText(element);
if (!eleRange.inRange(docRange)) {
docRange = eleRange;
docRange.collapse(false);
}
docRange.text = newText;
if (!selectNewText) docRange.collapse(false);
docRange.select();
}
else {
var s = element.selectionStart;
var e = element.selectionEnd;
element.value = element.value.substr(0, s) + String(newText) + element.value.substr(e);
if (selectNewText) element.setSelectionRange(s, s + newText.length);
else element.setSelectionRange(s + newText.length, s + newText.length);
}
element.scrollTop = scrollTop;
}
function BindKeyDown(element, fCallback) {
if (Prototype.Browser.IE || Prototype.Browser.WebKit) {
element.observe('keydown', fCallback);
}
else {
element.observe('keypress', fCallback);
}
}
function UnbindKeyDown(element, fCallback) {
if (Prototype.Browser.IE || Prototype.Browser.WebKit) {
element.stopObserving('keydown', fCallback);
}
else {
element.stopObserving('keypress', fCallback);
}
}
function BindKeyUp(element, fCallback) {
if (Prototype.Browser.IE || Prototype.Browser.WebKit) {
element.observe('keyup', fCallback);
}
else {
element.observe('keypress', fCallback);
}
}
function getHexRGBColor(color) {
color = color.replace(/\s/g,"");
var aRGB = color.match(/^rgb\((\d{1,3}[%]?),(\d{1,3}[%]?),(\d{1,3}[%]?)\)$/i);
if(aRGB) {
color = '#';
for (var i=1; i<=3; i++) color += Math.round((aRGB[i][aRGB[i].length-1]=="%"?2.55:1)*parseInt(aRGB[i])).toString(16).replace(/^(.)$/,'0$1');
}
else color = color.replace(/^#?([\da-f])([\da-f])([\da-f])$/i, '$1$1$2$2$3$3');
return color;
}
// offsetType can be either "offsetLeft" or "offsetTop"
function getAbsoluteOffset(element, offsetType) {
var offset = 0;
var ie7fix = (Prototype.Browser.IE && offsetType == 'offsetTop' && navigator.userAgent.indexOf('MSIE 7') != -1);
while ( element ) {
offset += element[offsetType];
if (ie7fix && element.offsetParent && element.offsetParent.nodeName == 'TABLE') {
var th = Element.up(element, 'td, th');
if (th && th.nodeName == 'TH') offset -= th[offsetType];
}
element = element.offsetParent;
}
return offset;
}
function getRelativeOffset(element, offsetType) {
var offset=0;
while ( element && (
element.getStyle('position')!='absolute' &&
element.getStyle('position')!='relative' )
) {
offset += element[offsetType];
element = element.offsetParent;
}
return offset;
}
function GetCookie(name) {
var matches = document.cookie.match(new RegExp(
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
))
return matches ? decodeURIComponent(matches[1]) : undefined
}
var NOLOG = (document.location.hash.search('logger') == -1);
var GLoggerWindow = null;
var GLoggerGUID = null;
if (!NOLOG && !GLoggerWindow) {
var uid = Math.uuid();
GLoggerWindow = window.open("/logger.html", "LoggerWindow", 'location=1,status=1,scrollbars=1,width=900,height=400');
GLoggerWindow.moveTo(100,100);
GLoggerWindow.guid = uid;
GLoggerGUID = uid;
// create Logger window
if (!GLoggerWindow) {
alert("Failed to create Logger!");
NOLOG = true;
} else {
//alert("Logger started");
}
}
// add new line to log
function LogAdd(msg) {
if(NOLOG) return;
if (window.LoggerClosed && window.LoggerClosed[GLoggerGUID]) {
NOLOG=true; // you only live twice (c)
alert('Logger '+GLoggerGUID+' disabled');
return;
}
try {
if (!GLoggerWindow || !GLoggerWindow.document || !GLoggerWindow.document.body) throw new Error("Logger window was closed");
var eDiv = GLoggerWindow.document.createElement('div');
var eLine = GLoggerWindow.document.body.appendChild(eDiv);
eLine.innerHTML = msg;
}
catch (exc) {}
}
// append message to last line
function LogAppend(msg) {
if(NOLOG) return;
if (window.LoggerClosed && window.LoggerClosed[GLoggerGUID]) {
NOLOG=true; // you only live twice (c)
alert('Logger '+GLoggerGUID+' disabled');
return;
}
try {
if (!GLoggerWindow || !GLoggerWindow.document || !GLoggerWindow.document.body) throw new Error("Logger window was closed");
var body = GLoggerWindow.document.body;
if (!body.lastChild) LogL(""); // start new line if none
var eLine = body.lastChild;
if (!eLine) return; // shit happened
eLine.innerHTML = eLine.innerHTML + msg;
}
catch (exc) {}
}
function LogS(sMsg,sStyle) {
if(NOLOG){
if (window.console && console.warn && console.info && console.log){
var today=new Date();
if ("LoggerExc" == sStyle) console.warn(""+today.toLocaleTimeString()+"."+today.getMilliseconds()+" "+sMsg);
else if ("LoggerText" == sStyle) console.info(""+today.toLocaleTimeString()+"."+today.getMilliseconds()+" "+sMsg);
else console.log(""+today.toLocaleTimeString()+"."+today.getMilliseconds()+" "+sMsg);
}
return;
}
var today=new Date();
var h=Extend(today.getHours(),2,'0');
var m=Extend(today.getMinutes(),2,'0');
var s=Extend(today.getSeconds(),2,'0');
var ms=Extend(today.getMilliseconds(),3,'0');
if (typeof(sMsg) == 'undefined') sMsg = 'undefined';
else if (sMsg === null) sMsg = 'null';
else if (sMsg.toString) sMsg = sMsg.toString();
var sL=AXML.EscapeEntities(sMsg);
sL = sL.replace(/\$\$([^\$]*)\$\$/g, '$1');
LogAdd('['+h+':'+m+':'+s+'.'+ms+'] '+sL+'');
}
function LogSN(sMsg,sStyle) {
if(NOLOG) return;
if (typeof(sMsg) == 'undefined') sMsg = 'undefined';
else if (sMsg === null) sMsg = 'null';
else if (sMsg.toString) sMsg = sMsg.toString();
var sL=AXML.EscapeEntities(sMsg);
sL = sL.replace(/\$\$([^\$]*)\$\$/g, '$1');
LogAppend(''+sL+'');
}
function LogL(sMsg) {
LogS(sMsg, 'LoggerText');
}
function LogE(sMsg) {
LogS(sMsg, 'LoggerExc');
}
function Log(sMsg) {
LogSN(sMsg, 'LoggerText');
}
// Writes all Object's properties into the log
function showObject(obj) {
LogL("===========================================");
if (!obj) LogL("Empty Object");
else {
for (var key in obj) try {
LogL(key+": "+obj[key]);
} catch(e) {
LogE("Error: '"+key+"' property cannot be accessed: "+e.message);
}
}
LogL("===========================================");
}
// TODO: wrap this in logger class?
function ThrowError(sMessage) {
LogE(sMessage);
throw Error(sMessage);
}
var warningBox=undefined;
var warningBoxHiding=false;
function ShowTip(parent, tip) {
var offset = Element.positionedOffset(parent);
var x = offset[0];
var y = offset[1];
warningBox=document.getElementById('_warning_box_');
if(warningBox){
var content = Element.down(warningBox, "div.warning");
if (content) Element.update(content, tip);
var offsetParent = Element.getOffsetParent(parent);
if (offsetParent != warningBox.parentNode) offsetParent.appendChild(warningBox.parentNode.removeChild(warningBox));
var c00 = Element.down(warningBox, "td.top_left");
Element.setStyle(warningBox, {"top": y + parseInt(parent.offsetHeight) + "px", //
"left": x - (c00 ? c00.offsetWidth : 0) + "px"});
return;
}
warningBox=new Element('div', {"id": '_warning_box_', 'class': 'warning'});
var content=new Element('div', {'class': 'warning'}).update(tip);
var tbl=new Element('table', {'class': 'popup', "cellpadding": "0", "cellspacing": "0"});
var addTableRow = function(table, classnames){
var result = new Array(classnames.length);
var row = table.insertRow(-1);
for (var iii = 0; iii < classnames.length; ++iii){
result[iii] = row.insertCell(-1);
if (classnames[iii]) result[iii].className = classnames[iii];
}
return result;
}
var cells_top = addTableRow(tbl, ["top_left", "top", "top_right"]);
var cells_mid = addTableRow(tbl, ["left", "", "right"]);
cells_mid[1].appendChild(content);
addTableRow(tbl, ["bot_left", "bottom", "bot_right"]);
Element.setStyle(warningBox, {"position": "absolute", "left": "-10000px", "top": "-10000px", "clip": 'rect(0px, 0px, 0px, 0px)'});
warningBox.appendChild(tbl);
Element.getOffsetParent(parent).appendChild(warningBox);
Element.setStyle(warningBox, {"left": x - cells_top[0].offsetWidth + 'px'});
var slide = new Animation($(warningBox), 6, undefined, undefined, Animation.prototype.decelerate);
slide.addAnimation('clip', warningBox.scrollHeight+'px, 10000px, 10000px, 0px', '0px, 10000px, 10000px, 0px');
slide.addAnimation('top', y+'px', y+parseInt(parent.offsetHeight)+'px');
slide.run();
var arise= new Animation($(warningBox), 4, undefined, undefined, Animation.prototype.decelerate);
arise.addAnimation('opacity', '0', '1');
arise.run();
}
function HideTip() {
warningBox=document.getElementById('_warning_box_');
if(warningBox && !warningBoxHiding) {
warningBoxHiding=true;
var x=parseInt(warningBox.offsetLeft);
var y=parseInt(warningBox.offsetTop);
var slide = new Animation($(warningBox), 6, undefined, undefined, Animation.prototype.decelerate);
slide.addAnimation('clip', '0px, 10000px, 10000px, 0px', warningBox.scrollHeight+'px, 10000px, 10000px, 0px');
slide.addAnimation('top', y+'px', y-parseInt(warningBox.scrollHeight)+'px');
slide.onfinish=function() {
if (warningBox) Element.remove(warningBox);
warningBoxHiding=false;
warningBox=undefined;
}
slide.run();
var arise= new Animation($(warningBox), 7, undefined, undefined, Animation.prototype.decelerate);
arise.addAnimation('opacity', '1', '0');
arise.run();
}
}
var TwoToMinus52 = Math.pow(2., -52);
var TwoToMinus28 = Math.pow(2., -28);
var TwoToMinus4 = Math.pow(2., -4);
function parseBytesAsDouble(str) {
var sign = str.charCodeAt(7) & 0x80;
var exp = (str.charCodeAt(6) >> 4) | ((str.charCodeAt(7) & 0x7f) << 4);
if (exp == 0) {
// We do not correctly support subnormal (2^-1022) numbers
return (sign ? -0 : 0);
}
var m1 = str.charCodeAt(0) |
(str.charCodeAt(1) << 8) |
(str.charCodeAt(2) << 16);
var m2 = str.charCodeAt(3) |
(str.charCodeAt(4) << 8) |
(str.charCodeAt(5) << 16);
var m3 = (str.charCodeAt(6) & 0x0f) | (1 << 4);
if ( exp == 0x7ff && (m1 != 0 || m2 != 0 || m3 != 0) ) {
return Number.NaN;
}
else if ( exp == 0x7ff ) {
return (sign ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY)
}
var num = m1 * TwoToMinus52 + m2 * TwoToMinus28 + m3 * TwoToMinus4;
if (sign) num =-num;
return num * Math.pow(2, exp - 1023);
}
var _emptyTags = {
"IMG": true,
"BR": true,
"INPUT": true,
"META": true,
"LINK": true,
"PARAM": true,
"HR": true
};
function GetOuterHTML(ths) {
if(Prototype.Browser.IE) return ths.outerHTML;
var attrs = ths.attributes;
var str = "<" + ths.tagName;
for (var i = 0; i < attrs.length; i++) {
str += " " + attrs[i].name + "=\"" + attrs[i].value + "\"";
}
if (_emptyTags[ths.tagName]) return str + ">";
return str + ">" + ths.innerHTML + "" + ths.tagName + ">";
}
function StopEvent(evt) {
if (!evt) return;
if (evt.stop) evt.stop();
else evt.stopPropagation(); // for Fx 3.6a
}
function CompareObjects(a, b) {
if(typeof(a)!=typeof(b)) return false;
if(typeof(a)=="object") {
for(var e in a) {
if(typeof(a[e])=="function") continue;
if(!CompareObjects(a[e], b[e])) return false;
}
for(var e in b) {
if(typeof(b[e])=="function") continue;
if(a[e]===undefined) return false;
}
}
else return a==b;
return true;
}
// Some test cases:
//
// 145555555.99911122
//alert ("A: " + parseBytesAsDouble("\x81\x8b\xff\xc7\x00\x5a\xa1\x41"));
// -1.5
//alert ("A: " + parseBytesAsDouble("\x00\x00\x00\x00\x00\x00\xf8\xbf"));
// 3
//alert ("A: " + parseBytesAsDouble("\x00\x00\x00\x00\x00\x00\x08\x40"));
//