/* global ActiveXObject: false */ var util = (function() { var YE = YAHOO.util.Event; var YD = YAHOO.util.Dom; return { // validHtmlElementAttributes & validImgElementAttributes are uses in createE() to distinguish // between html element and html style attributes validHtmlElementAttributes: { cellSpacing:true, colSpan:true, cols:true, className:true, href:true, htmlFor:true, id:true, rows:true, target:true, title:true, type:true, value:true }, validImgElementAttributes: { id:true, className:true, src:true, width:true, height:true, title:true, alt:true }, // used by langVar() checkedForIsLanguageModule: false, isLanguageModule: false, // lang contains langauage variables when in developer mode lang: {}, // List of XMLHttpRequest-creation factory functions to try HTTP_factories: [ function() { return new XMLHttpRequest(); }, function() { return new ActiveXObject('Msxml2.XMLHTTP'); }, function() { return new ActiveXObject('Microsoft.XMLHTTP'); } ], // When we find a factory that works store it here HTTP_factory: null, uniqueElementIdCount: 0, // used with getUniqueElementId getUniqueElementId: function() { var i = util.uniqueElementIdCount + 1; while (document.getElementById('ueid_' + i)) { i++; } // set global ueid count to new i util.uniqueElementIdCount = i; return 'ueid_' + i; }, userAgent: { isIE: false, isIE6: false, name: '', init: function() { // returns the user agent brand var userAgentString = navigator.userAgent.toLowerCase(); var userAgentAppName = navigator.appName.toLowerCase(); var brand; // Note, Interent Explorer may contain multiple versions (8.0 and 6.0!) as this one: // -mozilla/4.0 (compatible; msie 8.0; windows nt 5.2; wow64; trident/4.0; mozilla/4.0 (compatible; msie 6.0; windows nt 5.1; sv1) ; .net clr 2.0.50727; .net clr 3.0.04506.30; .net clr 3.0.4506.2152; .net clr3.5.30729) // Consider this when checking for isIE6! if (userAgentString.indexOf('safari') !== -1) { util.userAgent.name = 'safari'; } else if (userAgentString.indexOf('opera') !== -1) { util.userAgent.name = 'opera'; } else if (userAgentAppName === 'netscape') { util.userAgent.name = 'netscape'; } else if (userAgentAppName === 'microsoft internet explorer') { util.userAgent.name = 'msie'; util.userAgent.isIE = true; // Check if this is Internet Explorer Version 6 // (Regular Expression as defined in MSDN - Detecting Internet Explorer More Effectively) var re = new RegExp('msie ([0-9]{1,}[\u002e0-9]{0,})'); var ieVersion = -1; if (re.exec(userAgentString) !== null) { ieVersion = parseFloat(RegExp.$1); } // alert('ieVersion: ' + ieVersion); if (ieVersion >= 6.0 && ieVersion < 7.0) { util.userAgent.isIE6 = true; } } else { util.userAgent.name = 'unknown'; } // alert('util.userAgent.isIE: ' + util.userAgent.isIE + '\nutil.userAgent.isIE6: ' + util.userAgent.isIE6 + '\nutil.userAgent.name: ' + util.userAgent.name); } }, /* user interaction / session handler This pings the server upon user interaction in defined intervals so that a session timeout is reported early and not too late when the user is going to save any changes. */ userInteractionTimer: 120000, // time in ms, set to 2 minutes initSession: function() { // A new session starts, a page just loaded. // console.log('initSession()'); // Start listening for user interaction events later setTimeout('util.startUserInteractionListener()', util.userInteractionTimer); }, startUserInteractionListener: function() { // console.log('startUserInteractionListener() - just started'); YE.addListener(document, 'click', util.setSessionActive); YE.addListener(document, 'keydown', util.setSessionActive); }, setSessionActive: function() { // console.log('setSessionActive()'); // Some user interaction is active, ping the server // and start listening to user interaction again later // Remove the listener, we check for events again later YE.removeListener(document, 'click', util.setSessionActive); YE.removeListener(document, 'keydown', util.setSessionActive); // Ping the server so that the server knows that the user is active var url = '?dp=util.ping_session_active'; util.serverPost(url); // Start listening to user interactions again later setTimeout('util.startUserInteractionListener()', util.userInteractionTimer); }, pingSessionActiveResponse: function() { // Set lastServerCommTime // console.log('pingSessionActiveResponse()'); }, /* general utilities */ trim: function(theString) { // removes leading and trailing white space theString = theString.replace(/^\s+/, ''); theString = theString.replace(/\s+$/, ''); return theString; }, isBoolean: function(a) { return typeof a === 'boolean'; }, isObject: function(a) { return (a && typeof a === 'object') || util.isFunction(a); }, isFunction: function(a) { return typeof a === 'function'; }, isArray: function(a) { return util.isObject(a) && a.constructor === Array; }, isUndefined: function(a) { return typeof a === 'undefined'; }, isInteger: function(a, /* optional */ min, /* optional */ max) { var pattern = /^[-]?\d+$/; if (a !== '' && pattern.test(a)) { var minIsValid = true; var maxIsValid = true; if (!util.isUndefined(min)) { if (parseInt(a, 10) < parseInt(min, 10)) { minIsValid = false; } } if (!util.isUndefined(max)) { if (parseInt(a, 10) > parseInt(max, 10)) { maxIsValid = false; } } if (minIsValid && maxIsValid) { return true; } } return false; }, isFloat: function(a, min, max) { var pattern = /^[-]?\d*\.?\d*$/; if (a !== '' && pattern.test(a)) { var minIsValid = true; var maxIsValid = true; if (!util.isUndefined(min)) { if (parseFloat(a) < parseFloat(min)) { minIsValid = false; } } if (!util.isUndefined(max)) { if (parseFloat(a) > parseFloat(max)) { maxIsValid = false; } } if (minIsValid && maxIsValid) { return true; } } return false; }, isRegularExpression: function(s) { if (s !== '') { try { var obj = new RegExp(s); return true; } catch(e) { return false; } } return false; }, isEmailAddress: function(s) { // Returns true if s is a valid email address in the format: // 'username@hostname' || '' || 'display name ' // pattern1 matches: 'display name ' || '' // pattern2 matches: 'username@hostname' var pattern1 = /^.*<\w[-.&\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]{2,}>$/; var pattern2 = /^\w[-.&\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]{2,}$/; // alert('s: ' + s + '\nmatched pattern1: ' + s.match(pattern1) + '\nmatched pattern2: ' + s.match(pattern2)); var isValid = (pattern1.test(s) || pattern2.test(s)); return isValid; }, getE: function(elementId) { // get element reference return document.getElementById(elementId); }, focusE: function(elementId) { var element = util.getE(elementId); if (element) { // IE Hack, IE may show an error that it can't focus even if the // element is displayed, use setTimeout() setTimeout(function() {element.focus()}, 0); // element.focus(); } else { alert('focusE(), element with id "' + elementId + '" \ndoes not exist.'); } }, enableE: function(elementList, /* optional */ enableElement) { if (typeof enableElement === 'undefined') { enableElement = true; } util.enableDisableElement(elementList, !enableElement); }, disableE: function(elementList, /* optional */ disableElement) { if (typeof disableElement === 'undefined') { disableElement = true; } util.enableDisableElement(elementList, disableElement); }, enableDisableElement: function(elementList, isDisabled) { var a = []; if (!util.isArray(elementList)) { a[0] = elementList; } else { a = elementList; } for (var i = 0; i < a.length; i++) { var element = util.getE(a[i]); if (element) { element.disabled = isDisabled; } else { alert('enableDisableElement(), element with id "' + a[i] + '" \ndoes not exist.'); } } }, showEV: function(elementList, /* optional */ showElement) { // show Elements visibility if (typeof showElement === 'undefined') { showElement = true; } util.showHideElementVisibility(elementList, showElement); }, hideEV: function(elementList, /* optional */ hideElement) { // hide Elements visibility if (typeof hideElement === 'undefined') { hideElement = true; } util.showHideElementVisibility(elementList, !hideElement); }, showHideElementVisibility: function(elementList, displayElement) { var a = []; if (!util.isArray(elementList)) { a[0] = elementList; } else { a = elementList; } // alert('showHideElementVisibility displayElement: ' + displayElement); for (var i = 0; i < a.length; i++) { var element = util.getE(a[i]); if (element) { var visibility = displayElement ? 'visible' : 'hidden'; element.style.visibility = visibility; } else { alert('showHideElementVisibility(), element with id "' + a[i] + '" \ndoes not exist.'); } } }, showE: function(elementList, /* optional */ showElement) { // Use only for display, not for visibility if (typeof showElement === 'undefined') { showElement = true; } util.showHideElement(elementList, showElement); }, hideE: function(elementList, /* optional */ hideElement) { // Use only for display, not for visibility if (typeof hideElement === 'undefined') { hideElement = true; } util.showHideElement(elementList, !hideElement); }, showHideElement: function(elementList, displayElement) { var a = []; if (!util.isArray(elementList)) { a[0] = elementList; } else { a = elementList; } // alert('elementList 2: ' + elementList); for (var i = 0; i < a.length; i++) { var element = util.getE(a[i]); if (element) { var elementType = element.nodeName; var displayType; if (displayElement) { if (elementType === 'TD' || elementType === 'TR' || elementType === 'TBODY' || elementType === 'LI' || elementType === 'A') { displayType = ''; } else { displayType = 'block'; } } else { displayType = 'none'; } if (element.style.display !== displayType) { element.style.display = displayType; } } else { alert('showHideElement(), element with id "' + a[i] + '" \ndoes not exist.'); } } }, setF: function(elementOrElementId, theValue) { // set Form Value var element = (util.isObject(elementOrElementId)) ? elementOrElementId : util.getE(elementOrElementId); if (element) { var elementType = element.nodeName; // alert(elementType); switch (elementType) { case 'INPUT' : var typeAttr = element.type; if (typeAttr === 'text' || typeAttr === 'hidden') { element.value = theValue; } else if (typeAttr === 'checkbox' || typeAttr === 'radio') { element.checked = theValue; } else if (typeAttr === 'password') { // A password field can only be set when dynamically created // and by setting its value before appending it to the document. // Hence we create a new password field, set its value and replace // it with the existing one. var elementWidth = element.style.width; var containerElement = element.parentNode; var elementId = element.id; // delete existing password element containerElement.removeChild(element); // create new password element var newPasswordElement = document.createElement('input'); newPasswordElement.type = 'password'; newPasswordElement.id = elementId; newPasswordElement.value = theValue; newPasswordElement.style.width = elementWidth; containerElement.appendChild(newPasswordElement); } break; case 'SELECT' : var options = element.options; for (var i = 0, len = options.length; i < len; i++) { // alert(options[i].value); if (options[i].value === theValue) { options[i].selected = true; break; } } break; case 'TEXTAREA' : element.value = theValue; break; } } else { alert('setFormValue(), element with id "' + elementId + '" \ndoes not exist.'); } }, getF: function(elementId, /* optional */ trimFormValue) { // get Form Value var element = document.getElementById(elementId); var theValue; if (element) { var elementType = element.nodeName; // Set default trimFormValue if undefined if (typeof trimFormValue === 'undefined') { trimFormValue = true; } switch (elementType) { case 'INPUT' : var typeAttr = element.type; if (typeAttr === "text" || typeAttr === 'hidden' || typeAttr === 'password') { theValue = trimFormValue ? util.trim(element.value) : element.value; } else { theValue = element.checked; } break; case 'SELECT' : var i = element.selectedIndex; theValue = (i !== -1) ? element.options[i].value : ''; break; case 'TEXTAREA' : theValue = trimFormValue ? util.trim(element.value) : element.value; // Clean multi line values from carriage return \r characters // which are added in IE so that we only have the line feed \n // instead of \r\n. Otherwise the value is interpreted as isModified // although nothing has been modified. var pattern = /\u000D/g; // Carriage return \r if (pattern.test(theValue)) { // Reomve all carriage returns theValue = theValue.replace(pattern, ''); } break; } return theValue; } else { alert('getF(), element with id "' + elementId + '" \ndoes not exist.'); } }, resetF: function(elementList) { // Resets a form element, argument is a single form element Id or an array with form element Id's var a = []; if (!util.isArray(elementList)) { a[0] = elementList; } else { a = elementList; } for (var i = 0; i < a.length; i++) { var element = util.getE(a[i]); if (element) { element.reset(); } else { alert('resetF(), element with id "' + a[i] + '" \ndoes not exist.'); } } }, populateSelect: function(elementOrElementId, theList, valueKey, textKey, defaultSelectedValueArg /*optional*/) { // Populates a select element. theList is an array with objects var element = (util.isObject(elementOrElementId)) ? elementOrElementId : util.getE(elementOrElementId); var defaultSelectedValue = (defaultSelectedValueArg !== null) ? defaultSelectedValueArg : ''; if (element !== null) { // util.showObject(theList); element.options.length = 0; for (var i = 0, l = theList.length; i < l; i++) { var theValue = theList[i][valueKey]; var makeSelected = (theValue === defaultSelectedValue); // util.showObject({theValue:theValue, defaultSelectedValue:defaultSelectedValue}); element.options[i] = new Option(theList[i][textKey], theValue, makeSelected, makeSelected); } } else { alert('populateSelect(), element with id "' + elementId + '" \ndoes not exist.'); } }, extendSelect: function(elementOrElementId, theList, valueKey, textKey, defaultSelectedValueArg /*optional*/) { // This adds aditional options to a select element which is already populated var element = (util.isObject(elementOrElementId)) ? elementOrElementId : util.getE(elementOrElementId); var defaultSelectedValue = (defaultSelectedValueArg !== null) ? defaultSelectedValueArg : ''; if (element) { var j = element.options.length; for (var i = 0, l = theList.length; i < l; i++, j++) { // util.showObject({f:'extendSelect', i:i, j:j}); var theValue = theList[i][valueKey]; var makeSelected = (theValue === defaultSelectedValue); element.options[j] = new Option(theList[i][textKey],theValue, makeSelected, makeSelected); } } else { alert('extendPopulatedSelect(), element with id "' + elementId + '" \ndoes not exist.'); } }, getSelectOptionText: function(elementId) { // returns the text of the selected option in a select element var text = ''; var element = util.getE(elementId); if (element && (element.selectedIndex >= 0)) { text = element.options[element.selectedIndex].text; } return text; }, getEncodedURIComponent: function(theValue) { // returns an encoded URI component value if theValue contains special characters var pattern = /\W/; // The pattern /\W/ is equal [^a-zA-Z0-9_] if (pattern.test(theValue)) { theValue = encodeURIComponent(theValue); } return theValue; }, getRepetitionSequenceLetter: function(theSequence, theIndex) { // theSequence is an array, i.e. the latin alphabet ['A', 'B', 'C', ...] // theIndex is an integer which refers a letter in theSequence. // We return theSequence value. // If theIndex is equal or greater the length of theSequence then we extend theSequence // by adding duplicates of the initial sequence, so the sequence becomes: // ['A', 'B', 'C', ..., 'Z', 'AA', 'BB', 'CC', ..., 'ZZ', 'AAA', 'BBB', 'CCC', ... 'ZZZ', 'AAAA', ...] var numberOfSequenceItems = theSequence.length; if (theIndex < numberOfSequenceItems) { return theSequence[theIndex]; } else { // Return a repetition of a single letter var repetitionFactor = Math.floor(theIndex / numberOfSequenceItems) + 1; var theIndexWhichFits = theIndex % numberOfSequenceItems; var theLetter = theSequence[theIndexWhichFits]; var theLetterRepetition = ''; for (var i = 0; i < repetitionFactor; i++) { theLetterRepetition += theLetter; } return theLetterRepetition } }, createHash: function(theArray, theKey) { var hasKey = (typeof theKey !== 'undefined'); var s = ''; for (var i = 0, len = theArray.length; i < len; i++) { if (hasKey) { s = '__h__' + theArray[i][theKey]; theArray[s] = theArray[i]; } else { s = '__h__' + theArray[i]; theArray[s] = theArray[i]; } } }, h: function(name) { // converts a hash name to the above hash format return '__h__' + name; }, /* createNewKeyValue: function(the_array, the_key) { // creates and returns a unique node name // create lookup var a = []; for (var i = 0; i < the_array.length; i++) { var theValue = the_array[i][the_key]; a[theValue] = true; } // create new unique key value var isUnique = false; var count = 0; while (!isUnique) { count++; var newKeyValue = "new" + count; if (!a[newKeyValue]) { isUnique = true; } } return newKeyValue; }, */ getArrayObject: function(theArray, theKey, theValue) { // returns an object reference from theArray where theKey has the value theValue var obj = {}; for (var i = 0; i < theArray.length; i++) { if (theArray[i][theKey] === theValue) { obj = theArray[i]; break; } } return obj; }, getArrayObjectIndex: function(theArray, theKey, theValue) { // returns the index of the specified object for (var i = 0; i < theArray.length; i++) { if (theArray[i][theKey] === theValue) { return i; } } }, getNextArrayObject: function(theArray, theKey, theValue) { // returns the next object of the given object in the array. If there is no next // object it will return the previous object. If there is no next or // previous object it will return null. var nextObject = null; var numberOfObjects = theArray.length; if (numberOfObjects > 1) { // get position of given object for (var i = 0; i < numberOfObjects; i++) { if (theArray[i][theKey] === theValue) { break; } } var nextIndex; if (i < (numberOfObjects - 1)) { nextIndex = i + 1; } else { nextIndex = i - 1; } nextObject = theArray[nextIndex]; } return nextObject; }, deleteArrayObject: function(theArray, theKey, theValue) { // Delete the object from theArray where theKey has the value theValue. // Ignore deletion if the object does not exist // get index of object to delete var objExists = false; for (var i = 0; i < theArray.length; i++) { if (theArray[i][theKey] === theValue) { objExists = true; break; } } // alert('index to delete: ' + i); if (objExists) { theArray.splice(i, 1); } }, cloneObject: function(oriValue) { // returns a true copy of an array or object if (util.isArray(oriValue)) { // alert('isArray'); var newValue = []; for (var i = 0; i < oriValue.length; i++) { newValue[i] = util.cloneObject(oriValue[i]); } } else if (util.isObject(oriValue)) { // alert('isObject'); var newValue = {}; for (var prop in oriValue) { newValue[prop] = util.cloneObject(oriValue[prop]); } } else { // no oject or array, return oriValue // alert('return oriValue'); var newValue = oriValue; } // util.showObject(newValue); return newValue; }, removeChildElements: function(s /* s is an elementID or an element*/) { var element = util.isObject(s) ? s : util.getE(s); while (element.lastChild) { var childElement = element.lastChild; element.removeChild(childElement); } }, createE: function(elementType, attributes) { // Creates an element. attributes and labelText are optional arguments. // Note, attributes may contain html attributes and style attributes, // we check for differences here // I.e.: // util.createE('div'); // util.createE('input', {id:id, type:'checkbox'}); // util.createE('input', {id:id, type:'checkbox'}, {paddingLeft:'14px', margin:'5px'}); var element = document.createElement(elementType); if (attributes !== null) { var validAttributes = (elementType !== 'img') ? util.validHtmlElementAttributes : util.validImgElementAttributes; for (var prop in attributes) { if (validAttributes[prop]) { // Apply element attribute element[prop] = attributes[prop]; } else { // Apply element style attribute element.style[prop] = attributes[prop]; } } } return element; }, createT: function(s) { // Creates a new text node if (s === ' ') { s = '\u00a0'; } return document.createTextNode(s); }, updateT: function(elementId, text) { // Replaces any existing text of the element or creates a new text node if it does not yet exist var element = document.getElementById(elementId); if (element) { // alert('updateT() - element with text: ' + text); if (text === 0) { // alert('the text: ' + text + '\nis interpreted as the number 0'); text = '0'; } else if (text === ' ') { // alert('the text: ' + text + '\nis interpreted as space'); text = '\u00a0'; //   } var newText = document.createTextNode(text); if (element.firstChild) { // replace existing text var oldText = element.firstChild; element.replaceChild(newText, oldText); } else { // append new text element.appendChild(newText); } } else { alert('updateT() - element with elementId "' + elementId + '" does not exist.'); } }, chainE: function(/* html elements */) { // accepts any number of arguments // Chain elements appends the given html elements in two different ways // a.) Cascading (html elements are not given in an array) // Each previous element is the parent element, i.e.: // util.chainE(div, p, span, text); // span is the parent of text, p is the parent of span, div is the parent of p // b.) Tree (html elements are given in an array) // The first element of the array is the parent element, all following // elements in the array are appended to the 1st array element, i.e.: // util.chainE([div, p1, p2, p3, p4]); // All p elements (1-4) are appended to the 1st div element // Cascading and Tree can be combined, i.e.: // util.chainE(table, [tbody, [tr1, td1, text1], [tr2, td2, text2]]); // Arbitrary nesting of tree like arrays is allowed. var numberOfArguments = arguments.length; if (numberOfArguments > 1) { for (var i = numberOfArguments - 1; i > 0; i--) { var parentElement = arguments[i - 1]; var childElement = arguments[i]; if (util.isArray(parentElement)) { parentElement = util._chainElementsTreeLike(parentElement); } if (util.isArray(childElement)) { childElement = util._chainElementsTreeLike(childElement); } // alert('chainE()' + '\nparentElement: ' + parentElement + '\nchildElement: ' + childElement); parentElement.appendChild(childElement); } } else { // There is only one argument, this must be an array to which we apply _chainElementsTreeLike() var element = util._chainElementsTreeLike(arguments[0]); // The var element is not required in this case, its just a placeholder for the returned element } // alert('chainE() completed' ); }, _chainElementsTreeLike: function(elements) { // See chainE() for details // alert('_chainElementsTreeLike(): ' + elements); var parentElement = elements[0]; if (util.isArray(parentElement)) { parentElement = util._chainElementsTreeLike(parentElement); } for (var i = 1; i < elements.length; i++) { var childElement = elements[i]; if (util.isArray(childElement)) { childElement = util._chainElementsTreeLike(childElement); } parentElement.appendChild(childElement); } // alert('We return parentElement: ' + parentElement); return parentElement; }, setConfigItemListHeight: function() { var config_item_list_body = document.getElementById('config_item_list_body'); // alert('setConfigItemListHeight(): ' + config_item_list_body); var pos = YD.getXY('config_item_list_body'); var configItemListY = pos[1]; var pageY = YD.getClientHeight(); var configItemListHeight = pageY - (configItemListY + 40); config_item_list_body.style.height = configItemListHeight + 'px'; }, // // Encoding // /* Disabled - It looks like that the backslashes escaping problem only exists for File Manager, respectively the problem only exists when using GET, so when a pathname, i.e. C:\_logs\2007\, is part of the URL encodeDat: function(s) { // Encodes a string send from the client to the server via GET or POST // Note that we escape backslashes because Salang thinks we are escaping // something. s = s.replace(/\\/g, '\\'); s = encodeURIComponent(s); return s; }, */ // // // // XMLHttpRequest - server background calls // // // newXMLHttpRequest: function() { // Create new XMLHttpRequest object // If HTTP_factory is already known then use that one if (util.HTTP_factory !== null) return util.HTTP_factory(); for (var i = 0; i < util.HTTP_factories.length; i++) { try { var factory = util.HTTP_factories[i]; var request = factory(); if (request !== null) { util.HTTP_factory = factory; return request; } } catch(e) { continue; } } // If we get here then no factory candidate succeeded, // throw an exception now and for all future calls. util.HTTP_factory = function() { throw new Error("XMLHttpRequest not supported"); } util.HTTP_factory(); // Throw an error }, serverPost: function(url, dat) { // dat is optional // add volatile node for error handling if (dat) { dat += '&volatile.is_server_background_call=true'; } else { var dat = 'volatile.is_server_background_call=true'; } var request = util.newXMLHttpRequest(); // alert('request: ' + request); request.onreadystatechange = function() { if (request.readyState === 4) { // If the request is finished if (request.status === 200) { // If it was successful // alert(request.responseText.length); // If there is a response text if (request.responseText.length > 3) { eval('(' + request.responseText + ')'); } /* DISABLED try and catch because it does not allow detailed debugging with Firebug try { eval('(' + request.responseText + ')'); } catch (ex) { alertMsg = 'Inavlid response from server.\n\nServer response text:\n\n'; alertMsg += request.responseText; alertMsg += '\n\n JavaScript error message:\n\n' + ex; alert(alertMsg); } */ } } } request.open('POST', url, true); request.send(dat); }, authenticationFailureInServerBackgroundCall: function(dat) { // if (dat.isSessionTimedOut) { // // // Add volatile.session_timed_out=true to URL // // before authentication.cfv is called the second time // location.href = location.href + '&volatile.session_timed_out=true'; // } // else { // // // Unknown authentication failure // // alert('authenticationFailureInServerBackgroundCall'); // alert(dat.errorMessage); // // reload the current page so that we get the login form // location.reload(); // } // KHP 08/Dec/2012 - ToDo - revise session time out handling // We suppose this is always a session time out, even if // dat.isSessionTimedOut is false location.href = location.href + '&volatile.session_timed_out=true'; }, labelToNodeName: function(theLabel) { // returns a valid node name of label or empty '' if the label contains no single alphanumerical character var label = theLabel.toLowerCase(); var nodeName = ''; var pattern = /[a-z0-9]/; if (pattern.test(label)) { // alert(label + ' Matched!'); pattern = /[_a-z0-9]/; for (var i = 0; i < label.length; i++) { var s = label.charAt(i); var sUnicode = s.charCodeAt(0); // alert(s);\ if (!pattern.test(s)) { if (sUnicode < 128) { s = '_'; } else { // covert to hex s = sUnicode.toString(16); } } nodeName += s; } } return nodeName; }, labelToUniqueNodeName: function(label, existingNodeNames, nodeNamePrefix) { // Returns a valid and unique node name. // The nodeNamePrefix is used as name in case that the label does not contain any alphanumerical English characters. var i = 0; var len = existingNodeNames.length; var s = ''; var nodeNameLookup = {}; // Create nodeNameLookup // nodeNameLookup is an object in the format // o._name1 = true // o._name2 = true // the starting underscore "_" is not part of the node name but added to avoid any name conflicts for (i = 0; i < len; i++) { nodeNameLookup['_' + existingNodeNames[i]] = true; } var newNodeName = util.labelToNodeName(label); if (newNodeName !== '') { i = 1; s = ''; } else { // The label does not contain any alphanumerical characters. // Give it the node name prefix newNodeName = nodeNamePrefix; i = 1; s = '_' + i; } while (nodeNameLookup['_' + newNodeName + s]) { i++; s = '_' + i; } newNodeName = newNodeName + s; return newNodeName; }, arrayToString: function(a) { var s = ""; for (var i = 0; i 0) { // We apply a padding so that the table width can flow upon text sizing! cellElement.style.paddingLeft = deltaWidth + 'px'; } }, // // Date // salangDateToSimpleDateObject: function(salangDate) { // converts a salang date, i.e. 18/Jan/2006 to a javascript object in the format // o.year = 2006 // o.month = 0 // o.day = 18 var salangJsMonths = {jan:0, feb:1, mar:2, apr:3, may:4, jun:5, jul:6, aug:7, sep:8, oct:9 ,nov:10, dec:11}; var dat = salangDate.split('/'); // util.showObject({"salangDateToSimpleDateObject() - salangDate argument": salangDate}); // util.showObject({"salangDateToSimpleDateObject() - dat": dat}); var obj = {}; obj.year = parseInt(dat[2], 10); obj.month = salangJsMonths[dat[1].toLowerCase()]; obj.day = parseInt(dat[0], 10); // make sure the radix of base 10 is defined so that i.e. "08" isn't converted to "0" which could occur in ECMAScript v3 // util.showObject({"salangDateToSimpleDateObject() - obj": obj}); return obj; }, // // // Round box (i.e. panel-50) // // // getRoundBox: function(elementId, classNumber, contentElement) { // Creates a div with round corners (multiple div approach) // panelNumber is the number of the CSS class name, i.e. "50" for panel-50. // contentElement is the element which is inserted into the round box body section. // var div = util.createE('div', {id:elementId, className:'panel-' + classNumber, display:'none'}); // var headerDiv = util.createE('div', {className:'panel-' + classNumber + '-header'}); // var headerDivTop = util.createE('div', {className:'panel-' + classNumber + '-header-top'}); // var headerDivTopText = util.createT(' '); // var headerDivBottom = util.createE('div', {className:'panel-' + classNumber + '-header-bottom'}); // var headerDivBottomText = util.createT(' '); // var bodyDiv = util.createE('div', {className:'panel-' + classNumber + '-body'}); // var footerDiv = util.createE('div', {className:'panel-' + classNumber + '-footer'}); // var footerOffsetDiv = util.createE('div', {className:'panel-' + classNumber + '-footer-offset'}); // var footerOffsetText = util.createT(' '); // // util.chainE(div, [headerDiv, [headerDivTop, headerDivTopText], [headerDivBottom, headerDivBottomText]]); // util.chainE(div, bodyDiv, contentElement); // util.chainE(div, footerDiv, footerOffsetDiv, footerOffsetText); // return div; // }, // // // File manager window // // fileManagerWindow: { theWindow: null, open: function(pathnameElementId) { // alert('util.fileManagerWindow.open()'); var url = '?dp=file_manager.file_manager_page'; url += '&peid=' + encodeURIComponent(pathnameElementId); var windowName = 'file_manager'; var width = 700; var height = 480; // check if a path is defined in the pathname field // if a path exists then start the file manager with the defined path var pathname = util.getF(pathnameElementId); // alert('pathname not encoded: ' + pathname); if (pathname !== '') { pathname = pathname.replace(/\\/g, '__HexEsc__5C'); url += '&pathname=' + encodeURIComponent(pathname); } var left = parseInt((screen.availWidth/2) - (width/2), 10); var top = parseInt((screen.availHeight/2) - (height/2), 10); util.fileManagerWindow.theWindow = window.open(url,windowName,'location=no,width=' + width + ',height=' + height + ',left=' + left + ',top=' + top + ',status=yes,scrollbars=yes,resizable=yes'); util.fileManagerWindow.theWindow.focus(); }, setPathnameValue: function(pathnameElementId, pathname) { // This function is initiated from file manager, // it sets the pathname element to the given pathname util.setF(pathnameElementId, pathname); } }, // initAdminDropDownMenu: function() { // // // Init Reports Config navigation bar // // // Profiles menu // if (util.getE('rc_nav:profiles_btn') !== null) { // util.dropDownMenu.add('rc_nav:profiles_btn', 'rc_nav:profiles_drop_down'); // } // // // Config menu // if (util.getE('rc_nav:config_btn') !== null) { // util.dropDownMenu.add('rc_nav:config_btn', 'rc_nav:config_drop_down'); // } // // // Tools menu // if (util.getE('rc_nav:tools_btn') !== null) { // util.dropDownMenu.add('rc_nav:tools_btn', 'rc_nav:tools_drop_down'); // } // // // Admin menu // if (util.getE('rc_nav:admin_btn') !== null) { // util.dropDownMenu.add('rc_nav:admin_btn', 'rc_nav:admin_drop_down'); // } // }, // // // Help window // // helpWindow: { theWindow: null, centralUrl: '?dp+docs.technical_manual.toc', contextUrl: '', // Set upon init, the link refers to a specific topic group, i.e. Log Filters or Reports init: function(contextUrl) { // alert('helpWindow.init()'); YE.addListener('central_help_btn', 'click', util.helpWindow.openCentralHelp); if (contextUrl && contextUrl !== '') { util.helpWindow.contextUrl = contextUrl; YE.addListener('context_help_btn', 'click', util.helpWindow.openContextHelp); } }, openCentralHelp: function(evt) { // Opens the help window via central help button YE.preventDefault(evt); util.helpWindow.open(util.helpWindow.centralUrl); }, openContextHelp: function(evt) { // Opens the help window via toolbar context help button YE.preventDefault(evt); util.helpWindow.open(util.helpWindow.contextUrl); }, openGeneralHelp: function(evt) { // Opens the help window from any link in the GUI. The URL must be specified // as regular anchor because we get the URL from this anchor. YE.preventDefault(evt); var element = evt.target || evt.srcElement; var url = element.href; util.helpWindow.open(url); }, open: function(url) { // var width = YD.getViewportWidth() - 120; // var height = YD.getViewportHeight() - 60; var width = 1024; var height = 700; var features = 'width=' + width + ',height=' + height + ',location=yes,menubar=yes,toolbar=yes,status=yes,scrollbars=yes,resizable=yes'; util.helpWindow.theWindow = window.open(url, 'help', features); util.helpWindow.theWindow.focus(); } }, // // // About // // about: { isDisplayed: false, toggleAboutSection: function() { var showAboutSection = !util.about.isDisplayed; util.showE('product_bar:about_section', showAboutSection); util.about.isDisplayed = showAboutSection; } }, // // // Error / Alert handling // // errorInServerBackgroundCall: { panel: null, init: function() { // // Create the error panel // var panelId = 'error_in_server_background_call:panel'; var bodyElements = document.getElementsByTagName('body'); var body = bodyElements[0]; var mainDiv = util.createE('div', {id:panelId, className:'panel-50'}); util.chainE(body, mainDiv); // We create the alert panel via innerHTML because it doesn't correctly render // when creating it via DOM elements in Firefox var htmlString = '
'; htmlString += '
'; htmlString += '

' + langVar('lang_stats.error_handling.error_while_processing_last_request') + '

'; htmlString += ''; htmlString += langVar('lang_stats.error_handling.click_here_to_view_alert_msg'); htmlString += ''; htmlString += '
'; // panel-50-form htmlString += ''; htmlString += '
'; // panel-50-body mainDiv.innerHTML = htmlString; // // Init the error panel object // var panelObj = { panelId: panelId, panelClassName: 'panel-50', panelHeaderLabel: langVar('lang_stats.error_handling.product_alert_info'), left: 60, top: 60, zIndex: 5000, isCover: true, isCloseButton: false }; util.errorInServerBackgroundCall.panel = new util.Panel3(panelObj); YE.addListener('error_in_server_background_call:close_alert_btn', 'click', util.errorInServerBackgroundCall.close); }, open: function(errorId) { if (!util.errorInServerBackgroundCall.panel) { util.errorInServerBackgroundCall.init(); } var viewAlertBtn = util.getE('error_in_server_background_call:view_alert_msg_btn'); viewAlertBtn.href = '?dp=alert&ei=' + errorId; util.errorInServerBackgroundCall.panel.open(); }, close: function() { util.errorInServerBackgroundCall.panel.close(); // If this is the New Profile Wizard window // then restore the new profile wizard page try { restoreNewProfileWizardPageAfterError(); } catch(msg) {} } }, // // // Trial mode utilities // // trialLicensingTier: { reminderPanel: null, init: function(showTrialReminder, days_left) { // Init the change trial licensing tier button var a = [ 'prompt_for_trial_tier:lite', 'prompt_for_trial_tier:pro', 'prompt_for_trial_tier:enterprise' ]; YE.addListener(a, 'click', util.trialLicensingTier.change); // util.trialLicensingTier.btn.enable(); // YE.addListener(document, 'unload', util.trialLicensingTier.exit); // Enable dropDownMenu util.dropDownMenu.add('change_licensing_tier:btn', 'prompt_for_trial_tier:drop_down'); if (showTrialReminder) { // This checks and sets a flag in "system" so that the reminder // isn't shown twice. var url = '?dp=util.check_show_trial_reminder'; var dat = 'v.fp.page_token=' + pageInfo.changeTrialLicensingTierToken; dat += '&v.fp.days_left=' + days_left; util.serverPost(url, dat); } }, change: function() { var elementId = this.id; // Check if we have any unsaved changes on the current page if (adminConfig.getIsExitPagePermission()) { var bodyElements = document.getElementsByTagName('body'); var bodyElement = bodyElements[0]; bodyElement.style.display = 'none'; // User clicked on a link to change the trial mode var elementDat = elementId.split(':'); var trialLicensingTier = elementDat[1]; // alert('change trial mode to: ' + trialLicensingTier); var url = '?dp=util.change_trial_licensing_tier'; var dat = 'v.fp.page_token=' + pageInfo.changeTrialLicensingTierToken; dat += '&v.fp.trial_licensing_tier=' + trialLicensingTier; util.serverPost(url, dat); } }, changeResponse: function() { location.reload(true); }, showTrialReminderResponse: function(showTrialReminder) { if (showTrialReminder) { var panelObj = { panelId: 'trial_reminder:panel', panelClassName: 'panel-30', panelHeaderLabel: langVar('lang_admin.trial.reminder'), zIndex: 20, closeEvent: util.trialLicensingTier.closeTrialReminder }; util.trialLicensingTier.reminderPanel = new util.Panel3(panelObj); YE.addListener('trial_reminder:close_btn', 'click', util.trialLicensingTier.closeTrialReminder); util.trialLicensingTier.reminderPanel.prePositionAtCenter(); util.trialLicensingTier.reminderPanel.open(); } }, closeTrialReminder: function() { util.trialLicensingTier.reminderPanel.close(); } }, resolveLangVar: function(langVarPath, jsLangVarPath) { var langVarValue = ''; if (util.lang[jsLangVarPath]) { langVarValue = util.lang[jsLangVarPath]; } else { var url = '?dp=util.resolve_lang_var'; url += '&pathname=' + encodeURIComponent(langVarPath); var request = util.newXMLHttpRequest(); // Note, this is a synchronous server call request.open('GET', url, false); request.send(null); if (request.status === 200) { // alert(request.responseText); langVarValue = request.responseText; // Set language variable in util.lang for reuse util.lang[jsLangVarPath] = langVarValue; // util.showObject(xmlhttp.responseText); } } return langVarValue; }, positionAndShowDropDownElement: function(btnElement, menuElement) { // This sets the position of a drop-down element relative // to the button and available space. var clientRegion = YD.getClientRegion(); var clientWidth = clientRegion.width; var clientHeight = clientRegion.height; // util.showObject(clientRegion); var btnRegion = YD.getRegion(btnElement); var btnTop = btnRegion.top var btnBottom = btnRegion.bottom; var btnLeft = btnRegion.left; var btnRight = btnRegion.right; // util.showObject(btnRegion); // Get region of drop down menu menuElement.style.visibility = 'hidden'; menuElement.style.top = 0; menuElement.style.left = 0; menuElement.style.display = 'block'; var menuRegion = YD.getRegion(menuElement); // util.showObject(menuRegion); var menuWidth = menuRegion.width; var menuHeight = menuRegion.height; // Get menu top and menu left var alignLeft = false; var alignBottom = false; // Check if we align menu left or right of button if ((btnLeft + menuWidth) <= clientWidth) { // Align left of button alignLeft = true; } else if (btnRight - menuWidth >= 0) { // Align right of button alignLeft = false; } else { // Align on the side where more space is left var spaceOnRight = clientWidth - btnLeft; var spaceOnLeft = btnRight; if (spaceOnRight >= spaceOnLeft) { // Align left of button alignLeft = true; } else { // Align right of button alignLeft = false; } } // Check if we align menu bottom or top of button var menuLeft = alignLeft ? btnLeft : btnRight - menuWidth; var menuTop = btnBottom; // console.log('menuTop: ' + menuTop); // console.log('menuLeft: ' + menuLeft); // Set final position menuElement.style.top = menuTop + 'px'; menuElement.style.left = menuLeft + 'px'; // Show the menu menuElement.style.visibility = 'visible'; }, // // // // MISCELLANEOUS // // // // // // showObject handling // // showObjectWindowId: '', // Used with showObject, keeps the showObjectWindowId createShowObjectWindow: function() { var bodyElements = document.getElementsByTagName('body'); var body = bodyElements[0]; var showObjectWindowId = util.getUniqueElementId(); var mainDivProperties = { id:showObjectWindowId, position:'absolute', top:0, right:0, borderStyle: 'solid', borderWidth: '1px', borderColor: 'Silver', backgroundColor: 'White', zIndex: 5000 }; var objectDivProperties = { id:showObjectWindowId + ':body', width:'800px', height:'700px', overflow: 'scroll' } var mainDiv = util.createE('div', mainDivProperties); var headerDiv = util.createE('div', {padding:'4px', backgroundColor:'#f5f5f5'}); var a = util.createE('a', {id:showObjectWindowId + ':close_btn', href:'javascript:;'}); var aText = util.createT('Close Object Window'); var objectDiv = util.createE('div', objectDivProperties); util.chainE(headerDiv, a, aText); util.chainE(body, [mainDiv, headerDiv, objectDiv]); YE.addListener(showObjectWindowId + ':close_btn', 'click', util.closeShowObjectWindow); util.showObjectWindowId = showObjectWindowId; }, closeShowObjectWindow: function() { var showObjectWindowId = util.showObjectWindowId; // Clean object viewer util.removeChildElements(showObjectWindowId + ':body'); util.hideE(showObjectWindowId); }, showObject: function(obj, comment) { // showObject outputs objects to a debug window // The comment argument is optional if (util.showObjectWindowId === '') { util.createShowObjectWindow(); } var showObjectWindowId = util.showObjectWindowId; // Create a new div which we append to the already existing object viewer var container = util.getE(showObjectWindowId + ':body'); var div = util.createE('div', {padding:'0 14px', borderBottom:'1px solid Silver', zIndex: 5000}); util.chainE(container, div); var text = ''; if (comment) { text += '' + comment + '
'; } var objAsString = JSON.stringify(obj, null, ' '); text += '
' + objAsString.replace(/\u000A/g, '
') + '
'; div.innerHTML = text; util.showE(showObjectWindowId); } } }()); /* CommandLink (used for anchor buttons) */ // util.CommandLink = function(elementId, buttonEvent, isDisabled) { util.CommandLink = function(elementId, buttonEvent, defaultEnabled, options, contextObj /* optional */) { // This initializes a command link // options are // options.classNameEnabled // options.classNameDisabled var element = util.getE(elementId); this.element = element; this.buttonEvent = buttonEvent; this.isEnabled = defaultEnabled; this.classNameEnabled = options.classNameEnabled; this.classNameDisabled = options.classNameDisabled; this.contextObj = contextObj; // Set default state if the command link actually exists if (element !== null) { if (defaultEnabled) { element.className = this.classNameEnabled; if (contextObj == null) { YAHOO.util.Event.addListener(element, 'click', buttonEvent); } else { YAHOO.util.Event.addListener(element, 'click', buttonEvent, contextObj); } } else { element.className = this.classNameDisabled; } } } util.CommandLink.prototype.enable = function(enableElement) { // If command link exists if (this.element !== null) { // The makeEnabled argument is optional var enableElement = enableElement !== null ? enableElement : true; var makeEnabled = typeof enableElement !== 'undefined' ? enableElement : true; // Only enable the button if it is not yet enabled if (makeEnabled) { if (!this.isEnabled) { var element = this.element; if (this.contextObj == null) { YAHOO.util.Event.addListener(element, 'click', this.buttonEvent); } else { YAHOO.util.Event.addListener(element, 'click', this.buttonEvent, this.contextObj); } // YAHOO.util.Event.addListener(element, 'click', this.buttonEvent); element.className = this.classNameEnabled; this.isEnabled = true; } } else { this.disable(); } } } util.CommandLink.prototype.disable = function() { // Don't disable the button if it is already disabled if (this.element !== null && this.isEnabled) { var element = this.element; YAHOO.util.Event.removeListener(element, 'click', this.buttonEvent); element.className = this.classNameDisabled; this.isEnabled = false; } } /** * * * * ToolbarButton class (could eventually replace the CommandLink class, so that we only use one class!) * * Creates an object for a toolbar button composed of an anchor with an image. * The ToolbarButton object considers rbac state by defining a "ignore" method. * I.e.:, saveBtn.ignore() will hide the button and ignore it any other method * which is applied so that hoverOn(), disable() or enable() does not have any effect. * This allows us to code buttons as in non-rbac mode and simply ignore them in case * that there is no permission to use the saveBtn or any other RBAC feature. * * Arguments: * buttonItemName: This is not the element ID but a simple button item name which acts as a referece in buttonsDb and from which we compose the elementId * buttonEvent: The event which is fired upon onclick * buttonsDb: Includes general button properties and all toolbar buttons, it has following format: * buttonsDb = { * classNameEnabled: 'btn-10', * classNameDisabled: 'btn-10-disabled', * classNameHover: 'btn-10-hover', * enabled: {"_save_changes:"new Image(), "_new_role":new Image()}, * disabled: {"_save_changes:"new Image(), "_new_role":new Image()}, * } * buttonsDb.enabled._save_changes.src = "/picts/toolbars/save_changes.gif", * buttonsDb.enabled._new_role.src = "/picts/toolbars/new_role.gif", * buttonsDb.disabled._save_changes.src = "/picts/toolbars/save_changes_dis.gif", * buttonsDb.disabled._new_role.src = "/picts/toolbars/new_role_dis.gif" * * * // Note, all button item Id's start internally with an underbar to avoid any name conflicts * // The elementId is a composistion of "toolbar:buttonItemID" * * * * */ util.ToolbarButton = function(buttonName, buttonEvent, buttonsDb) { // By default we set all buttons to the disabled state, that's how // the html code is specified. // ignore=true will ignore this button upon all applied methods. // We also set buttonName to true if the button does not exist due // RBAC or licensing features. So we must always check for button // existence! var buttonId = '_' + buttonName; var elementId = 'toolbar:' + buttonName; var btn = util.getE(elementId); this.elementId = elementId; this.buttonEvent = buttonEvent; this.isDisabled = true; this.ignore = (btn !== null) ? false : true; this.classNameEnabled = buttonsDb.classNameEnabled; this.classNameDisabled = buttonsDb.classNameDisabled; this.classNameHover = buttonsDb.classNameHover; // Images are optional this.srcEnabled = buttonsDb.enabled[buttonId]['src']; this.srcDisabled = buttonsDb.disabled[buttonId]['src']; } util.ToolbarButton.prototype.enable = function(/* optional */makeEnabled) { if (!this.ignore) { if (typeof makeEnabled === 'undefined') { makeEnabled = true; } // Only enable the button if it is not yet enabled if (makeEnabled) { if (this.isDisabled) { var btn = util.getE(this.elementId); YAHOO.util.Event.addListener(btn, 'click', this.buttonEvent); btn.className = this.classNameEnabled; var img = btn.firstChild; img.src = this.srcEnabled; this.isDisabled = false; } } else { this.disable(); } } } util.ToolbarButton.prototype.disable = function() { // Don't disable the button if it is already disabled if (!this.ignore && !this.isDisabled) { // alert('disable button'); var btn = util.getE(this.elementId); YAHOO.util.Event.removeListener(btn, 'click', this.buttonEvent); btn.className = this.classNameDisabled; var img = btn.firstChild; img.src = this.srcDisabled; this.isDisabled = true; } } util.ToolbarButton.prototype.disableAndIgnore = function() { // This sets a button to disabled and ignored state if (!this.ignore) { // if not yet disavled if (!this.isDisabled) { this.disable(); } this.ignore = true; } } util.ToolbarButton.prototype.hoverOn = function() { if (!this.ignore) { // TODO } } util.ToolbarButton.prototype.hoverOff = function() { if (!this.ignore) { // TODO } } /* Tabs2 class */ util.Tabs2 = function(tabElementIds, tabEvent) { this.tabElementIds = tabElementIds; this.tabEvent = tabEvent; this.selectedTabElementId = null; // init the tabs for (var i = 0; i < tabElementIds.length; i++) { // alert('init the tabs: ' + tabElementIds[i]); YAHOO.util.Event.addListener(tabElementIds[i], 'click', tabEvent); YAHOO.util.Event.addListener(tabElementIds[i], 'mouseover', this.hoverOn); YAHOO.util.Event.addListener(tabElementIds[i], 'mouseout', this.hoverOff); } } util.Tabs2.prototype.setActiveTab = function(tabElementId) { // alert('util.Tabs2.prototype.setActiveTab: ' + tabElementId); var li; var a; var selectedTabElementId = this.selectedTabElementId; // If the tab isn't already selected if (selectedTabElementId !== tabElementId) { // Reset selected tab if (selectedTabElementId !== null) { // alert('Tabs2 class - Reset selected tab'); li = util.getE(selectedTabElementId); a = li.firstChild; li.className = ''; a.className = ''; YAHOO.util.Event.addListener(selectedTabElementId, 'click', this.tabEvent); YAHOO.util.Event.addListener(selectedTabElementId, 'mouseover', this.hoverOn); YAHOO.util.Event.addListener(selectedTabElementId, 'mouseout', this.hoverOff); } // Select tab of given tabElementId // alert('Tabs2 class - Select tab of given tabElementId: ' + tabElementId); li = util.getE(tabElementId); a = li.firstChild; li.className = 'active'; a.className = 'active'; YAHOO.util.Event.removeListener(tabElementId, 'click', this.tabEvent); YAHOO.util.Event.removeListener(tabElementId, 'mouseover', this.hoverOn); YAHOO.util.Event.removeListener(tabElementId, 'mouseout', this.hoverOff); // remove focus a.blur(); this.selectedTabElementId = tabElementId; } // util.showObject(this); // alert('util.Tabs2.prototype.setActiveTab - this.selectedTabElementId: ' + this.selectedTabElementId); } util.Tabs2.prototype.hide = function(tabElementId) { // hide the tab or tabs util.hideE(tabElementId); } util.Tabs2.prototype.show = function(tabElementId) { // show the tab or tabs util.showE(tabElementId); } util.Tabs2.prototype.hoverOn = function() { var li = this; var a = li.firstChild; li.className = 'hover'; a.className = 'hover'; } util.Tabs2.prototype.hoverOff = function() { var li = this; var a = li.firstChild; li.className = ''; a.className = ''; } /* Tab3 class (should replace Tab and Tab2 classs) This class fixes a IE bug where hiding a li element which is not the last li element messes up the tab display. Tab3 hides li elements in sequence, beginning from the last li element and re-creates the tab labels. */ util.Tabs3 = function(ulContainer, allTabIds, tabEvent) { // 'ulContainer' is the elementId of the tab element // 'allTabIds' is a simple array with all tab Id's (not element Id's!), i.e.: // ['graphs', 'graph_options', 'table'] // The element Id's for the list elements are created here. We also read the labels and // save them within a new tabs object, because we need the labels if we change the tab sequence. // tabs must contain all possible tabs, respectively as they exist in the ul element, in the right order. // The tabs can later be set by setSequence to any number or order of the given tabs. // We create a tab object to handle the tabs, which looks as follows: // The tabsDb contains all tabs identified by ID ... /* tabsDb = { graphs: { label: 'Graphs' currentTabIndex: 0 }, graph_options: { label: 'Graph Options' currentTabIndex: 0 } ... } */ // The tab li elements become an ID with tabIndex (0,1,2,...) in combination with an idPrefix, i.e.: // ue_id:0 // ue_id:1 var idPrefix = util.getUniqueElementId(); var tabsDb = {}; this.idPrefix = idPrefix; this.allTabIds = allTabIds; this.tabEvent = tabEvent; this.selectedTabIndex = -1; // 0, 1, 2, ... refers to the tab array position this.tabSequence = []; // initialized upon setSequence() , i.e. ['graphs', 'table'] will only show the graphs and table tab var ul = util.getE(ulContainer); var liElements = ul.getElementsByTagName('li'); // init the tabs for (var i = 0; i < allTabIds.length; i++) { var tabId = allTabIds[i]; var elementId = idPrefix + ':' + i; var li = liElements[i]; li.id = elementId; var a = li.firstChild; var aText = a.firstChild; var label = aText.nodeValue; // alert('tab label: ' + label); tabsDb[tabId] = {label: label}; // tabsDb[tabId]['currentTabIndex'] = -0; YAHOO.util.Event.addListener(li, 'click', this.tabActivated, this); YAHOO.util.Event.addListener(li, 'mouseover', this.hoverOn); YAHOO.util.Event.addListener(li, 'mouseout', this.hoverOff); } this.tabsDb = tabsDb; // util.Tabs3SelfReferences[idPrefix] = this; } util.Tabs3.prototype.tabActivated = function(evt, self) { // Activates the tab function defined in this.tabEvent, which // is a function in the module of the tabs object. // We return the tabId as argument // alert('util.Tabs3.prototype.tabActivated() - this.id: ' + this.id); var elementId = this.id; var dat = elementId.split(':'); var idPrefix = dat[0]; var tabIndex = parseInt(dat[1], 10); // alert('tabIndex: ' + tabIndex); // var self = util.Tabs3SelfReferences[idPrefix]; var tabSequence = self.tabSequence; var tabId = tabSequence[tabIndex]; // alert('util.Tabs3.prototype.tabActivated() - tabId: ' + tabId); self.tabEvent(tabId); } util.Tabs3.prototype.setSequence = function(tabSequence, setToTabId) { // alert('setSequence()'); var idPrefix = this.idPrefix; var allTabIds = this.allTabIds; var tabsDb = this.tabsDb; var i; var newSelectedTabIndex = -1; for (i = 0; i < tabSequence.length; i++) { var tabId = tabSequence[i]; var tabElementId = idPrefix + ':' + i; var tabLi = util.getE(tabElementId); var tabAnchor = tabLi.firstChild; var existingTextNode = tabAnchor.firstChild; var newTextNode = document.createTextNode(tabsDb[tabId].label); tabAnchor.replaceChild(newTextNode, existingTextNode); // display the tab if (tabLi.style.display === 'none') { // alert('Set style.display of tab index: ' + i); tabLi.style.display = ''; } // get the index of the activeTabId if (tabId === setToTabId) { newSelectedTabIndex = i; } } if (tabSequence.length < allTabIds.length) { // hide all further tab elements for (i = tabSequence.length; i < allTabIds.length; i++) { util.hideE(idPrefix + ':' + i); } } if (newSelectedTabIndex > -1) { // make the tab active this.setActiveTabByIndex(newSelectedTabIndex); } /* else { // There is some mismatch with setToTabId alert('Tabs3.setSquence - invalid setToTabId: ' + setToTabId); } */ this.tabSequence = tabSequence; } util.Tabs3.prototype.setActiveTab = function(tabId) { // Get the index of the tabId and then set the tab by setActiveTabByIndex() // alert('util.Tabs3.prototype.setActiveTab - tabId: ' + tabId); var tabSequence = this.tabSequence; for (var i = 0; i < tabSequence.length; i++) { if (tabId === tabSequence[i]) { this.setActiveTabByIndex(i); break; } } } util.Tabs3.prototype.setActiveTabByIndex = function(newTabIndex) { // Only set the tab if it is not already active var selectedTabIndex = this.selectedTabIndex; if (selectedTabIndex !== newTabIndex) { // If the tab isn't already selected var idPrefix = this.idPrefix; // var tabElementIds = this.tabElementIds; var li; var a; if (selectedTabIndex !== -1) { // Reset selected tab // alert('Tabs3 class - Reset selected tab'); li = util.getE(idPrefix + ':' + selectedTabIndex); a = li.firstChild; li.className = ''; a.className = ''; YAHOO.util.Event.addListener(li, 'click', this.tabEvent); YAHOO.util.Event.addListener(li, 'mouseover', this.hoverOn); YAHOO.util.Event.addListener(li, 'mouseout', this.hoverOff); } // Select tab of newTabIndex // alert('Tabs2 class - Select tab of given tabElementId: ' + tabElementId); li = util.getE(idPrefix + ':' + newTabIndex); a = li.firstChild; li.className = 'active'; a.className = 'active'; YAHOO.util.Event.removeListener(li, 'click', this.tabEvent); YAHOO.util.Event.removeListener(li, 'mouseover', this.hoverOn); YAHOO.util.Event.removeListener(li, 'mouseout', this.hoverOff); // remove focus a.blur(); this.selectedTabIndex = newTabIndex; } } util.Tabs3.prototype.hoverOn = function() { var li = this; var a = li.firstChild; li.className = 'hover'; a.className = 'hover'; } util.Tabs3.prototype.hoverOff = function() { var li = this; var a = li.firstChild; li.className = ''; a.className = ''; } /* dropDownMenu control */ util.dropDownMenu = { menuItems: {}, // contains obj as defined below, accessible by btnElementId activeMenuItemId: '', // Drop down region region: { left: 0, top: 0, right: 0, bottom: 0 }, // Active mouse position tracked by mousemove pageX: 0, pageY: 0, add: function(btnElementId, dropDownElementId) { // alert('dropDownMenu.add()'); // register menuItem by btnElementId var obj = {}; obj.btnElementId = btnElementId; obj.dropDownElement = util.getE(dropDownElementId); util.dropDownMenu.menuItems[btnElementId] = obj; // add event YAHOO.util.Event.addListener(btnElementId, 'click', util.dropDownMenu.toggle); }, toggle: function(evt) { // invoked upon click on btnElementId // open or close drop down var btnElement = evt.target || evt.srcElement; if (btnElement.nodeName !== 'A') { btnElement = btnElement.parentNode; } if (util.dropDownMenu.activeMenuItemId === '') { // Drop down menu is closed, open it. var obj = util.dropDownMenu.menuItems[btnElement.id]; // get Region of reference element var btnRegion = YAHOO.util.Dom.getRegion(btnElement); var ul = obj.dropDownElement; ul.style.top = btnRegion.bottom + 'px'; ul.style.left = btnRegion.left + 'px'; ul.style.display = 'block'; // Write ul region to obj which we check for move out coordinates var dropDownRegion = YAHOO.util.Dom.getRegion(ul); // Override the top region with the btn region so that we can move out of the ul, // We also add some padding around so that the ul does not immediately disappear. var region = util.dropDownMenu.region; region.top = btnRegion.top; region.left = dropDownRegion.left - 18; region.right = dropDownRegion.right + 18; region.bottom = dropDownRegion.bottom + 18; util.dropDownMenu.activeMenuItemId = btnElement.id; YAHOO.util.Event.addListener(document, 'mousemove', function(evt) { // Track mouse position util.dropDownMenu.pageX = evt.pageX; util.dropDownMenu.pageY = evt.pageY; setTimeout(function() { util.dropDownMenu.closeByMoveOut(); }, 200); }); YAHOO.util.Event.addListener(ul, 'mouseup', util.dropDownMenu.closeByMouseClick); } else { // drop down is open, close it util.dropDownMenu.close(); } }, close: function() { // Make sure the menu hasn't been closed yet. if (util.dropDownMenu.activeMenuItemId !== '') { var obj = util.dropDownMenu.menuItems[util.dropDownMenu.activeMenuItemId]; var ul = obj.dropDownElement; YAHOO.util.Event.removeListener(document, 'mousemove'); YAHOO.util.Event.removeListener(ul, 'mouseup'); ul.style.display = 'none'; util.dropDownMenu.activeMenuItemId = ''; } }, closeByMouseClick: function(evt) { // Close the drop down upon left mousedown var i = (!util.userAgent.isIE) ? evt.button : evt.button - 1; if (i === 0) { util.dropDownMenu.close(); } // alert('closeByMouseClick: ' + evt.button); }, closeByMoveOut: function() { // closes the drop down when moving out of it var region = util.dropDownMenu.region; var x = util.dropDownMenu.pageX; var y = util.dropDownMenu.pageY; if (x < region.left || x > region.right || y < region.top || y > region.bottom) { util.dropDownMenu.close(); } } } /* navGroup replaces util.dropDownMenu. It can be used for single menu items with a drop down or multiple menu items with and without drop down. */ util.NavGroup = function(o) { // o.containerId => the container element of one or more buttons // o.menuBaseIds => an array with one or more relevant menu baseId's, i.e.: // rc_nav_config => This is the baseId // rc_nav_config:btn => This is the button of the given baseId // rc_nav_config:menu => This is the ul menu of the given baseId // // o.events => optional events per baseId which are fired when // opening the corresponding menu. var YE = YAHOO.util.Event; var containerId = o.containerId; var menuBaseIds = o.menuBaseIds; var events = o.hasOwnProperty('events') ? o.events : {}; this.btnClassName = o.hasOwnProperty('btnClassName') ? o.btnClassName : ''; this.btnActiveClassName = o.hasOwnProperty('btnActiveClassName') ? o.btnActiveClassName : ''; this.menuBaseIds = {}; this.openedMenuBaseId = ''; // Any opened menu this.onNavbar = false; // True if the mouse cursor is above navigation bar this.onMenu = false; // True if the mouse cursor is above the opened menu this.eventCount = 0; var baseId; var btnElement; var menuElement; var numberOfDropDowns = 0; // Track the drop down menus which actually exist in the GUI. for (var i = 0, l = menuBaseIds.length; i < l; i++) { baseId = menuBaseIds[i]; btnElement = util.getE(baseId + ':btn'); menuElement = util.getE(baseId + ':menu'); if (typeof btnElement !== 'undefined') { // Keep a reference to the button and menu element. this.menuBaseIds[baseId] = {}; this.menuBaseIds[baseId].btn = btnElement; this.menuBaseIds[baseId].menu = menuElement; // Note, we also need to handle buttons without a menu for // the _hoverOnButton event because hovering over a simple button // must yet close any open menu of another button. YE.addListener(btnElement, 'mouseover', this._hoverOnButton, this); if (typeof menuElement !== 'undefined') { // Assign individual click events because the single delegate event // has a problem with the context object "self" YE.addListener(btnElement, 'click', this._toggleMenu, this); if (events.hasOwnProperty(baseId)) { this.menuBaseIds[baseId].event = events[baseId]; } numberOfDropDowns = numberOfDropDowns + 1; } } } // util.showObject(this.menuBaseIds); if (numberOfDropDowns > 0) { // Assign event to container element // YE.delegate(containerId, 'mouseover', this.moveInGroup, 'a', this); // Toggle menu - disabled because context object "self" does not work! // YE.delegate(containerId, 'click', this._toggleMenu, 'a', this); // This handles hovering over a button // This handles exiting the navbar YE.addListener(containerId, 'mouseenter', this._handleMouseenter, this); YE.addListener(containerId, 'mouseleave', this._handleMouseleave, this); } } util.NavGroup.prototype = { _getBaseId: function(elementId) { // This returns the baseId by removing the id suffix // :btn or :menu from the element id. Note, // baseId may contain colons as well, i.e.: re01:rows:btn, // where the baseId is 're01:rows'. var substringIndex = elementId.lastIndexOf(':'); var baseId = elementId.substring(0, substringIndex); return baseId; }, _toggleMenu: function(evt, self) { var id = this.id; // console.log('toggleMenu fired: ' + id); if (id.indexOf(':') !== -1) { // Get the baseId var baseId = self._getBaseId(id); var openedMenuBaseId = self.openedMenuBaseId; // Handle already opened menu if (openedMenuBaseId === '') { // No menu is open yet, open it self._openMenu(baseId); } else if (openedMenuBaseId === baseId) { // Menu is open, close it self._closeMenu(); } // Remove focus this.blur(); } }, _openMenu: function(baseId) { // console.log('_openMenu of baseId: ' + baseId); // Position the menu var baseObj = this.menuBaseIds[baseId]; var btnElement = baseObj.btn; var menuElement = baseObj.menu; // Note, there may be buttons without a menu, so we need to check if a menu exists if (menuElement) { util.positionAndShowDropDownElement(btnElement, menuElement); YAHOO.util.Event.addListener(menuElement, 'mouseenter', this._handleMouseenter, this); YAHOO.util.Event.addListener(menuElement, 'mouseleave', this._handleMouseleave, this); YAHOO.util.Event.addListener(menuElement, 'mouseup', this._closeMenuByClick, this); this._setButtonStyle(baseId, true); if (baseObj.hasOwnProperty('event')) { // Call defined event baseObj.event(); } } // We also set openedMenuBaseId in case that the button // has no drop down to keep track that we are in open menu mode. this.openedMenuBaseId = baseId; }, _closeMenu: function() { // console.log('_closeMenu() fired'); // This closes the current open menu var openedMenuBaseId = this.openedMenuBaseId; if (openedMenuBaseId !== '') { var menuElement = this.menuBaseIds[openedMenuBaseId].menu; if (menuElement) { YAHOO.util.Event.removeListener(menuElement, 'mouseenter', this._handleMouseenter); YAHOO.util.Event.removeListener(menuElement, 'mouseleave', this._handleMouseleave); YAHOO.util.Event.removeListener(menuElement, 'mouseup', this._closeMenuByClick); menuElement.style.display = 'none'; this._setButtonStyle(openedMenuBaseId, false); } // openedMenuBaseId may also exist when the button // has no drop down to keep track that we are in open menu mode. this.openedMenuBaseId = ''; } }, _closeMenuByClick: function(evt, self) { // Clicked on menu item, close the menu upon left mouse click // when not clicking in input field such as in profiles drop down. var clickId = (!util.userAgent.isIE) ? evt.button : evt.button - 1; var element = evt.target || evt.srcElement; // console.log('_closeMenuByClick: ' + evt.target.nodeName); var pattern = /^A|SPAN|LI$/; if (clickId === 0 && pattern.test(element.nodeName)) { self.onMenu = false; self._closeMenu(); } }, _setButtonStyle: function(baseId, isActive) { var btnElement = this.menuBaseIds[baseId].btn; btnElement.className = isActive ? this.btnActiveClassName : this.btnClassName; }, _hoverOnButton: function(evt, self) { // console.log('_hoverOnButton fired: ' + this.id); var openedMenuBaseId = self.openedMenuBaseId; // Hovered over a nav button. Take action only // if a menu is already open. if (openedMenuBaseId !== '') { var id = this.id; var baseId = self._getBaseId(id); if (baseId !== openedMenuBaseId) { // Close the open menu self._closeMenu(); // Open menu of given baseId self._openMenu(baseId); } } }, // Close menu when moving out of navigation area _handleMouseenter: function(evt, self) { // console.log('_handleMouseenter fired: ' + this.id); self._handleMouseenterMouseleave(this.id, true); }, _handleMouseleave:function(evt, self) { // console.log('_handleMouseleave fired: ' + this.id); self._handleMouseenterMouseleave(this.id, false); }, _handleMouseenterMouseleave: function(elementId, isMouseEnter) { // console.log('_handleMouseenterMouseleave()'); // console.log('_handleMouseenterMouseleave() - elementId: ' + elementId); // console.log('_handleMouseenterMouseleave() - isMouseEnter: ' + isMouseEnter); // Set mouse position state if (elementId === this.containerId) { this.onNavbar = isMouseEnter; } else { // Must have moved out of menu this.onMenu = isMouseEnter; } // Set eventCount var newEventCount = this.eventCount + 1; this.eventCount = newEventCount; // console.log('_handleMouseenter newEventCount: ' + newEventCount); var self = this; setTimeout(function() { self._checkMousePositionState.call(self, newEventCount); }, 800); }, _checkMousePositionState: function(eventCount) { // console.log('_checkMousePositionState fired: ' + eventCount + ' ' + this.eventCount + ' ' + this.onNavbar + ' ' + this.onMenu); // Handle last event only if (this.openedMenuBaseId !== '' && eventCount === this.eventCount && !this.onNavbar && !this.onMenu) { // Moved mouse cursor out of navbar and out of open menu. // Close open menu. // console.log('_checkMousePositionState CLOSE MENU'); this._closeMenu(); } } } /* Validator class */ // note, we must always return the form value, even if the item is already logged, so that // the callee object alwyas gets a value, or simply don't return something? util.Validator = function() { this.errorLog = []; } util.Validator.prototype.reset = function() { // remove all error messages and clear the error log var errorLog = this.errorLog; for (var i = 0; i < errorLog.length; i++) { var elementId = errorLog[i].elementId + ':error'; var element = document.getElementById(elementId); if (element) { util.hideE(elementId); } } this.errorLog = []; } // util.Validator.prototype.resetElement = function(elementId) { util.Validator.prototype.resetElement = function(e, validatorObj) { // alert('reset element of elementId: ' + this.id + '\nerrorLog: ' + validatorObj); var elementId = this.id; var formElement = document.getElementById(elementId); var errorElement = document.getElementById(elementId + ':error'); // remove the event listener from form element if (formElement) { YAHOO.util.Event.removeListener(formElement,'click', validatorObj.resetElement); } // hide error message if (errorElement) { util.hideE(elementId + ':error'); } // remove elementId in error log // util.deleteArrayObject(this.errorLog, 'elementId', elementId); util.deleteArrayObject(validatorObj.errorLog, 'elementId', elementId); } util.Validator.prototype.allValid = function() { // checks the errorLog for errors and if there is // any error it displays them var errorLog = this.errorLog; if (errorLog.length > 0) { for (var i = 0; i < errorLog.length; i++) { // util.showObject(errorLog[i]); // var formElement = document.getElementById(errorLog[i].elementId); var errorElement = document.getElementById(errorLog[i].elementId + ':error'); // alert(formElement + '\n' + errorElement); // if (formElement && errorElement) { if (errorElement) { // alert('write and show error'); // write error message to ':error' element container util.updateT(errorLog[i].elementId + ':error', errorLog[i].msg); util.showE(errorLog[i].elementId + ':error'); } else { // alert('formElement or errorElement does not exist'); } } return false; } return true; } util.Validator.prototype.getIsLogged = function(elementId) { // This returns true if the elementId is already logged in this.errorLog var isLogged = false; var errorLog = this.errorLog; for (var i = 0; i < errorLog.length; i++) { if (errorLog[i].elementId === elementId) { isLogged = true; break; } } return isLogged; } util.Validator.prototype.logInvalidElementValue = function(elementId, msg) { // add element and type to error log var errorLog = this.errorLog; errorLog[errorLog.length] = {elementId:elementId, msg: msg}; // Add event which will hide the error message upon element click // Note, 'isCustom' might not have an element, hence check for the element var element = util.getE(elementId); // alert(' Set error element: ' + element); if (element) { // alert('add eventListener to: ' + elementId); // We need to add the Validator object in the Listener so that we // get an object reference in resetElement() YAHOO.util.Event.addListener(element,'click', this.resetElement, this); } // alert('added item to error log, new length: ' + this.errorLog.length); } util.Validator.prototype.isValue = function(elementId, /* optional */ trimFormValue) { // Checks the form element to be not empty. // Set default trimFormValue if undefined if (typeof trimFormValue === 'undefined') { trimFormValue = true; } var theValue = util.getF(elementId, trimFormValue); // If this element hasn't been validated yet if (!this.getIsLogged(elementId) && (theValue === '')) { var msg = langVar('lang_stats.form_validation.no_value'); this.logInvalidElementValue(elementId, msg); } return theValue; } util.Validator.prototype.isUnique = function(elementId, lookupItems, /* optional */ convertToLowercase, /* optional */ trimFormValue) { // We check if the value of elementId exists in the lookupItems array // Set default convertToLowercase if undefined if (typeof convertToLowercase === 'undefined') { convertToLowercase = false; } // Set default trimFormValue if undefined if (typeof trimFormValue === 'undefined') { trimFormValue = true; } var theValue = util.getF(elementId, trimFormValue); // If this element hasn't been validated yet if (!this.getIsLogged(elementId)) { var isDuplicateItemValue = false; var s = !convertToLowercase ? theValue : theValue.toLowerCase(); for (var i = 0; i < lookupItems.length; i++) { var lookupItemValue = lookupItems[i]; if (convertToLowercase) { lookupItemValue = lookupItemValue.toLowerCase(); } if (s === lookupItemValue) { isDuplicateItemValue = true; break; } } if (isDuplicateItemValue) { var msg = langVar('lang_stats.form_validation.duplicat_name'); this.logInvalidElementValue(elementId, msg); } } return theValue; } util.Validator.prototype.isInteger = function(elementId, /* optional */ min, /* optional */ max) { var theValue = util.getF(elementId); if (!this.getIsLogged(elementId) && !util.isInteger(theValue, min, max)) { var minDefined = !util.isUndefined(min); var maxDefined = !util.isUndefined(max); var msg = ''; if (minDefined && maxDefined) { msg = langVar('lang_stats.form_validation.invalid_integer_min_max'); msg = msg.replace(/__PARAM__1/, min); msg = msg.replace(/__PARAM__2/, max); } else if (minDefined) { msg = langVar('lang_stats.form_validation.invalid_integer_min'); msg = msg.replace(/__PARAM__1/, min); } else if (maxDefined) { msg = langVar('lang_stats.form_validation.invalid_integer_max'); msg = msg.replace(/__PARAM__1/, max); } else { msg = langVar('lang_stats.form_validation.invalid_integer'); } this.logInvalidElementValue(elementId, msg); } return theValue; } util.Validator.prototype.isFloat = function(elementId, /* optional */ min, /* optional */ max) { var theValue = util.getF(elementId); if (!this.getIsLogged(elementId) && !util.isFloat(theValue, min, max)) { var msg = ''; var minDefined = !util.isUndefined(min); var maxDefined = !util.isUndefined(max); if (minDefined && maxDefined) { msg = langVar('lang_stats.form_validation.invalid_float_min_max'); msg = msg.replace(/__PARAM__1/, min); msg = msg.replace(/__PARAM__2/, max); } else if (minDefined) { msg = langVar('lang_stats.form_validation.invalid_float_min'); msg = msg.replace(/__PARAM__1/, min); } else if (maxDefined) { msg = langVar('lang_stats.form_validation.invalid_float_max'); msg = msg.replace(/__PARAM__1/, max); } else { msg = langVar('lang_stats.form_validation.invalid_float'); } this.logInvalidElementValue(elementId, msg); } return theValue; } util.Validator.prototype.isNumber = function(elementId, /* optional */ min, /* optional */ max) { // This checks for any number (int or float) var theValue = util.getF(elementId); if (!this.getIsLogged(elementId) && !util.isInteger(theValue, min, max) && !util.isFloat(theValue, min, max)) { var msg = langVar('lang_stats.form_validation.invalid_number'); this.logInvalidElementValue(elementId, msg); } return theValue; } util.Validator.prototype.isRegularExpression = function(elementId) { var theValue = util.getF(elementId); if (!this.getIsLogged(elementId) && !util.isRegularExpression(theValue)) { var msg = langVar('lang_stats.form_validation.invalid_regular_expression'); this.logInvalidElementValue(elementId, msg); } return theValue; } util.Validator.prototype.isEmailAddress = function(elementId) { // This validates a single email address var theValue = util.getF(elementId); if (!this.getIsLogged(elementId) && !util.isEmailAddress(theValue)) { var msg = langVar('lang_stats.form_validation.invalid_email_address'); this.logInvalidElementValue(elementId, msg); } return theValue; } util.Validator.prototype.isEmailAddresses = function(elementId) { // This validates a single email address or multiple email addresses separated by a comma. var theValue = util.getF(elementId); if (!this.getIsLogged(elementId)) { var isValidEmailAddress = true; if (theValue.indexOf(',') === -1) { // single email address isValidEmailAddress = util.isEmailAddress(theValue); } else { // multiple email addresses var emailAddressesDat = theValue.split(','); for (var i = 0; i < emailAddressesDat.length; i++) { var emailAddress = util.trim(emailAddressesDat[i]); if (!util.isEmailAddress(emailAddress)) { isValidEmailAddress = false; break; } } } if (!isValidEmailAddress) { var msg = langVar('lang_stats.form_validation.invalid_email_addresses'); this.logInvalidElementValue(elementId, msg); } } return theValue; } util.Validator.prototype.isNodeName = function(elementId) { // checks to be a valid node name var theValue = util.getF(elementId); if (!this.getIsLogged(elementId)) { var pattern = /[^_a-z0-9]/; if (pattern.test(theValue)) { var msg = langVar('lang_stats.form_validation.invalid_identifier'); this.logInvalidElementValue(elementId, msg); } } return theValue; } util.Validator.prototype.isCustom = function(elementId, msg) { // This does not require validation, it simply throws a custom error message // and does not return a form value. if (!this.getIsLogged(elementId)) { this.logInvalidElementValue(elementId, msg); } } /* Panel3 class */ util.Panel3 = function(obj) { // util.showObject(obj); // Default values become overwritten by obj this.panelId = null; this.panelClassName = ''; // i.e. panel-50 this.width = -1; this.height = -1; this.top = -1; this.left = -1; this.right = -1; this.bottom = -1; this.zIndex = 20; // The zIndex of the panel, we require the zIndex for the form, the cover and iframe! this.isCover = false; // Creates a background cover if true this.isCloseButton = true; this.closeEvent = null; // this.isIframe = util.userAgent.isIE; this.isIframe = false; // KHP 31/JAN/2011 - the iframe becomes a problem with drag drop, check for solution // alert('this.isIframe: ' + this.isIframe); // If isSticky is given and is true then we don't re-position the panel upon "scroll", // it sticks at the position where the panel is initially positioned. // This is useful for panels which don't fit in Admin or Config this.isSticky = false; this.panelHeaderLabel = ''; // this.isScroll = false; // Override default values for (var prop in obj) { this[prop] = obj[prop]; } this.headerTitleId = ''; this.coverId = ''; this.iframeId = ''; var panel = util.getE(this.panelId); panel.style.zIndex = this.zIndex; if (this.width > 0) { panel.style.width = this.width + 'px'; } if (this.height > 0) { panel.style.height = this.height + 'px'; } if (this.panelHeaderLabel !== '') { // // Create the panel header and insert it into the panel // var titleId = util.getUniqueElementId(); var imageContainerId = util.getUniqueElementId(); var firstElement = panel.firstChild; var headerDiv = document.createElement('div'); var headerElementId = this.panelId + ':header'; headerDiv.id = headerElementId; headerDiv.className = this.panelClassName + '-header'; var headerFrameDiv = document.createElement('div'); headerFrameDiv.id = imageContainerId; headerFrameDiv.className = this.panelClassName + '-header-frame'; var headerTitleDiv = document.createElement('div'); headerTitleDiv.id = titleId; headerTitleDiv.className = this.panelClassName + '-header-title'; var headerTitleTxt; if (this.panelHeaderLabel !== '-') { headerTitleTxt = document.createTextNode(this.panelHeaderLabel); } else { headerTitleTxt = document.createTextNode('\u00a0'); } var headerBottomDiv = document.createElement('div'); headerBottomDiv.className = this.panelClassName + '-header-bottom'; // var spaceTxt = document.createTextNode('\u00a0'); // inserts   var spaceTxtA = document.createTextNode('\u00a0'); var spaceTxtB = document.createTextNode('\u00a0'); if (this.isCloseButton) { var img = document.createElement('img'); img.src = imgDb.panelClose.src; img.alt = langVar('lang_stats.btn.close'); img.width = imgDb.panelClose.width; img.height = imgDb.panelClose.height; if (this.closeEvent) { // Use external close event to close the panel YAHOO.util.Event.addListener(img, 'click', this.closeEvent, this); } else { // Use internal close event to close the panel YAHOO.util.Event.addListener(img, 'click', this.__close, this); } } headerTitleDiv.appendChild(headerTitleTxt); headerFrameDiv.appendChild(headerTitleDiv); headerFrameDiv.appendChild(spaceTxtA); headerBottomDiv.appendChild(spaceTxtB); if (this.isCloseButton) { headerFrameDiv.appendChild(img); } headerDiv.appendChild(headerFrameDiv); headerDiv.appendChild(headerBottomDiv); panel.insertBefore(headerDiv, firstElement); this.headerTitleId = titleId; // Handle drag drop var dd = new YAHOO.util.DD(this.panelId); dd.setHandleElId(headerElementId); } // // Create the footer // var footerDiv = document.createElement('div'); footerDiv.className = this.panelClassName + '-footer'; var footerOffsetDiv = document.createElement('div'); footerOffsetDiv.className = this.panelClassName + '-footer-offset'; var footerSpaceTxt = util.createT(' '); footerOffsetDiv.appendChild(footerSpaceTxt); footerDiv.appendChild(footerOffsetDiv); panel.appendChild(footerDiv); // // Create background cover which hides underlying elements // if (this.isCover) { this.coverId = util.getUniqueElementId(); var coverZIndex = this.zIndex - 5; var coverDiv = util.createE('div', {id:this.coverId, className:'form-cover', zIndex:coverZIndex}); var coverText = util.createT(' '); util.chainE(coverDiv, coverText); panel.parentNode.appendChild(coverDiv); } // Create iframe element as form backround. // This fixes IE so that no elements shine through the form. if (this.isIframe) { this.iframeId = util.getUniqueElementId(); var iframe = document.createElement('iframe'); iframe.id = this.iframeId; iframe.tabIndex = '-1'; iframe.src = 'javascript:false;'; iframe.className = 'form-cover'; iframe.style.zIndex = this.zIndex - 2; panel.parentNode.appendChild(iframe); } } util.Panel3.prototype.open = function(obj) { // obj is optional and has the properties left, top, right, bottom and label // If a position argument is given it overrides any existing absolute position // If a label argument is given it sets the panel header label if (typeof obj !== 'undefined') { // Note, if i.e. the "left" position is given then we set // the "right" position to default value! if (obj.hasOwnProperty('left')) { this.left = obj.left; this.right = -1; } if (obj.hasOwnProperty('right')) { this.right = obj.right; this.left = -1; } if (obj.hasOwnProperty('top')) { this.top = obj.top; this.bottom = -1; } if (obj.hasOwnProperty('bottom')) { this.bottom = obj.bottom; this.top = -1; } if (obj.hasOwnProperty('label')) { util.updateT(this.headerTitleId, obj.label); } } // alert('this.top after open(): ' + this.top); if (this.isCover) { this.setCoverSize(); YAHOO.util.Event.addListener(window, 'resize', this.setCoverSizeUponResize, this); util.showE(this.coverId); } if (!this.isSticky) { YAHOO.util.Event.addListener(window, 'scroll', this.__setPositionByWindow, this); } // set initial position this.__setPosition(true/* true because this is the initial positioning */); util.showE(this.panelId); if (this.isIframe) { this.setIframePositionAndSize(); util.showE(this.iframeId); } } util.Panel3.prototype.__close = function(evt, self) { // __close() is only used if no external closeEvent is given! self.close(); } util.Panel3.prototype.close = function() { if (!this.isSticky) { YAHOO.util.Event.removeListener(window, 'scroll', this.__setPositionByWindow); } util.hideE(this.panelId); if (this.isIframe) { util.hideE(this.iframeId); } if (this.isCover) { YAHOO.util.Event.removeListener(window, 'resize', this.setCoverSizeUponResize, this); util.hideE(this.coverId); } } util.Panel3.prototype.__setPositionByWindow = function(evt, self) { var isInitialPositioning = false; self.__setPosition(isInitialPositioning); } util.Panel3.prototype.__setPosition = function(isInitialPositioning) { // If isInitialPositioning is true then we don't position the iframe // because the panel is not yet open, in all other cases we // position the iframe if it exists. // alert('update position of panelId: ' + this.panelId); var element = util.getE(this.panelId); var scrollY = YAHOO.util.Dom.getDocumentScrollTop(); var scrollX = YAHOO.util.Dom.getDocumentScrollLeft(); // util.showObject(this); if (this.top >= 0) { // alert('this.top: ' + this.top + '\nthis.left: ' + this.left); // alert('this.top: ' + this.top + '\nscrollY: ' + scrollY); element.style.top = (this.top + scrollY) + 'px'; } if (this.left >= 0) { // alert('set left position to: ' + (left + scrollX) + 'px'); element.style.left = (this.left + scrollX) + 'px'; } if (this.right >= 0) { // alert('set right position to: ' + (right + scrollX) + 'px'); element.style.right = (this.right + scrollX) + 'px'; } if (!isInitialPositioning && this.isIframe) { this.setIframePositionAndSize(); } // util.showObject(element.style.top); } util.Panel3.prototype.setIframePositionAndSize = function() { var region = YAHOO.util.Dom.getRegion(this.panelId); var element = util.getE(this.iframeId); element.style.top = region.top; element.style.left = region.left; element.style.width = region.width; element.style.height = region.height; } util.Panel3.prototype.prePositionAtCenter = function() { // Display the panel temporary so that we get the region var panel = util.getE(this.panelId); panel.style.top = '0px'; panel.style.left = '0px'; panel.style.display = 'block'; panel.style.visibility = 'hidden'; // util.showE(this.panelId); // util.hideEV(this.panelId); var panelRegion = YAHOO.util.Dom.getRegion(panel); // util.showObject(region); panel.style.display = 'none'; panel.style.visibility = ''; panelWidth = panelRegion.width; panelHeight = panelRegion.height; var viewportWidth = YAHOO.util.Dom.getViewportWidth(); var viewportHeight = YAHOO.util.Dom.getViewportHeight(); // var topDistance = ((viewportHeight - panelHeight) / 2) - 30; var topDistance = ((viewportHeight - panelHeight) / 3); var leftDistance = (viewportWidth - panelWidth) / 2; this.top = (topDistance > -1) ? topDistance : 0; this.left = (leftDistance > -1) ? leftDistance : 0; } util.Panel3.prototype.setCoverSizeUponResize = function(evt, self) { self.setCoverSize(); } util.Panel3.prototype.setCoverSize = function() { var coverElement = util.getE(this.coverId); coverElement.style.width = YAHOO.util.Dom.getDocumentWidth() + 'px'; coverElement.style.height = YAHOO.util.Dom.getDocumentHeight() + 'px'; } /* BusyPanel class */ util.BusyPanel = function() { this.isBuild = false; this.isActive = false; this.mainElement = ''; this.contentElementId = ''; } util.BusyPanel.prototype.showLoading = function() { this._show(langVar('lang_stats.btn.loading')); } util.BusyPanel.prototype.showSaving = function() { this._show(langVar('lang_stats.btn.saving')); } util.BusyPanel.prototype.showCustom = function(label) { this._show(label); } util.BusyPanel.prototype._show = function(label) { // label is allowed to be in HTML, so we use innerHTML var element; if (!this.isBuild) { this._build(); } var contentElement = util.getE(this.contentElementId); contentElement.innerHTML = label; if (!this.isActive) { // Set the position before we display it element = this.mainElement; element.style.visibility = 'hidden'; element.style.display = 'block'; this._setPosition(); element.style.visibility = 'visible'; YAHOO.util.Event.addListener(window, 'resize', this._setPositionUponResize, this); this.isActive = true; } else { // progress panel is already displayed, just re-position this._setPosition(); } } util.BusyPanel.prototype._setPositionUponResize = function(evt, self) { self._setPosition(); } util.BusyPanel.prototype._setPosition = function() { var YD = YAHOO.util.Dom; var element = this.mainElement; var region = YD.getRegion(element); var elementWidth = region.width; var viewportWidth = YD.getViewportWidth(); var viewportHeight = YD.getViewportHeight(); element.style.left = Math.round(viewportWidth / 2 - elementWidth / 2) + 'px'; element.style.top = Math.round(viewportHeight / 3) + 'px'; } util.BusyPanel.prototype.stop = function() { if (this.isActive) { YAHOO.util.Event.removeListener(window, 'resize', this._setPositionUponResize); this.mainElement.style.display = 'none'; this.isActive = false; } } util.BusyPanel.prototype._build = function() { var mainElementId = util.getUniqueElementId(); var contentElementId = mainElementId + ':content'; var mainContentDiv = util.createE('div', {padding:'0'}); var contentDiv = util.createE('div', {id:contentElementId, padding:'10px 16px'}); var imgDat = imgDb.simpleProgress; var imgDiv = util.createE('div', {textAlign:'center', padding:'0px 16px 8px 16px'}); var img = util.createE('img', {src:imgDat.src, width:imgDat.width, height:imgDat.height, title:'', alt:''}); util.chainE([mainContentDiv, contentDiv, [imgDiv, img]]); // var mainDiv = util.getRoundBox(mainElementId, 20, mainContentDiv); var mainDiv = util.createE('div', {id:mainElementId, className:'panel-20', display:'none'}); util.chainE(mainDiv, mainContentDiv); mainDiv.style.zIndex = 1000; var bodyElements = document.getElementsByTagName('body'); var bodyElement = bodyElements[0]; bodyElement.appendChild(mainDiv); this.isBuild = true; this.mainElement = mainDiv; this.contentElementId = contentElementId; } // // // MoveControl class // // util.MoveControl = function(baseId, moveEvent) { // Move control baseId is the element ID of the move control container div // Each image element ID in this container is a combination // of the baseID and move direction as follwos: // id="baseId:top" // id="baseId:up" // id="baseId:down" // id="baseId:bottom" // Note, the baseId may contain other colons ':' this.baseId = baseId; this.moveEvent = moveEvent; this.buttonsState = { top: {id:baseId + ':top', isDisabled:true, src:imgDb.moveTop.src, srcDis:imgDb.moveTopDis.src}, up: {id:baseId + ':up', isDisabled:true, src:imgDb.moveUp.src, srcDis:imgDb.moveUpDis.src}, down: {id:baseId + ':down', isDisabled:true, src:imgDb.moveDown.src, srcDis:imgDb.moveDownDis.src}, bottom: {id:baseId + ':bottom', isDisabled:true, src:imgDb.moveBottom.src, srcDis:imgDb.moveBottomDis.src} } } util.MoveControl.prototype = { setState: function(selectedItemIndex, numberOfItems) { // Sets the move control button state (enabled/disabled) depending // of selectedItemIndex and numberOfItems. // // Set default state // var moveDisabled = { top: true, up: true, down: true, bottom: true }; // // Set active state // if (selectedItemIndex >= 0 && numberOfItems > 1) { if (selectedItemIndex > 0) { moveDisabled.top = false; moveDisabled.up = false; } if (selectedItemIndex < (numberOfItems - 1)) { moveDisabled.down = false; moveDisabled.bottom = false; } } // // Set the buttons // var buttonsState = this.buttonsState; for (var prop in moveDisabled) { var isDisabled = moveDisabled[prop]; var theButton = buttonsState[prop]; if (isDisabled !== theButton.isDisabled) { // Change the button state var img = util.getE(theButton.id); img.src = isDisabled ? theButton.srcDis : theButton.src; theButton.isDisabled = isDisabled; if (isDisabled) { YAHOO.util.Event.removeListener(img, 'click', this.moveItem); } else { YAHOO.util.Event.addListener(img, 'click', this.moveItem, this); } } } }, moveItem: function(evt, self) { var element = evt.target || evt.srcElement; var elementId = element.id; var direction = self.getMoveDirection(elementId); self.moveEvent(direction); }, getMoveDirection: function(buttonElementId) { var dat = buttonElementId.split(':'); var lastItemIndex = dat.length - 1; return dat[lastItemIndex]; }, setPosition: function(listElementId) { // Sets the absolute position of the move control // alert('setPosition'); var moveElement = util.getE(this.baseId); var region = YAHOO.util.Dom.getRegion(listElementId); // util.showObject(region); moveElement.style.top = region.top + 'px'; moveElement.style.left = (region.left - 46) + 'px'; moveElement.style.display = 'block'; } } // // // Language variable util function // // function langVar(langVarPath) { // Return language variable if it exists, else return the langVarPath // Check if language variables exists by language module // name such as lang_stats, lang_config, etc. // If no language variable exists then we are in developer mode. if (!util.checkedForIsLanguageModule) { var i = langVarPath.indexOf('.'); var langModule = langVarPath.slice(0, i); util.isLanguageModule = (window[langModule] !== null); // We only check the first langVarPath util.checkedForIsLanguageModule = true; // alert('util.isLanguageModule: ' + util.isLanguageModule); } // Replace each dot "." in the langVarPath with dot underscore "._" // because the language variables use an underscore in the js object to // prevent name conflicts for words such as "delete", "length", etc. var jsLangVarPath = langVarPath.replace(/\./g,'._'); // alert('jsLangVarPath: ' + jsLangVarPath); var langVarValue; if (util.isLanguageModule) { // alert('jsLangVarPath 1:' + jsLangVarPath); /* if (window[jsLangVarPath] !== null) { alert('jsLangVarPath 2:' + jsLangVarPath); langVarValue = window[jsLangVarPath]; alert('langVarValue:' + langVarValue); } else { langVarValue = jsLangVarPath; } */ try { langVarValue = eval(jsLangVarPath); // alert('langVarPath: ' + langVarPath + '\nlangVarValue: ' + langVarValue); } catch(ex) { // alert('Missing language variable in js file: "' + langVarPath + '"'); langVarValue = jsLangVarPath; } } else { // Resolve language variables from server langVarValue = util.resolveLangVar(langVarPath, jsLangVarPath); } return langVarValue; } // Invoke upon load util.userAgent.init();