JavaXT
|
|
utils Classif(!javaxt) var javaxt={}; if(!javaxt.dhtml) javaxt.dhtml={}; //****************************************************************************** //** Utils //*****************************************************************************/ /** * Common functions and utilities used by the webcontrols * ******************************************************************************/ javaxt.dhtml.utils = { //************************************************************************** //** get //************************************************************************** /** Used to execute an HTTP GET request. Example: <pre> get(url + "?filter=" + encodeURIComponent(filter), { success: function(text){ var arr = JSON.parse(text).records; }, failure: function(request){ alert(request.status); } }); </pre> * @param url Required. * @param config Optional. Common config settings include a "success" * callback function, "failure" callback function, and "payload". Note that * if a payload is given, an HTTP POST request will be executed. See the * http() method for a full range of options. */ get: function(url, config){ if (config.payload!=null){ //convert to post request var payload = config.payload; delete config.payload; return javaxt.dhtml.utils.post(url, payload, config); } var settings = { method: "GET", payload: null }; javaxt.dhtml.utils.merge(settings, config); return javaxt.dhtml.utils.http(url, settings); }, //************************************************************************** //** post //************************************************************************** /** Used to execute an HTTP POST request. */ post: function(url, payload, config){ var settings; if (payload.payload){ settings = payload; settings.method = "POST"; } else{ var settings = { method: "POST", payload: payload }; javaxt.dhtml.utils.merge(settings, config); } return javaxt.dhtml.utils.http(url, settings); }, //************************************************************************** //** delete //************************************************************************** /** Used to execute an HTTP DELETE request. */ delete: function(url, config){ config.method = "DELETE"; return javaxt.dhtml.utils.http(url, config); }, //************************************************************************** //** http //************************************************************************** /** Used to execute an HTTP request. */ http: function(url, config){ var cache = false; //no caching by default! if (config.cache){ if (config.cache==true) cache = true; } if (!cache){ if (url.indexOf("?")==-1) url += "?"; url += "&_=" + new Date().getTime(); } var method = config.method; var success = config.success; var scope = config.scope; var async = true; if (config.async){ if (config.async!=false) async = true; } var failure = config.failure; if (typeof failure === "undefined") failure = function(request){ if (request.status!==0){ alert(request); } }; var request = new XMLHttpRequest(); if (config.username && config.password){ request.open(method, url, async, config.username, config.password); request.setRequestHeader("Authorization", "Basic " + btoa(config.username + ":" + config.password)); //<-- Needed to add this sometime in mid 2018... } else{ request.open(method, url, async); } if (!cache) request.setRequestHeader("Cache-Control", "no-cache, no-transform"); request.onreadystatechange = function(){ if (request.readyState === 4) { if (request.status>=200 && request.status<300){ if (success) success.apply(scope, [request.responseText, request.responseXML, request.responseURL, request]); } else{ if (failure) failure.apply(scope, [request]); } } }; if (config.payload) request.send(config.payload); else request.send(); return request; }, //************************************************************************** //** getParameter //************************************************************************** /** Returns the value of a given parameter name in a URL querystring * @param name Parameter name * @param url URL (e.g. window.location.href) */ getParameter: function(name, url){ name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]"); if (!url) url = window.location.href; var regexS = "[\\?&]"+name+"=([^]*)"; var regex = new RegExp( regexS ); var results = regex.exec(url); if (results == null) return ""; else return results[1]; }, //************************************************************************** //** merge //************************************************************************** /** Used to merge properties from one json object into another. Credit: * https://github.com/stevenleadbeater/JSONT/blob/master/JSONT.js */ merge: function(settings, defaults) { var merge = function(settings, defaults) { if (settings==null) return; //Check if the settings is an array. Do not merge arrays! if (javaxt.dhtml.utils.isArray(settings)){ return; } for (var p in defaults) { if (defaults.hasOwnProperty(p) && typeof settings[p] !== "undefined") { if (p!=0) //<--Added this as a bug fix merge(settings[p], defaults[p]); } else { settings[p] = defaults[p]; } } }; merge(settings, defaults); return settings; }, //************************************************************************** //** clone //************************************************************************** /** Used to clone a json object */ clone: function(obj){ return javaxt.dhtml.utils.merge({}, obj); }, //************************************************************************** //** isDirty //************************************************************************** /** Returns true if the given json object differs from the original. */ isDirty: function(obj, org){ var isEmpty = javaxt.dhtml.utils.isEmpty; var a = isEmpty(obj); var b = isEmpty(org); if ((a==true && b==false) || (b==true && a==false)) return true; var d = javaxt.dhtml.utils.diff(obj, org); return !isEmpty(d); }, //************************************************************************** //** diff //************************************************************************** /** Used to compare 2 json objects. Returns a json object with differences. * Credit: https://stackoverflow.com/a/13389935/ */ diff: function(obj1, obj2){ var isEmpty = javaxt.dhtml.utils.isEmpty; var merge = javaxt.dhtml.utils.merge; var diff = function(obj1, obj2){ var ret = {},rett; for (var i in obj2) { rett = {}; if (typeof obj2[i] === 'object'){ if (obj1.hasOwnProperty(i)){ rett = diff(obj1[i], obj2[i]); if (!isEmpty(rett) ){ ret[i]= rett; } } else{ ret[i] = obj2[i]; } } else{ if (!obj1 || !obj1.hasOwnProperty(i) || obj2[i] !== obj1[i]) { ret[i] = obj2[i]; } } } return ret; }; var d1 = diff(obj1, obj2); var d2 = diff(obj2, obj1); return merge(d1,d2); }, //************************************************************************** //** isEmpty //************************************************************************** /** Returns true if the given json object has no key/value pairs. */ isEmpty: function(obj){ return JSON.stringify(obj) === "{}"; }, //************************************************************************** //** isArray //************************************************************************** /** Used to check whether a given object is an array. Note that this check * does not use the "instanceof Array" approach because of issues with * frames. */ isArray: function(obj){ return (Object.prototype.toString.call(obj)==='[object Array]'); }, //************************************************************************** //** isString //************************************************************************** /** Return true if a given object is a string. */ isString: function(obj){ return (typeof obj === "string"); // || obj instanceof String) }, //************************************************************************** //** isNumber //************************************************************************** /** Return true if a given object is a number or can be parsed into a number. */ isNumber: function(n) { if (typeof n === "number") return true; if (typeof n !== "string") n = ""+n; return !isNaN(parseFloat(n)) && !isNaN(n - 0); }, //************************************************************************** //** isDate //************************************************************************** /** Return true if a given object can be parsed into a date. Returns false * if the object is a number (e.g. "3", "1.2") */ isDate: function(d) { //Don't pass numbers to Date.parse if (typeof d === "string" || typeof d === "number"){ var n = (d+"").replace(/[^-+0-9,.]+/g,""); if (d===n){ return false; } } return !isNaN(Date.parse(d)); }, //************************************************************************** //** isElement //************************************************************************** /** Return true if a given object is a DOM element. */ isElement: function(obj){ return (obj instanceof Element); //TODO: tighten up the logic... }, //************************************************************************** //** setStyle //************************************************************************** /** Used to set the style for a given element, replacing whatever style was * there before. * @param el DOM element. * @param style If a string is provided, assumes that the string represents * a CSS class name update "class" attribute of given element. If a JSON * object is provided, will assign the key/value pairs to the "style" * attribute of the node. */ setStyle: function(el, style){ if (el===null || el===0) return; if (style===null) return; //Special case for iScroll if (typeof IScroll !== 'undefined'){ if (el instanceof IScroll){ var indicators = el.indicators; if (indicators){ var indicatorClass = "iScrollIndicator"; if (style.indicator) indicatorClass = style.indicator; for (var i=0; i<indicators.length; i++){ var indicator = indicators[i].indicator; indicator.className = indicatorClass; var scrollbar = indicator.parentNode; if (scrollbar.className.indexOf("iScrollVerticalScrollbar")){ if (style.verticalScrollbar){ scrollbar.className = scrollbar.className.replace("iScrollVerticalScrollbar", style.verticalScrollbar); } } else{ if (style.horizontalScrollbar){ scrollbar.className = scrollbar.className.replace("iScrollHorizontalScrollbar", style.horizontalScrollbar); } } } } return; } } //el.style = ''; el.removeAttribute("style"); if (javaxt.dhtml.utils.isString(style)){ el.className = style; } else{ for (var key in style){ if (style.hasOwnProperty(key)){ var val = style[key]; if (key==="content"){ el.innerHTML = val; } else{ el.style[key] = val; } } } } }, //************************************************************************** //** addStyle //************************************************************************** /** Used to add style to a given element. * @param el DOM element. * @param style If a string is provided, assumes that the string represents * a CSS class name update "class" attribute of given element. If a JSON * object is provided, will assign the key/value pairs to the "style" * attribute of the node. */ addStyle: function(el, style){ if (el===null || el===0) return; if (style===null) return; if (javaxt.dhtml.utils.isString(style)){ style = style.replace(/^\s*/, "").replace(/\s*$/, ""); if (el.hasAttribute("class")){ var arr = el.className.split(" "); for (var i=0; i<arr.length; i++){ var className = arr[i].replace(/^\s*/, "").replace(/\s*$/, ""); if (className===style) return; } el.className += " " + style; } else{ el.className = style; } } else{ for (var key in style){ var val = style[key]; el.style[key] = val; if (key==="transform"){ el.style["-webkit-" +key] = val; } } } }, //************************************************************************** //** hasStyleRule //************************************************************************** /** Returns true if there is a style rule defined for a given selector. * @param selector CSS selector (e.g. ".deleteIcon", "h2", "#mid") */ hasStyleRule: function(selector) { var hasRule = function(selector, rules){ if (!rules) return false; for (var i=0; i<rules.length; i++) { var rule = rules[i]; if (rule.selectorText){ var arr = rule.selectorText.split(','); for (var j=0; j<arr.length; j++){ if (arr[j].indexOf(selector) !== -1){ var txt = trim(arr[j]); if (txt===selector){ return true; } else{ var colIdx = txt.indexOf(":"); if (colIdx !== -1){ txt = trim(txt.substring(0, colIdx)); if (txt===selector){ return true; } } } } } } } return false; }; var trim = function(str){ return str.replace(/^\s*/, "").replace(/\s*$/, ""); }; for (var i=0; i<document.styleSheets.length; i++){ var rules; try{ rules = document.styleSheets[i].rules || document.styleSheets[i].cssRules; if (hasRule(selector, rules)){ return true; } } catch(e){ //Security error, typically occurs when running on the local file system (vs web server) } var imports = document.styleSheets[i].imports; if (imports){ for (var j=0; j<imports.length; j++){ rules = imports[j].rules || imports[j].cssRules; if (hasRule(selector, rules)) return true; } } } return false; }, //************************************************************************** //** addNoSelectRule //************************************************************************** /** Inserts the "javaxt-noselect" class into the document if it is not * present. */ addNoSelectRule: function(){ var hasStyleRule = javaxt.dhtml.utils.hasStyleRule; if (!hasStyleRule(".javaxt-noselect")){ var head = document.head || document.getElementsByTagName('head')[0]; var sheet = document.createElement('style'); sheet.innerHTML = ".javaxt-noselect {\n"; var arr = ["-webkit-","-moz-","-o-","-ms-","-khtml-",""]; for (var i=0; i<arr.length; i++){ sheet.innerHTML += arr[i] + "user-select: none;\n"; } sheet.innerHTML += "}"; head.appendChild(sheet); } }, //************************************************************************** //** createElement //************************************************************************** /** Used to create a DOM element * @param type Node type (string). Example "div". This field is required. * @param obj Optional. If a DOM element is provided, will append the newly * created node into the element. Otherwise, will assume that the object is * a style. * @param style Optional. If a string is provided, assumes that the string * represents a CSS class name update "class" attribute of the newly created * node. If a JSON object is provided, will assign the key/value pairs to * the "style" attribute. */ createElement: function(type, obj, style){ var setStyle = javaxt.dhtml.utils.setStyle; var el = document.createElement(type); if (obj){ if (javaxt.dhtml.utils.isElement(obj)){ setStyle(el, style); obj.appendChild(el); } else{ //Shift args (2nd arg might be a style) if (!style) style = obj; setStyle(el, style); } } else{ setStyle(el, style); } return el; }, //************************************************************************** //** createTable //************************************************************************** /** Used to create a table element. * @param parent DOM element to append to (optional) * @returns Table element (DOM object) with custom methods */ createTable: function(parent){ var createElement = javaxt.dhtml.utils.createElement; var table = createElement('table', parent, { width: "100%", height: "100%", margin: 0, padding: 0, borderCollapse: "collapse" }); table.cellSpacing = 0; table.cellPadding = 0; var tbody = createElement('tbody', table); table.addRow = function(style){ var tr = createElement("tr", tbody, style); tr.addColumn = function(style){ return createElement("td", tr, style); }; return tr; }; table.removeRow = function(tr){ if (!tr) return; tbody.removeChild(tr); }; table.getRows = function(){ return tbody.childNodes; }; table.clear = function(){ tbody.innerHTML = ""; }; if (parent) parent.appendChild(table); return table; }, //************************************************************************** //** getSuggestedColumnWidths //************************************************************************** /** Used to analyze a given dataset and suggest column widths for a table or * a datagrid * @param records A two-dimensional array representing rows and columns * @param pixelsPerChar Approximate, average width of a character * @returns JSON object with various stats and suggestedWidths */ getSuggestedColumnWidths: function(records, pixelsPerChar){ var widths = []; var zscores = []; var totalWidth = 0; var headerWidth = 0; var suggestedWidths = []; var columns = records[0]; if (columns.length>1){ for (var i=0; i<columns.length; i++){ var len = 0; var column = columns[i]; if (column!=null) len = (column+"").length; widths.push(len); headerWidth+=len*pixelsPerChar; } for (var i=0; i<records.length; i++){ var record = records[i]; for (var j=0; j<record.length; j++){ var rec = record[j]; var len = 0; if (rec!=null){ var str = rec+""; var r = str.indexOf("\r"); var n = str.indexOf("\n"); if (r==-1){ if (n>-1) str = str.substring(0, n); } else{ if (n>-1){ str = str.substring(0, Math.min(r,n)); } else str = str.substring(0, r); } len = str.length*pixelsPerChar; } widths[j] = Math.max(widths[j], len); } } //Get total width for (var i=0; i<widths.length; i++){ totalWidth += widths[i]; } //Check if any columns are super wide using z-scores var outliers = []; zscores = javaxt.dhtml.utils.getZScores(widths, true); for (var i=0; i<zscores.length; i++){ if (zscores[i]>1) outliers.push(i); } //Come up with suggestedWidths if (outliers.length==1){ //If we have one column that's really wide, let's make it 100% //width and use pixels for the other columns var outlier = outliers[0]; for (var i=0; i<widths.length; i++){ var colWidth = i==outlier ? "100%" : widths[i] + "px"; suggestedWidths.push(colWidth); } } else{ //Use percentages for all the fields for (var i=0; i<widths.length; i++){ var colWidth = ((widths[i]/totalWidth)*100)+"%"; suggestedWidths.push(colWidth); } } } else{ widths.push(1); totalWidth = 1; suggestedWidths.push("100%"); } return { widths: widths, zscores: zscores, totalWidth: totalWidth, headerWidth: headerWidth, suggestedWidths: suggestedWidths }; }, //************************************************************************** //** onRender //************************************************************************** /** Used to check whether DOM element has been added to the document. Calls * a callback if it exists or when it is added. */ onRender: function(el, callback){ var w = el.offsetWidth; if (w===0 || isNaN(w)){ var timer; var checkWidth = function(){ var w = el.offsetWidth; if (w===0 || isNaN(w)){ timer = setTimeout(checkWidth, 100); } else{ clearTimeout(timer); if (callback) callback.apply(el, [el]); } }; timer = setTimeout(checkWidth, 100); } else{ if (callback) callback.apply(el, [el]); } }, //************************************************************************** //** updateDOM //************************************************************************** /** Used to update the default befaviour of the browser to prevent things * like right mouse click, scrolling beyond a page, and drag and drop. */ updateDOM: function(){ if (document.javaxt) return; //Disable right-click context menu document.oncontextmenu = function(e){ return false; }; //Add logic to prevent touch devices like iPad from scrolling beyond the document //http://stackoverflow.com/a/26853900 var firstMove; window.addEventListener('touchstart', function (e) { firstMove = true; }); window.addEventListener('touchmove', function (e) { if (firstMove) { e.preventDefault(); firstMove = false; } }); //Watch for drag and drop events if (!document.body) document.body = document.getElementsByTagName("body")[0]; var body = document.body; body.addEventListener('dragover', function(e) { e.stopPropagation(); e.preventDefault(); return false; }, false); body.addEventListener('drop', function(e) { e.stopPropagation(); e.preventDefault(); return false; }, false); document.javaxt = {}; }, //************************************************************************** //** getRect //************************************************************************** /** Returns the geometry of a given element. */ getRect: function(el){ if (el.getBoundingClientRect){ return el.getBoundingClientRect(); } else{ var x = 0; var y = 0; var w = el.offsetWidth; var h = el.offsetHeight; function isNumber(n){ return n === parseFloat(n); } var org = el; do{ x += el.offsetLeft - el.scrollLeft; y += el.offsetTop - el.scrollTop; } while ( el = el.offsetParent ); el = org; do{ if (isNumber(el.scrollLeft)) x -= el.scrollLeft; if (isNumber(el.scrollTop)) y -= el.scrollTop; } while ( el = el.parentNode ); return{ x: x, y: y, left: x, right: x+w, top: y, bottom: y+h, width: w, height: h }; } }, //************************************************************************** //** intersects //************************************************************************** /** Used to test whether two rectangles intersect. */ intersects: function(r1, r2) { return !(r2.left > r1.right || r2.right < r1.left || r2.top > r1.bottom || r2.bottom < r1.top); }, //************************************************************************** //** getAreaOfIntersection //************************************************************************** /** Returns the area of intersection between 2 rectangles. */ getAreaOfIntersection: function(r1, r2){ var minX = r2.left; var maxX = r2.right; var minY = r2.top; var maxY = r2.bottom; var left = r1.left; var right = r1.right; var top = r1.top; var bottom = r1.bottom; if (left<minX) left=minX; if (right>maxX) right=maxX; if (top<minY) top=minY; if (bottom>maxY) bottom=maxY; var w = right-left; var h = bottom-top; return w*h; }, //************************************************************************** //** getZScores //************************************************************************** /** Returns z-scores for a given set of values * @param values An array of numbers * @param normalize If true, will return positive values for z-scores * @returns An array of decimal values representing z-scores */ getZScores: function(values, normalize){ //Sum all the values var total = 0; for (var i=0; i<values.length; i++){ total+=values[i]; } //Work out the Mean (the simple average of the numbers) var numSamples = values.length; var mean = total / numSamples; //Then for each number: subtract the Mean and square the result var sum = 0.0; for (var i=0; i<values.length; i++){ var x = values[i]; sum += Math.pow(x - mean, 2); } //Then compute the square root of the mean of the squared differences var std = Math.sqrt(sum/numSamples); //Calculate z-scores var zScores = []; for (var i=0; i<values.length; i++){ var x = values[i]; var z = (x - mean)/std; if (z<0 && normalize) z = -z; zScores.push(z); } return zScores; }, //************************************************************************** //** initDrag //************************************************************************** initDrag : function(dragHandle, config){ javaxt.dhtml.utils.addNoSelectRule(); if (!config) config = {}; var holdDelay = config.holdDelay; if (isNaN(holdDelay)) holdDelay = 50; var cursor = dragHandle.style.cursor; if (!cursor) cursor = "default"; //This timeout, started on mousedown, triggers the beginning of a hold var holdStarter = null; //This flag indicates the user is currently holding the mouse down var holdActive = false; //OnClick //div.onclick = NOTHING!! not using onclick at all - onmousedown and onmouseup take care of everything //MouseDown dragHandle.onmousedown = function(e){ //Set the holdStarter and wait for the predetermined delay, and then begin a hold holdStarter = setTimeout(function() { holdStarter = null; holdActive = true; //Initiate drag startDrag(e); //Add event listeners if (document.addEventListener) { document.addEventListener("mousemove", onMouseMove); document.addEventListener("mouseup", onMouseUp); } else if (document.attachEvent) { document.attachEvent("onmousemove", onMouseMove); document.attachEvent("onmouseup", onMouseUp); } }, holdDelay); }; //MouseUp var onMouseUp = function(e){ //If the mouse is released immediately (i.e., a click), before the //holdStarter runs, then cancel the holdStarter and do the click if (holdStarter) { clearTimeout(holdStarter); //simple click } //Otherwise, if the mouse was being held, end the hold else if (holdActive) { holdActive = false; //Remove event listeners if (document.removeEventListener) { document.removeEventListener("mousemove", onMouseMove); document.removeEventListener("mouseup", onMouseUp); } else if (document.detachEvent) { document.detachEvent("onmousemove", onMouseMove); document.detachEvent("onmouseup", onMouseUp); } //Update cursor dragHandle.style.cursor = cursor; if (config.onDragEnd) config.onDragEnd.apply(dragHandle, [e]); //Remove the "javaxt-noselect" class var body = document.getElementsByTagName('body')[0]; setTimeout(function() { body.className = body.className.replace( /(?:^|\s)javaxt-noselect(?!\S)/g , '' ); }, 800); } }; dragHandle.onmouseup = onMouseUp; //Start touch (similar to "onmousedown") dragHandle.ontouchstart = function(e) { e.preventDefault(); var touch = e.touches[0]; var x = touch.pageX; var y = touch.pageY; //Set the holdStarter and wait for the holdDelay before starting the drag holdStarter = setTimeout(function() { holdStarter = null; holdActive = true; //Initiate drag startDrag({ clientX: x, clientY: y }); //Add "touchmove" event listener if (document.removeEventListener) { dragHandle.addEventListener("touchmove", onTouchMove); } else if (document.detachEvent) { dragHandle.attachEvent("ontouchmove", onTouchMove); } }, holdDelay); }; //End touch (similar to "onmouseup") dragHandle.ontouchend = function(e) { //Remove "touchmove" event listener if (document.removeEventListener) { dragHandle.removeEventListener("touchmove", onTouchMove); } else if (document.detachEvent) { dragHandle.detachEvent("ontouchmove", onTouchMove); } //If the mouse is released immediately (i.e., a click), before the //holdStarter runs, then cancel the holdStarter and do the click if (holdStarter) { clearTimeout(holdStarter); //Click Event! } //Otherwise, if the mouse was being held, end the hold else if (holdActive) { holdActive = false; //End drag! } }; var onMouseMove = function(e){ var x = e.clientX; var y = e.clientY; if (config.onDrag) config.onDrag.apply(dragHandle, [x,y]); }; var onTouchMove = function(e) { e.preventDefault(); var touch = e.touches[0]; var x = touch.pageX; var y = touch.pageY; onMouseMove({ clientX: x, clientY: y }); }; var startDrag = function(e){ var x = e.clientX; var y = e.clientY; if (config.onDragStart) config.onDragStart.apply(dragHandle, [x,y,e]); //Disable text selection in the entire document - very important! var body = document.getElementsByTagName('body')[0]; if (!body.className.match(/(?:^|\s)javaxt-noselect(?!\S)/) ){ body.className += (body.className.length==0 ? "" : " ") + "javaxt-noselect"; } }; }, //************************************************************************** //** addResizeListener //************************************************************************** /** Used to watch for resize events for a given element. Credit: * http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/ */ addResizeListener: function(element, fn){ var destroy, isDestroyed = false; var requestFrame = (function(){ var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || function(fn){ return window.setTimeout(fn, 20); }; return function(fn){ return raf(fn); }; })(); var cancelFrame = (function(){ var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.clearTimeout; return function(id){ return cancel(id); }; })(); function resizeListener(e, fn){ var el = e.target || e.srcElement; if (el.raf) cancelFrame(el.raf); el.raf = requestFrame(function(){ if (isDestroyed) return; fn.call(el.resizeTrigger, e); }); }; if (document.attachEvent) { //non-standard JS function implemented in IE8 and below element.resizeTrigger = element; var f = function(e){ resizeListener(e, fn); }; element.attachEvent('onresize', f); destroy = function(){ element.detachEvent('onresize', f); }; } else { if (getComputedStyle(element).position == 'static') element.style.position = 'relative'; var obj = element.resizeTrigger = document.createElement('object'); obj.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;'); obj.resizeElement = element; obj.onload = function(e){ this.contentDocument.defaultView.resizeTrigger = this.resizeElement; this.contentDocument.defaultView.addEventListener('resize', function(e){ resizeListener(e, fn); }); }; var isIE = navigator.userAgent.match(/Trident/); obj.type = 'text/html'; if (isIE) element.appendChild(obj); obj.data = 'about:blank'; if (!isIE) element.appendChild(obj); destroy = function(){ element.removeChild(obj); }; } return { destroy: function(){ try{ destroy(); } catch(e){} isDestroyed = true; } }; }, //************************************************************************** //** getHighestElements //************************************************************************** /** Returns an array of elements at the highest z-index in the document */ getHighestElements: function(obj){ var arr = []; var highestIndex = 0; var currentIndex = 0; var elArray = Array(); if(obj){elArray = obj.getElementsByTagName('*');}else{elArray = document.getElementsByTagName('*');} for (var i=0; i < elArray.length; i++){ var el = elArray[i]; if (el.currentStyle){ currentIndex = parseFloat(el.currentStyle['zIndex']); } else if(window.getComputedStyle){ currentIndex = parseFloat(document.defaultView.getComputedStyle(el,null).getPropertyValue('z-index')); } if(!isNaN(currentIndex)){ if (currentIndex > highestIndex){ highestIndex = currentIndex; arr = []; arr.push(el); } else if (currentIndex===highestIndex){ arr.push(el); } } } return { zIndex: highestIndex, elements: arr, contains: function(el){ for (var i=0; i<arr.length; i++){ if (arr[i]===el) return true; } return false; } }; }, //************************************************************************** //** getNextHighestZindex //************************************************************************** /** Returns an integer represeting the highest z-value of all the DOM * elements that appear with the given object + 1 */ getNextHighestZindex: function(obj){ var highestIndex = javaxt.dhtml.utils.getHighestElements(obj).zIndex; return(highestIndex+1); }, //************************************************************************** //** addShowHide //************************************************************************** /** Adds show/hide methods to a DOM element or javaxt component */ addShowHide: function(el){ if (el.el){ //Special case for javaxt components var me = el; me.show = function(){ me.el.style.visibility = ''; me.el.style.display = ''; }; me.hide = function(){ me.el.style.visibility = 'hidden'; me.el.style.display = 'none'; }; me.isVisible = function(){ return !(me.el.style.visibility === 'hidden' && me.el.style.display === 'none'); }; } else{ el.show = function(){ this.style.visibility = ''; this.style.display = ''; }; el.hide = function(){ this.style.visibility = 'hidden'; this.style.display = 'none'; }; el.isVisible = function(){ return !(this.style.visibility === 'hidden' && this.style.display === 'none'); }; } }, //************************************************************************** //** destroy //************************************************************************** /** Used to help destroy javaxt components */ destroy: function(me){ if (!me.el) return; me.el.innerHTML = ""; var parent = me.el.parentNode; if (parent) parent.removeChild(me.el); var props = []; for (var key in me) { if (me.hasOwnProperty(key)){ props.push(key); } } for (var i=0; i<props.length; i++){ var key = props[i]; me[key] = null; delete me[key]; } props = null; }, //************************************************************************** //** round //************************************************************************** /** Rounds decimal to the nearest 10ths place. */ round : function(number, decimalPlaces){ if (decimalPlaces){ var n = Math.pow(10, decimalPlaces); return Math.round( number * n ) / n; } else{ return Math.round(number); } } }; |