/** * @version $Id$ $Rev: 102307 $ $Date: 2010-07-29 15:42:30 -0700 (Thu, 29 Jul 2010) $ * Copyright (c) 2001-2010 Innovative Interfaces, Inc. All rights reserved. */ var sResearchProContext = "/iii/mfrpro"; var sContentPane = "mfStandardContentPane"; /******************************************************************************* MF XMLHttpRequest ******************************************************************************* The MFXMLHttpRequest object is a wrapper for JavaScript's native XMLHTTPRequest it provides "encapsulation" for the functionality and allows maintenance of multiple connections */ function MFXMLHttpRequest(name,url,datahandler,method,mimetype,datatype) { if ( arguments.length > 2 ) { this.init(name,url,datahandler,method,mimetype,datatype); } else { return false; } } MFXMLHttpRequest.prototype.init = function(name,url,datahandler,method,mimetype, datatype) { //ensure we bind this, don't want to lose our reference var req = this; //the id/name req.name = name; //the URL to be sent to the server req.URL= url; //function to process data req.dataHandler = datahandler; //the method for the request, for example GET or POST req.method = (method) ? method : "GET"; //mime type of the document being requested req.mimeType = (mimetype) ? mimetype : "text/xml"; //date type to be retrieved req.dataType = (datatype) ? datatype : "xml"; //get the status for this request req.status = 204; //junk addition req.message = null; //timer id req.timerId= null; //any additional headers to be sent with the request - hashmap req.headers= new Array(); //the data from the response either an XML doc or Text req.data = null; req.text = null; //data is loaded - default is false req.isLoaded = false; //request is being - used default is false req.requestIsActive = 0; //any error message req.error = null; } //list of ready state, uses JSON notation MFXMLHttpRequest.prototype.ReadyState = { UNINITIALIZED:0, LOADING:1, LOADED:2, INTERACTIVE:3, COMPLETE:4 } //list of statuses, uses JSON notation MFXMLHttpRequest.prototype.Status = { OK: 200, Created: 201, Accepted: 202, NoContent: 204, BadRequest: 400, Unauthorized: 401, Forbidden: 403, NotFound: 404, MethodNotAllowed: 405, RequestTimeout: 408, Gone: 410, ServerError: 500 } //list of errors, uses JSON notation MFXMLHttpRequest.prototype.Exception = { XmlHttpNotSupported: "XMLHTTPRequest is not supported by the browser.", XmlDomNotSupported: "XML DOM is not supported by the browser.", XmlIslandNotSupported: "XML Data Island is not supported by the browser.", InvalidMethod: "'method' must be 'GET', 'POST', or 'HEAD'.", MissingURL: "'url' must be specified.", InvalidHeaders: "'headers' must be an object.", InvalidContent: "'content' must be a string of the format 'name1=value1&name2=value2'.", IllegalContent: "'content' must be null when 'method' is 'GET' or 'HEAD'.", IllegalInterval: "'interval' can be set only if 'callback' of 'request' is set.", InvalidCallbackArgs: "'args' for the callback function misses certain properties.", InvalidDataReturn: "There was a problem retrieving the XML data:" } //allows users to set their own HTTP headers MFXMLHttpRequest.prototype.setHeaders = function(header,headerType) { //add headers to the hashmap this.headers[headerType]= header; } //creates formatted header string MFXMLHttpRequest.prototype.getHeaders = function() { var my = this; //make the header string var sHeader = ""; if( my.headers instanceof Array) { for (var key in my.headers) { sHeader = s + key + ":" + my.headers[key] + "\r\n"; } if (sHeader.length > 0) { sHeader.substring(0, sHeader.length - 2); } return sHeader; } else return null; } //create a cross-browser request object MFXMLHttpRequest.prototype.getRequestor = function() { try{ return new ActiveXObject("Msxml2.XMLHTTP"); } catch( e ) { this.error = e; } try{ return new ActiveXObject("Microsoft.XMLHTTP"); } catch( e ) { this.error = e; } try{ return new XMLHttpRequest(); } catch( e ) { this.error = e; } return null; } MFXMLHttpRequest.prototype.getData = function(req) { // Make sure the request is loaded (4) if (req.readyState == this.ReadyState.COMPLETE ) { // Make sure the status is "OK" //201 - end of the page //204 - no content available //200 - successful request //1223 - IE bug if ( req.status == this.Status.OK ) { // alert ("cxs req.responseText = " + req.responseText); // alert ("cxs this.dataType = " + this.dataType); this.text = req.responseText; if(this.dataType == 'xml') { this.data = req.responseXML; } else { this.data = req.responseText; } //data is loaded this.isLoaded = true; } else { this.error = this.Exception.InvalidDataReturn + req.statusText; this.isLoaded = false; } //alert(this.name+" getData:\n "+req.status+":"+this.error); this.status = req.status; //return true if the request is complete return true; } return false; } MFXMLHttpRequest.prototype.sendRequest = function() { var my = this; var requestor = my.getRequestor(); //if we have a requestor if(requestor) { //if browser supports it, set the mime type to the user supplied parameter if( requestor.overrideMimeType) { requestor.overrideMimeType(my.mimeType); } requestor.onreadystatechange = function() { if( my.getData.call( my, requestor) ) { if(my.isLoaded == true) { //call the dataHandler provided in the constructor //call method take: context as first param //change to apply to allow for variable arg list my.dataHandler.call( my, my.data, my.name) ; } //set the request to inactive my.requestIsActive=0; } else { //set the request to active my.requestIsActive=1; } } //don't let app overwrite a request if(my.requestIsActive==0) { requestor.open(my.method, my.URL, true); (window.ActiveXObject) ? requestor.send( null ) : requestor.send(""); } } } /******************************************************************************* All Other Functions *******************************************************************************/ /** * @param sAddress * @return true is sAddress is valid for email */ function validateEmail( sAddress ) { var emailAddr = ""; var savedForm = document.mfsavedstrutsform; if ( arguments.length == 1 ) emailAddr = sAddress; if ( emailAddr == "" || emailAddr.length() < 3 ) emailAddr = savedForm.mfemailto.value; var regExp = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,6})+$/; if ( regExp.test(emailAddr) ) { savedForm.submit(); return true; } else { alert(sInvalidEmailMessage); return false; } } /** * This function decodes the any string that's been encoded * using URL encoding technique * @param sEncodeString * @return */ function URLDecode( sEncodeString ) { // Create a regular expression to search all +s in the string var lsRegExp = /\+/g; // Return the decoded string return unescape(String(sEncodeString).replace(lsRegExp, " ")); } /** * change the cursorstyle of the specified element * * @param sElementID * @param cursorStyle */ function changeCursor( elementID, cursorStyle ) { var sElement = document.getElementById(elementID); if ( sElement ) { sElement.style.cursor = cursorStyle; } } /** * Handles the event triggered when the user selected a new language * from the dropdown created by the token. * * @param sContext explicitly set the context. */ function changeLanguage( sContext ) { var sLanguage = document.getElementById('language'); var sCurrentPage = document.getElementById('currentpage'); var sURL; if (sLanguage && sCurrentPage) { if (!sContext) sContext = sResearchProContext; sURL = sContext + '/changeLanguage.do?language=' + sLanguage.value + '¤tpage=' + sCurrentPage.value; replaceOrRedraw(sURL); } } /* add input element to current document */ function addInput( sType, sName, sValue ) { var inputRow = document.createElement('INPUT'); inputRow.setAttribute('type', sType); inputRow.setAttribute('name', sName); inputRow.setAttribute('value', sValue); inputRow.setAttribute('id', sName); document.mfsearchstrutsform.appendChild(inputRow); } /* returns true if current browser is IE */ function isBrowserIE() { var ie=0; if ( navigator.appName.indexOf('Explorer')>-1 ) ie=1; return ie; } function escapeQuot( str ) { s = s.replace('/"/g', """); return s; } function trim( str ) { if ( str.length > 0 ) { if ( str.charAt(0)==' ' ) { str = str.substr(1,str.length-1); str = trim(str); } if ( str.charAt(str.length-1)==' ' ) { str = str.substr(0,str.length-1); str = trim(str); } } return str; } function suppressErrors() { return true; } window.onerror= suppressErrors; function replaceOrRedraw( new_URL ) { //var oBase = document.all.tags('base'); //if (oBase && oBase.target) oBase.target = _self; if ( navigator.appVersion.charAt(0) < '3' ) location = new_URL; else location.replace(new_URL); return false; } function replaceOrRedrawParent( new_URL ) { //var oBase = document.all.tags('base'); //if (oBase && oBase.target) oBase.target = _self; if ( navigator.appVersion.charAt(0) < '3' ) parent.location = new_URL; else parent.location.replace(new_URL); return false; } /* pause js execution for specified milliseconds */ function pause( milliSeconds ) { date = new Date(); var curDate = null; do { var curDate = new Date(); } while(curDate-date < milliSeconds); } /* If we have received a iiitoken on a url, as a result of an mfgo or mffavs or a redirected MyMillennium auto login then show the logged in message and the logout button. */ function setLoginMsgAndButton() { var elementToken = document.getElementById( "mfLoggedInMsgLoadTime" ); var elementReplacement = document.getElementById( "loggedinstringid" ); var elementButton = document.getElementById( "logoffaccountid" ); if( elementToken ) { if( elementReplacement && ( elementReplacement.value != "null" ) ) { elementToken.innerHTML = elementReplacement.value; } else { if( elementButton ) elementButton.style.display = "none"; elementToken.innerHTML = ""; } } } /** * Pull the value from hiddensearchterm and put it into the searchterm * input if this is a simple search and searchterm1 if this is an * advanced search. * @see MFSimpleSearchPage.jsp * @see MFAdvancedSearchPage.jsp * @see C1001582 */ function setSearchTerm() { var searchTerm = document.getElementById("hiddensearchterm"); var searchType = document.getElementById("searchtype"); if (!searchTerm || searchTerm.value == null) { return; } if (searchType.value == "advanced") { var searchTermInput = document.getElementById( "searchterm1" ); searchTermInput.value = searchTerm.value; } else { var searchTermInput = document.getElementById( "searchterm" ); searchTermInput.value = searchTerm.value; } } function disableCtrlModifer(someEvent) { var rc = null; var disabled = {n:0, t:0}; var ctrlModifier = (window.event) ? window.event.ctrlKey : someEvent.ctrlKey; var key = (window.event) ? window.event.keyCode : someEvent.which; key = String.fromCharCode(key).toLowerCase(); if (ctrlModifier && (key in disabled)) rc = false; else rc = true; return rc; } /** * creates a new secondary browser window, * @param newURL String url to be fetched an loaded in new window * @param windowName String * @param model String yes/no */ function openViewSavedWindow (newURL) { var windowName = "SavedResultsWindow"; var newWindow; var debug="no"; newWindow = window.open(newURL, windowName, "titlebar=yes,toolbar=" + debug + ",width=750,height=650,left=10,status=yes,scrollbars=yes,resizable=yes," + "menubar=" + debug); if ( newWindow.focus ) // older browsers do not support focus newWindow.focus(); return false; } /** * creates a new secondary browser window, for the save group feature * (440 and up!) * @param newURL String url to be fetched an loaded in new window * @param windowName String * @param model String yes/no */ /* function openSaveGroupWindow(newURL) { var windowName = "SaveGroupWindow"; var newWindow; var debug="no"; newWindow = window.open(newURL, windowName, "titlebar=yes,toolbar=" + debug + ",width=750,height=650,left=10,status=yes,scrollbars=yes,resizable=yes," + "menubar=" + debug); if ( newWindow.focus ) // older browsers do not support focus newWindow.focus(); return false; } */ /** would like to have the view saved window be modal but in IE, cannot refer back to the parent to change any dom elements. 1. ModalDialogInterval = newWindow.setInterval("ModalDialogMaintainFocus()",5); 2. if the parent knows about it's child ( and noone thinks it does ) then when the parent gets focus you could not allow the user to act on the window or you could close the child 3. http://jquery.com/demo/thickbox/ 4. http://archive.dojotoolkit.org/nightly/tests/widget/test_ModalFloatingPane.html */ /** * creates a new secondary browser window, * @param newURL String url to be fetched an loaded in new window * @param windowName String * @param model String yes/no */ function openNewWindow (newURL, windowName, modal) { var debug="no"; var newWindow; if ( modal == 'yes') { // not all browsers support model dialog // and it turns out when using this method, the child window cannot get // to its opener or parent if ( window.showModalDialog ) newWindow = window.showModalDialog(newURL, windowName, "dialogWidth:750px;dialogHeight:650px;status:yes;scroll:yes;resizable:yes;dependent=yes"); else /* unfortunately it still doesn't actually make it modal it just forces it to stay in front which is the best that you can do with these browsers */ newWindow = window.open(newURL, windowName, "titlebar=yes,toolbar=" + debug + ",width=750,height=650,status=yes,scrollbars=yes,resizable=yes,dependent=yes,menubar=" + debug + ",modal=yes"); } else newWindow = window.open(newURL, windowName, "titlebar=yes,toolbar=" + debug + ",width=750,height=650,status=yes,scrollbars=yes,resizable=yes,dependent=no,menubar=" + debug + ",modal=no"); if ( newWindow.focus ) // older browsers do not support focus newWindow.focus(); return false; } /** * closes window * @param reloadParent String */ function closeWindow (reloadParent) { if ( reloadParent == "1" ) window.opener.location.reload(true); window.close(); return false; } /** * make an ajax request to have this record marked on the server * relies heavily on the DOM, if it changes... * @param sourceElem the requesting input element */ function notifyCheckChange (sourceElem, sResourceName) { var elem = sourceElem.nextSibling; var identifier = null; var ichecked = sourceElem.checked; // walking backwards up the tree to look for sResourceName // would expect this on the standard results pane and the view saved pane if ( arguments.length < 2 || !sResourceName || sResourceName == null ) { var pNode = sourceElem.parentNode; while ( pNode ) { if ( (pNode.nodeName == "DIV" || pNode.nodeName == "div") && pNode.className == "result" ) { pNode = pNode.parentNode; while ( pNode ) { if ( pNode.id && (pNode.id == sContentPane || pNode.id == "mfSavedResultsContentPane") ) { sResourceName = "AllResources"; break; } else if ( pNode.id ) { //sResourceName = pNode.id; //added a container for the content Content sResourceName = pNode.parentNode.id; break; } // keep going up the tree until you find one pNode = pNode.parentNode; } } if ( sResourceName != null ) break; pNode = pNode.parentNode; } } while ( elem ) { if ( elem.type == "hidden" && elem.name == "MarkedRecordID" ) { identifier = elem.value; break; } elem = elem.nextSibling; } if ( III.rProcessor && sResourceName && sResourceName != null && identifier ) { III.rProcessor.sendExportRequest(sResourceName, identifier, ichecked); return true; } return false; } /** * make an ajax request to have this record marked on the server * relies heavily on the DOM, if it changes... * @param sourceElemList Array of requesting elements * @param ichecked true/false * @param sResourceName String */ function notifyCheckChangeBatch (sourceElemList, ichecked, sResourceName) { var rtn = false; // ASSUMPTIONS: all elements in the list are from the same resource // all elements in the list are in the same checked state if ( sourceElemList == null || sourceElemList.length == 0 ) return rtn; // walking backwards up the tree to look for sResourceName // would expect this on the standard results pane and the view saved pane if ( arguments.length < 3 || !sResourceName || sResourceName == null ) { var pNode = sourceElemList[0].parentNode; while ( pNode ) { if ( (pNode.nodeName == "DIV" || pNode.nodeName == "div") && pNode.className == "result" ) { pNode = pNode.parentNode; while ( pNode ) { if ( pNode.id && (pNode.id == sContentPane || pNode.id == "mfSavedResultsContentPane") ) { sResourceName = "AllResources"; break; } else if ( pNode.id ) { sResourceName = pNode.id; break; } // keep going up the tree until you find one pNode = pNode.parentNode; } } if ( sResourceName != null ) break; pNode = pNode.parentNode; } } else if ( sResourceName == sContentPane ) sResourceName = "AllResources"; if ( !sResourceName || sResourceName == null ) return false; /* http://gethelp.devx.com/techtips/dhtml_pro/10min/10min1199/10min1199.asp */ var theIdentifierList = new Array(); var ctr = 0; for ( var i = 0; i < sourceElemList.length; i++ ) { var elem = sourceElemList[i].nextSibling; while ( elem ) { if ( elem.type == "hidden" && elem.name == "MarkedRecordID" ) { theIdentifierList[ctr] = elem.value; ctr++; break; } elem = elem.nextSibling; } } if ( III.rProcessor && theIdentifierList ) { III.rProcessor.sendExportRequestBatch(sResourceName, theIdentifierList, ichecked); pause(1000); rtn = true; } return rtn; } /** * @param sElement element to hide */ function hideElement(sElement) { if ( sElement ) { if ( isBrowserIE() ) sElement.style.display = "none"; else sElement.setAttribute("class", "mfOff"); } } /** * @param sElement element to show */ function showElement (sElement) { if ( sElement ) { if ( isBrowserIE() ) sElement.style.display = "block"; else sElement.setAttribute("class", "mfOn"); } } /** * @param sSomeString a string with milstring-type tokens in it (i.e. %0, %1, %2 etc) * @param aryReplacementValues an array of values to be used in the replacements * @return a string with %0 replaced by the first value in the array, %1 by the second, etc. */ function replaceMilStringTokens(sSomeString, aryReplacementValues) { if (sSomeString == null) return null; if (aryReplacementValues == null) return sSomeString; var sReplacedString = sSomeString; for (var i = 0; i < aryReplacementValues.length; i++) { var sToken = "%" + i; sReplacedString = replaceAnyToken(sReplacedString, sToken, aryReplacementValues[i]); } return sReplacedString; } /** * @param sSomeString a string containing a token that should be replaced * @param sToken the token that should be replaced (not necessarily a milstring-type token) * @param sReplacementValue the value that should be substituted for the token * @return the original string with token replaced by value */ function replaceAnyToken(sSomeString, sToken, sReplacementValue) { if (sSomeString == null) return null; if ((sToken == null) || (sReplacementValue == null)) return sSomeString; var sReplacedString; for (var i = 0; i < sSomeString.length; i++) { if (sSomeString.substring(i, i + sToken.length) == sToken) { sReplacedString = sSomeString.substring(0, i) + sReplacementValue + sSomeString.substring(i + sToken.length, sSomeString.length); i = sSomeString.length; // only replace the first instance of the token } } return sReplacedString; } //for call: C1063159 function initMFSaveGroupDisplay() { if( document.getElementById("overlayTransparency") ) { document.getElementById("overlayTransparency").onclick = hideOverlay; } if( document.getElementById("overlayContent") ) { var overlay = document.getElementById("overlayContent"); var mffav = document.getElementById("mfSaveGroup"); displayDOMNode("mfSaveGroup"); try{ overlay.replaceChild(mffav,overlay.childNodes[0]); }catch(e){ alert(e.message); } } var saveGroupCheck = document.getElementById("mfSaveGroupDisplay"); saveGroupCheck.onclick = function() { showOverlay(); checkBoxToggle(saveGroupCheck); }; } function checkBoxToggle(checkbox) { if(checkbox.checked) { checkbox.checked = false; } else { checkbox.checked = true; } } //generic show/hide:takes id value - defaults to show function displayDOMNode(nodeId) { var node = document.getElementById(nodeId); if(node) { if(node.style.display == "block") node.style.display = "none"; else node.style.display = "block"; } } function updateSaveGroupSearchInput(input) { if(input.id) { var hiddenInput = document.getElementById(input.id+"name"); if(hiddenInput) { hiddenInput.value = input.value; } } } /** * OVERLAY */ var pagePosition = 0; var overlayDisplay = false; function initOverlayBack() { if( !document.getElementById("overlay") ) { var overlayElem = document.createElement("div"); overlayElem.setAttribute("id", "overlay" ); var contentElem = document.createElement("div"); contentElem.setAttribute("id", "overlayContent" ); var contentHeader = document.createElement("div") contentHeader.className ="overlayHeader"; var transparencyElem = document.createElement("div"); transparencyElem.setAttribute("id", "overlayTransparency" ); var closeElem = document.createElement("span"); closeElem.className = "overlayClose"; var closeAnchor = document.createElement("a"); closeAnchor.onclick = hideOverlay; closeAnchor.appendChild(document.createTextNode("X")); if(overlayDisplay) overlayElem.style.display = ""; else overlayElem.style.display = "none"; try{ closeElem.appendChild(closeAnchor); contentHeader.appendChild(closeElem); contentElem.appendChild(document.createElement("div")); contentElem.appendChild(contentHeader); overlayElem.appendChild(transparencyElem); overlayElem.appendChild(contentElem); document.getElementsByTagName("body")[0].appendChild(overlayElem); }catch(ex){ alert(ex+":"+ex.message); } } } function hideOverlay() { overlayDisplay = false; var oOverLayDiv = document.getElementById("overlay"); oOverLayDiv.style.display = "none"; scroll(0,pagePosition); } function showOverlay() { overlayDisplay = true; var over = document.getElementById("overlay"); if(over) { over.style.display = ""; } pagePosition = document.body.scrollTop; scroll(0,0); } //Used to simulate maxWidth css property for IE6. This can be used for max-width properties that only need to be set once per page, lIke the Link+ logo. The property for the CSS expression will then get overwritten. function maxPixelWidth(elem, maxWidth) { if (document.all) { if (elem.offsetWidth > 0 ) { elem.style.width = elem.offsetWidth > maxWidth ? maxWidth + 'px' : elem.offsetWidth; } } }