/** * 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 + ""; } 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")); //