function doSubmit(){ var f = document.forms[0]; var a = new Array(); a[a.length] = [f.LastName, 'Last Name']; a[a.length] = [f.FirstName, 'First Name']; a[a.length] = [f.Salary, 'Salary', ['number', 1, null]]; if ( validateRequiredFields( f, a ) ){ f.submit(); return true; } return; } /******************************************************** Set of Global JavaScript functions to be used troughout InSite! Jake Howlett, v1.0, 27/11/03 ********************************************************/ /*Remove leading and trailing spaces from a string Originally written by Jim Fricker */ function trim(aStr) { return aStr.replace(/^\s{1,}/, "").replace(/\s{1,}$/, "") } /* disablePassThru() Makes sure that users can't enter start or end tags for Domino PassThru HTML. Both < and > are replaced with their encoded values [< or >] */ function disablePassThru( fieldObject ) { var procString = fieldObject.value; procString = procString.replace(/\[\\]/g,'>]'); fieldObject.value = procString; } /* getPathName Required due to Opera bug where location.pathname returns location.search as well. */ function getPathName(){ var pth = location.pathname.split('?'); return pth[0]; } /*doSearch is called from the button below simple query box on all pages */ function doSearch ( query, view ) { var regExp1 = /\bfield\b/i; //used to test for reserved word field in query string var regExp2 = /[(,),<,>,\[,\]]/; //used to test for reserved char(s) in the query string var str = query.value; if ( trim(str) == "" ){ alert("Please be sure to enter something to search for."); query.focus(); return false; } else { if ( typeof regExp1.source != 'undefined' ) //supports regular expression testing if ( regExp1.test( str ) || regExp2.test( str ) ){ var alrt = "Please note that you can not include:"; alrt += "\n\nThe reserved word 'field'\nthe characters [, ], (, ), < or >"; alrt += "\n\nin your search query!\n\nIf you are confident that you know"; alrt += "\nwhat you are doing, then you can\nmanually produce the URL required." alert( alrt ); s.focus(); return false; } document.location = "/" + _db_path + "/" + view + "?SearchView&Query=" + escape( str ) + "&start=1&count=10&SearchFuzzy=True"; } } /*doSearch is called from the button on the section browse page */ function doSearchSection ( query, view, section ) { var regExp1 = /\bfield\b/i; //used to test for reserved word field in query string var regExp2 = /[(,),<,>,\[,\]]/; //used to test for reserved char(s) in the query string var str = query.value; if ( trim(str) == "" ){ alert("Please be sure to enter something to search for."); query.focus(); return false; } else { if ( typeof regExp1.source != 'undefined' ) //supports regular expression testing if ( regExp1.test( str ) || regExp2.test( str ) ){ var alrt = "Please note that you can not include:"; alrt += "\n\nThe reserved word 'field'\nthe characters [, ], (, ), < or >"; alrt += "\n\nin your search query!\n\nIf you are confident that you know"; alrt += "\nwhat you are doing, then you can\nmanually produce the URL required." alert( alrt ); s.focus(); return false; } document.location = "/" + _db_path + "/" + view + "?SearchView&Query=" + escape( str ) + " AND [Section] CONTAINS "+section+"&start=1&count=10&SearchFuzzy=True§ion="+section; } } /* getRadioSelectedValue is an easy way to get the value of the selected radio button */ function getRadioSelectedValue( obj ){ for (var r=0; r < obj.length; r++){ if ( obj[r].checked ) return obj[r].value; } } /*doEdit */ function doEdit(){ location.search="?EditDocument"; } /*doSubmit */ function doSubmit(){ document.forms[0].submit(); } /*doDelete */ function doDelete(){ if (confirm("Do you really want to delete this document?")) location.search="?DeleteDocument"; } /*disableStylesView*/ function disableStylesView(index){ document.styleSheets[index].disabled = (document.styleSheets[index].disabled)?false:true; } //#################################################################### // code from http://webfx.eae.net, some small adaptions made for numbers and first sort order and sText = sText.replace(/[\.,]/g,''); //#################################################################### function SortableTable(oTable, oSortTypes) { this.element = oTable; this.tHead = oTable.tHead; this.tBody = oTable.tBodies[0]; this.document = oTable.ownerDocument || oTable.document; this.sortColumn = null; this.descending = null; var oThis = this; this._headerOnclick = function (e) { oThis.headerOnclick(e); }; // only IE needs this var win = this.document.defaultView || this.document.parentWindow; this._onunload = function () { oThis.destroy(); }; if (win && typeof win.attachEvent != "undefined") { win.attachEvent("onunload", this._onunload); } this.initHeader(oSortTypes || []); } SortableTable.gecko = navigator.product == "Gecko"; SortableTable.msie = /msie/i.test(navigator.userAgent); // Mozilla is faster when doing the DOM manipulations on // an orphaned element. MSIE is not SortableTable.removeBeforeSort = SortableTable.gecko; SortableTable.prototype.onsort = function () {}; // adds arrow containers and events // also binds sort type to the header cells so that reordering columns does // not break the sort types SortableTable.prototype.initHeader = function (oSortTypes) { var cells = this.tHead.rows[0].cells; var l = cells.length; var img, c; for (var i = 0; i < l; i++) { c = cells[i]; img = this.document.createElement("IMG"); img.src = "arrow_up_grey.gif"; c.appendChild(img); if (oSortTypes[i] != null) { c._sortType = oSortTypes[i]; } if (typeof c.addEventListener != "undefined") c.addEventListener("click", this._headerOnclick, false); else if (typeof c.attachEvent != "undefined") c.attachEvent("onclick", this._headerOnclick); } this.updateHeaderArrows(); }; // remove arrows and events SortableTable.prototype.uninitHeader = function () { var cells = this.tHead.rows[0].cells; var l = cells.length; var c; for (var i = 0; i < l; i++) { c = cells[i]; c.removeChild(c.lastChild); if (typeof c.removeEventListener != "undefined") c.removeEventListener("click", this._headerOnclick, false); else if (typeof c.detachEvent != "undefined") c.detachEvent("onclick", this._headerOnclick); } }; SortableTable.prototype.updateHeaderArrows = function () { var cells = this.tHead.rows[0].cells; var l = cells.length; var img; for (var i = 0; i < l; i++) { img = cells[i].lastChild; if (i == this.sortColumn) img.src = (this.descending ? "arrow_dwn.gif" : "arrow_up.gif"); // img.className = "sort-arrow " + (this.descending ? "descending" : "ascending"); else // img.className = "sort-arrow"; // only show greyed out arrow for the first 5 columns (as we do not want to show it for non-sortable cols in Activity Search i.e. Details and Select) // if (i < 5) { img.src = "arrow_up_grey.gif" // } else { // img.src = "blank.gif" // } } }; SortableTable.prototype.headerOnclick = function (e) { // find TD element var el = e.target || e.srcElement; while (el.tagName != "TD") el = el.parentNode; this.sort(SortableTable.msie ? SortableTable.getCellIndex(el) : el.cellIndex); //maw NOT changed }; // IE returns wrong cellIndex when columns are hidden SortableTable.getCellIndex = function (oTd) { var cells = oTd.parentNode.childNodes var l = cells.length; var i; for (i = 0; cells[i] != oTd && i < l; i++) ; return i; }; SortableTable.prototype.getSortType = function (nColumn) { var cell = this.tHead.rows[0].cells[nColumn]; var val = cell._sortType; if (val != "") return val; return "String"; }; // only nColumn is required // if bDescending is left out the old value is taken into account // if sSortType is left out the sort type is found from the sortTypes array SortableTable.prototype.sort = function (nColumn, bDescending, sSortType) { if (sSortType == null) sSortType = this.getSortType(nColumn); // exit if None if (sSortType == "None") return; if (bDescending == null) { if (this.sortColumn != nColumn) this.descending = false; else this.descending = !this.descending; } this.sortColumn = nColumn; if (typeof this.onbeforesort == "function") this.onbeforesort(); var f = this.getSortFunction(sSortType, nColumn); var a = this.getCache(sSortType, nColumn); var tBody = this.tBody; a.sort(f); if (this.descending) a.reverse(); if (SortableTable.removeBeforeSort) { // remove from doc var nextSibling = tBody.nextSibling; var p = tBody.parentNode; p.removeChild(tBody); } // insert in the new order var l = a.length; for (var i = 0; i < l; i++) tBody.appendChild(a[i].element); if (SortableTable.removeBeforeSort) { // insert into doc p.insertBefore(tBody, nextSibling); } this.updateHeaderArrows(); this.destroyCache(a); if (typeof this.onsort == "function") this.onsort(); }; SortableTable.prototype.asyncSort = function (nColumn, bDescending, sSortType) { var oThis = this; this._asyncsort = function () { oThis.sort(nColumn, bDescending, sSortType); }; window.setTimeout(this._asyncsort, 1); }; SortableTable.prototype.getCache = function (sType, nColumn) { var rows = this.tBody.rows; var l = rows.length; var a = new Array(l); var r; for (var i = 0; i < l; i++) { r = rows[i]; a[i] = { value: this.getRowValue(r, sType, nColumn), element: r }; }; return a; }; SortableTable.prototype.destroyCache = function (oArray) { var l = oArray.length; for (var i = 0; i < l; i++) { oArray[i].value = null; oArray[i].element = null; oArray[i] = null; } } SortableTable.prototype.getRowValue = function (oRow, sType, nColumn) { var s; var c = oRow.cells[nColumn]; if (typeof c.innerText != "undefined") s = c.innerText; else s = SortableTable.getInnerText(c); return this.getValueFromString(s, sType); }; SortableTable.getInnerText = function (oNode) { var s = ""; var cs = oNode.childNodes; var l = cs.length; for (var i = 0; i < l; i++) { switch (cs[i].nodeType) { case 1: //ELEMENT_NODE s += SortableTable.getInnerText(cs[i]); break; case 3: //TEXT_NODE s += cs[i].nodeValue; break; } } return s; } SortableTable.prototype.getValueFromString = function (sText, sType) { switch (sType) { case "Number": sText = sText.replace(/[\.,]/g,''); return Number(sText); case "CaseInsensitiveString": return sText.toUpperCase(); case "Date": var parts = sText.split("-"); var d = new Date(0); d.setDate(parts[0]); d.setMonth(parts[1] - 1); d.setFullYear(parts[2]); return d.valueOf(); case "Nothing": sText = ""; return sText; } return sText; }; SortableTable.prototype.getSortFunction = function (sType, nColumn) { return function compare(n1, n2) { if (n1.value < n2.value) return -1; if (n2.value < n1.value) return 1; return 0; }; }; SortableTable.prototype.destroy = function () { this.uninitHeader(); var win = this.document.parentWindow; if (win && typeof win.detachEvent != "undefined") { // only IE needs this win.detachEvent("onunload", this._onunload); } this._onunload = null; this.element = null; this.tHead = null; this.tBody = null; this.document = null; this._headerOnclick = null; this.sortTypes = null; this._asyncsort = null; this.onsort = null; }; /********************************************************* Set of JavaScript functions used for validation Author : Jake Howlett, http://www.rockalldesign.com/ Date : 17 Dec 2003 **********************************************************/ /* validateNumber() This function checks that the value of a field is a number and, optionally within a certain range. Arguments: val = Value to be checked min = Optional minimum allowed value max = Optional maximum allowed value */ function validateNumber(val, min, max){ if ( isNaN( val ) ) return false; if ( min && val < min ) return false; if ( max && val > max ) return false; return true; } /*********************************************************** dateComponents() This function splits a date in to the day, month and year components, depending on the format supplied. Used by Date Validation routine. Arguments: obj = Input whose value is to be checked format = date format, ie mm/dd or dd/mm ************************************************************/ function dateComponents(dateStr, format) { var results = new Array(); var datePat = /^(\d{1,2})(\/|-|\.)(\d{1,2})\2(\d{2}|\d{4})$/; var matchArray = dateStr.match(datePat); if (matchArray == null) { return null; } //check for two digit (20th century) years and prepend 19. matchArray[4] = (matchArray[4].length == 2) ? '19' + matchArray[4] : matchArray[4]; // parse date into variables if (format.charAt(0)=="d"){ //what format does the server use for dates? results[0] = matchArray[1]; results[1] = matchArray[3]; } else { results[1] = matchArray[1]; results[0] = matchArray[3]; } results[2] = matchArray[4]; return results; } /*********************************************************** valiDate() This function checks that the value of a date is in the correct format and, optionally, within a certain range. Arguments: obj = Input whose value is to be checked min = Optional minimum allowed value max = Optional maximum allowed value format = date format, ie mm/dd or dd/mm ************************************************************/ function valiDate(obj, min, max, format){ dateBits = dateComponents(obj.value, format); if (dateBits == null) return false; //Check it is a valid date first day = dateBits[0]; month = dateBits[1]; year = dateBits[2]; if ((month < 1 || month > 12) || (day < 1 || day > 31)) { // check month range return false; } if ((month==4 || month==6 || month==9 || month==11) && day==31) { return false; } if (month == 2) { // check for february 29th var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); if (day>29 || (day==29 && !isleap)) { return false; } } //Now check whether a range is specified and if in bounds var theDate = new Date(dateBits[2], parseInt(dateBits[1]) - 1, dateBits[0]); if ( min ) { minBits = dateComponents (min, format); var minDate = new Date(minBits[2], parseInt(minBits[1],10) - 1, minBits[0]); if ( minDate.getTime() > theDate.getTime() ) return false; } if ( max) { maxBits = dateComponents (max, format); var maxDate = new Date(maxBits[2], parseInt(maxBits[1],10) - 1, maxBits[0]); if ( theDate.getTime() > maxDate.getTime() ) return false; } return true; } /*********************************************************** validateEmail() This function checks that the value of a field is a valid SMTP e-mail address ie x@xx.xx Arguments: obj = Input whose value is to be checked Original source: http://javascript.internet.com Author: Sandeep V. Tamhankar (stamhankar@hotmail.com) Note: Work in progress = validate SMTP OR Notes Canonical ************************************************************/ function validateEmail( obj ) { var emailStr = obj.value; var reg1 = /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/; // not valid var reg2 = /^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/; // valid if ( !reg1.test( emailStr ) && reg2.test( emailStr ) ) { return true; } else { return false; } } /*********************************************************** locateFileUpload() Returns a handle to the file upload control on a form. Used to get around the fact that there is no consistent way to refer to the element cross-browser. ***********************************************************/ function locateFileUpload( f ) { for(var i = 0; i < f.elements.length; i ++) if( f.elements[i].type=='file' ){ return f.elements[i]; } } /*********************************************************** validateFileType() This function checks that the type of file being uploaded is allowed Arguments: obj = The File Upload control. fTyp = Allowed file types ************************************************************/ function validateFileType( obj, fTyp ) { dots = obj.value.split("."); fType = "." + dots[dots.length-1]; if ( fTyp != null && fTyp.indexOf(fType) == -1 ) return false; return true; } /*********************************************************** validateFileLimit() This function checks that the value in a file upload Arguments: obj = The File Upload control cur = Current number of file attachments max = Limit on allowed files ************************************************************/ function validateFileLimit( obj, cur, max ) { if ( cur >= max ) return false; return true; } /*********************************************************** OnFailure() This function returns the failure message to the user and sets focus on the input in question. Arguments: obj = Input element on which to return focus lbl = Field Label to prepend on to the message msg = Array value for message to give the user ************************************************************/ function OnFailure( obj, lbl, msg ){ var msgs = new Array(); msgs["text"] = " is a required field. \n\nPlease enter a value."; msgs["textarea"] = " is a required field. \n\nPlease enter a value."; msgs["select-one"] = " is a required field. \n\nPlease select an entry."; msgs["select-multiple"] = " is a required field. \n\nPlease select an entry."; msgs["checkbox"] = " is a required field. \n\nPlease select an entry."; msgs["file"] = " is a required upload. \n\nPlease select a file."; msgs["fileType"] = " requires certain file types. \n\nPlease select a valid file type."; msgs["fileLimit"] = " is a limited file upload. \n\nPlease reduce number of attachment(s) first."; msgs["radio"] = " is a required field. \n\nPlease select an entry."; msgs["number"] = " is a numeric field. \n\nPlease enter a valid number."; msgs["date"] = " is a date field. \n\nPlease enter a valid date."; msgs["email"] = " is an address field. \n\nPlease enter a valid e-mail address."; if(msg[1] || msg[2]){ //upper/lower bound ranges have been specified if(msg[1] && msg[2]){//range term = ( msg[0] == "date" )? " ("+msg[3]+")" : ""; alert(lbl + msgs[msg[0]] + term + " between " + msg[1] + " and " + msg[2]); } else if (msg[1]) {//lower bound term = ( msg[0] == "number" ) ? " greater than " : " (" + msg[3] + ") after "; alert(lbl + msgs[msg[0]] + term + msg[1]); } else {//upper bound term = ( msg[0] == "number" )? " less than " : " (" + msg[3] + ") before "; alert(lbl + msgs[msg[0]] + term + msg[2]); } } else {//no range given alert(lbl + msgs[msg[0]]); } obj.focus(); return false; } /*********************************************************** isSomethingSelected() This function is passed an object of type redio group or check box. It then loops through all options and checks that one of them is selected, returning true if so. Arguments: obj = Reference to the parent object of the group. ************************************************************/ function isSomethingSelected( obj ){ for (var r=0; r < obj.length; r++){ if ( obj[r].checked ) return true; } } /*********************************************************** validateRequiredFields() This function is passed an array of fields that are required to be filled in and iterates through each ensuring they have been correctly entered. ************************************************************/ function validateRequiredFields( f, a ){ for (var i=0; i < a.length; i++){ e = a[i][0]; //checks input types: "text","select-one","select-multiple","textarea","checkbox","radio","file" switch (e.type) { case "text": if ( trim(e.value) == "" ) return OnFailure(e, a[i][1], ["text"]); if ( a[i][2] ) { switch ( a[i][2][0] ){ case "number": if ( !validateNumber(e.value, a[i][2][1], a[i][2][2]) ) return OnFailure(e, a[i][1], ["number", a[i][2][1], a[i][2][2]]); break case "date": if ( !valiDate(e, a[i][2][1], a[i][2][2], a[i][2][3]) ) return OnFailure(e, a[i][1], ["date", a[i][2][1], a[i][2][2], a[i][2][3]]); break case "email": if ( !validateEmail(e) ) return OnFailure(e, a[i][1], ["email"]); break default: break } } break case "file": //make sure AT LEAST one file gets attached if ( a[i][2][1] == 0 && trim(e.value) == "" ) return OnFailure(e, a[i][1], ["file"]); if ( trim(e.value) != "") { //check type of file that is being uploaded if ( a[i][2][0] != null && validateFileType( e, a[i][2][0] ) == false ) return OnFailure(e, a[i][1], ["fileType"]); //check that file limit has not been reached if ( a[i][2][2] != null && validateFileLimit( e, a[i][2][1], a[i][2][2] ) == false ) return OnFailure(e, a[i][1], ["fileLimit"]); } break case "textarea": if ( trim(e.value) == "" ) return OnFailure(e, a[i][1], ["textarea"]); break case "select-one": if ( e.selectedIndex == 0 ) return OnFailure(e, a[i][1], ["select-one"]); break case "select-multiple": if (e.selectedIndex == -1) return OnFailure(e, a[i][1], ["select-multiple"]); break default: //must be a checkbox or a radio group if none of above if ( !e[0]) {//handle single item group first switch (e.type) { case "checkbox": if ( !e.checked ) return OnFailure(e, a[i][1], ["checkbox"]); break case "radio": if ( !e.checked ) return OnFailure(e, a[i][1], ["radio"]); break default: break } } else { //handle multi-item groups switch (e[0].type) { case "checkbox": if ( !isSomethingSelected( e ) ) return OnFailure(e[0], a[i][1], ["checkbox"]); break case "radio": if ( !isSomethingSelected( e ) ) return OnFailure(e[0], a[i][1], ["radio"]); break default: break } } break } } return true; }