/******************************************************************************************** | | SCRIPT REACTION | browser-detector.js | | Created by : Kevin Biskaborn | Copyright (c) 2005-2015 ScriptReaction | https://www.scriptreaction.ca | |-- LATEST REVISION ------------------------------------------------------------------------- | | K. Biskaborn | |-- CLASSES REQUIRED ------------------------------------------------------------------------ | | GlobalDirector | ********************************************************************************************/ var BrowserDetector = { CONST: { // Browser Type Refs BROWSER_TYPE_REF_GECKO: "gecko", BROWSER_TYPE_REF_IE: "ie", // CSS File Info FILE_PATH_PREFIX_CSS: "/assets/css/", FILE_NAME_PREFIX_VERSION_SPECIFIC_CSS: "browser-specific-" }, settings: { // Browser Information browser_isIE: 0, // flag for Internet Explorer browser_isMobile: 0, // flag for Mobile browser_typeRef: "", // the browser type ref string browser_version: -1, // the browser version number // Version Specific Handling versionSpecificCSS_enabled: 0 }, preload: function (){ // detect the client browser BrowserDetector.detectClientBrowser(); // check if browser specific CSS is enabled if( BrowserDetector.settings.versionSpecificCSS_enabled ) // populate the version specific CSS this.populate.css(); }, //************************************************************************************************************** // begin BrowserDetector.verify verify: { isIE: function (){ return BrowserDetector.settings.browser_isIE; }, isMobile: function (){ return BrowserDetector.settings.browser_isMobile; } }, // end BrowserDetector.verify //************************************************************************************************************** detectClientBrowser: function (){ if( window.XMLHttpRequest ){ if( window.ActiveXObject ){ // IE 7 BrowserDetector.settings.browser_typeRef = BrowserDetector.CONST.BROWSER_TYPE_REF_IE; BrowserDetector.settings.browser_version = 7; } else { // Opera, Safari, Firefox BrowserDetector.settings.browser_typeRef = BrowserDetector.CONST.BROWSER_TYPE_REF_GECKO; } } else { // IE6 and below BrowserDetector.settings.browser_typeRef = BrowserDetector.CONST.BROWSER_TYPE_REF_IE; BrowserDetector.settings.browser_version = 6; } // set the Internet Explorer flag BrowserDetector.settings.browser_isIE = ( BrowserDetector.settings.browser_typeRef == BrowserDetector.CONST.BROWSER_TYPE_REF_IE ); // set the Mobile flag BrowserDetector.settings.browser_isMobile = BrowserDetector.detectMobile( navigator.userAgent||navigator.vendor||window.opera ); }, detectMobile: function ( a ){ return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)); }, //************************************************************************************************************** // begin BrowserDetector.populate populate: { css: function (){ // check if version specific CSS is enabled // AND that the browser is Internet Explorer if( BrowserDetector.settings.versionSpecificCSS_enabled && BrowserDetector.verify.isIE() ){ // INTERNET EXPLORER // get the browser type ref var browserTypeRef = BrowserDetector.CONST.BROWSER_TYPE_REF_IE; // get the version number var versionNumber = BrowserDetector.settings.browser_version; // check for all IE browsers ABOVE IE 6.0 if( versionNumber > 6 ) // attach the IE 7.0+ version specific CSS BrowserDetector.populate.css_versionSpecific( browserTypeRef, 7 ); else // IE 6.0 and below BrowserDetector.populate.css_versionSpecific( browserTypeRef, 6 ); } }, css_versionSpecific: function ( browserTypeRef, versionNumber ){ // attach the requested version specific CSS file GlobalDirector.attachAsset.cssLink( BrowserDetector.CONST.FILE_PATH_PREFIX_CSS + BrowserDetector.CONST.FILE_NAME_PREFIX_VERSION_SPECIFIC_CSS + browserTypeRef + versionNumber + ".css" ); } } // end BrowserDetector.populate //************************************************************************************************************** } /******** GLOBAL LAUNCH ********/ BrowserDetector.preload(); /******************************************************************************************** | | SCRIPT REACTION | contact-form-manager.js | | Created by : Kevin Biskaborn | Copyright (c) 2005-2015 ScriptReaction | https://www.scriptreaction.ca | |-- LATEST REVISION ------------------------------------------------------------------------- | | K. Biskaborn | |-- CLASSES REQUIRED ------------------------------------------------------------------------ | | BrowserDetector | ElementAccessor | ElementClassUtility | LivePage | StringUtility | ********************************************************************************************/ var ContactFormManager = { CONST: { ARRAY_OF_FIELD_OBJECTS: [ { ref: "contact-name", label: "Name" }, { ref: "contact-email", label: "E-mail" }, { ref: "contact-phone", label: "Phone" }, { ref: "contact-website", label: "Web Site" }, { ref: "contact-message", label: "What can we help you with?", isTextArea: 1 } ], CLASS_NAME_FIELD_ERROR: "field-has-error", ELEMENT_ID_PREFIX_FIELD_WRAPPER: "field-wrapper-", ELEMENT_ID_PREFIX_LABEL: "label-", ELEMENT_ID_SUBMIT_BTN: "contact-form-btn", FORM_ID: "contact-data-form" }, settings: { isValid_email: 0, isValid_message: 0, isValid_name: 0, isValid_phone: 0, isValidating: 0 }, launch: function (){ // create loop containers var fieldObject; var ref, label, isTextArea; var inputElement, wrapElement; var labelId, labelElement; // cycle through all field objects for( var i = 0; i < ContactFormManager.CONST.ARRAY_OF_FIELD_OBJECTS.length; ++i ){ // get the next field object fieldObject = ContactFormManager.CONST.ARRAY_OF_FIELD_OBJECTS[ i ]; // extract field properties isTextArea = ( typeof( fieldObject.isTextArea ) == "undefined" ) ? 0 : 1; label = fieldObject.label; ref = fieldObject.ref; // get the field wrapper and input elements inputElement = ElementAccessor.get( ref ); wrapElement = $( "#" + ContactFormManager.CONST.ELEMENT_ID_PREFIX_FIELD_WRAPPER + ref ); // specify the ID to use for the label labelId = ContactFormManager.CONST.ELEMENT_ID_PREFIX_LABEL + ref; // add the place holder label to each field wrapElement.append( "
" + label + "
" ); // get the newly created label element labelElement = ContactFormManager.get.labelElementByRef( ref ); // ------------------------------------------------------------- // check for TEXT AREAS if( isTextArea ){ // if the value of the text area matches the field label, // then the value of the text area can be safely cleared if( inputElement.value.toUpperCase() == label.toUpperCase() ) inputElement.value = ""; } else // assume TEXT LINE // clear the original place holder inputElement.placeholder = ""; // ------------------------------------------------------------- // add action handlers to each INPUT ELEMENT // ON BLUR inputElement.onblur = function (){ ContactFormManager.actions.fieldOnBlur( this.id ); } // ON CLICK inputElement.onclick = function (){ ContactFormManager.actions.fieldOnClick( this.id ); } // ON FOCUS inputElement.onfocus = function (){ ContactFormManager.actions.fieldOnFocus( this.id ); } // ON INPUT inputElement.oninput = function (){ ContactFormManager.actions.fieldOnInput( this.id ); } // ON KEY UP inputElement.onkeyup = function (){ ContactFormManager.actions.fieldOnInput( this.id ); } // ------------------------------------------------------------- // add action handlers to each LABEL // ON CLICK labelElement.onclick = function (){ ContactFormManager.actions.labelOnClick( this.id ); } // ------------------------------------------------------------- // check if the LIVE VALUE of the field is already different from the label // IMPORTANT: the live value CANNOT be empty // ie: following a form submission and page re-load // get the live value var liveValue = ContactFormManager.get.inputElementLiveValueByRef( ref ).toUpperCase(); // perform the check if( !( liveValue == "" ) && !( liveValue == label.toUpperCase() ) ) // hide the label ContactFormManager.actions.hideLabel( ref ); } // get the form }, get: { inputElementByRef: function ( fieldRef ){ return ElementAccessor.get( fieldRef ); }, inputElementLabelByRef: function ( fieldRef ){ var label = ""; // create loop containers var fieldObject; // cycle through all field objects // until all have been iterated or until a label is found for( var i = 0; i < ContactFormManager.CONST.ARRAY_OF_FIELD_OBJECTS.length && label == ""; ++i ){ // get the next field object fieldObject = ContactFormManager.CONST.ARRAY_OF_FIELD_OBJECTS[ i ]; // check for the requested field if( fieldObject.ref == fieldRef ) // set output value label = fieldObject.label; } return label; }, inputElementLiveValueByRef: function ( fieldRef ){ return ContactFormManager.get.inputElementByRef( fieldRef ).value; }, labelElementByRef: function ( fieldRef ){ return ContactFormManager.get.wrapElementByRef( fieldRef ).getElementsByTagName( "div" )[ 0 ]; }, liveValue_email: function (){ return ContactFormManager.get.inputElementLiveValueByRef( "contact-email" ); }, liveValue_message: function (){ return ContactFormManager.get.inputElementLiveValueByRef( "contact-message" ); }, liveValue_name: function (){ return ContactFormManager.get.inputElementLiveValueByRef( "contact-name" ); }, liveValue_phone: function (){ return ContactFormManager.get.inputElementLiveValueByRef( "contact-phone" ); }, liveValue_website: function (){ return ContactFormManager.get.inputElementLiveValueByRef( "contact-website" ); }, wrapElement_email: function (){ return ContactFormManager.get.wrapElementByRef( "contact-email" ); }, wrapElement_message: function (){ return ContactFormManager.get.wrapElementByRef( "contact-message" ); }, wrapElement_name: function (){ return ContactFormManager.get.wrapElementByRef( "contact-name" ); }, wrapElement_phone: function (){ return ContactFormManager.get.wrapElementByRef( "contact-phone" ); }, wrapElementByRef: function ( fieldRef ){ return ElementAccessor.get( ContactFormManager.get.wrapElementId( fieldRef ) ); }, wrapElementId: function ( fieldRef ){ return ContactFormManager.CONST.ELEMENT_ID_PREFIX_FIELD_WRAPPER + fieldRef; } }, set: { inputElementLiveValueByRef: function ( fieldRef, str ){ return ContactFormManager.get.inputElementByRef( fieldRef ).value = str; }, liveValue_email: function ( str ){ return ContactFormManager.set.inputElementLiveValueByRef( "contact-email", str ); }, liveValue_message: function ( str ){ return ContactFormManager.set.inputElementLiveValueByRef( "contact-message", str ); }, liveValue_name: function ( str ){ return ContactFormManager.set.inputElementLiveValueByRef( "contact-name", str ); }, liveValue_phone: function ( str ){ return ContactFormManager.set.inputElementLiveValueByRef( "contact-phone", str ); }, liveValue_website: function ( str ){ return ContactFormManager.set.inputElementLiveValueByRef( "contact-website", str ); } }, actions: { fieldOnBlur: function ( fieldRef ){ // when the field is blurred, determine if the label should be reshown // get the LIVE value of the field var liveValue = ContactFormManager.get.inputElementLiveValueByRef( fieldRef ).toUpperCase(); // check if the live value is EMPTY or EQUAL to the initial label value if( liveValue == "" || liveValue == ContactFormManager.get.inputElementLabelByRef( fieldRef ).toUpperCase() ){ // live value is empty or MATCHS the initial label value // clear the live value ContactFormManager.set.inputElementLiveValueByRef( fieldRef, '' ); // show the label ContactFormManager.actions.showLabel( fieldRef ); } }, fieldOnClick: function ( fieldRef ){ // re-direct click to onFocus handler ContactFormManager.actions.fieldOnFocus( fieldRef ); }, fieldOnFocus: function ( fieldRef ){ // BROWSER-SPECIFIC // On the HOME PAGE on MOBILE DEVICES, pause all jQuery animations // to release addition memory: if( LivePage.verify.isHome() && BrowserDetector.verify.isMobile() ){ // pause the splash projects $( "#splash-slider .project-square-holder" ).slickPause(); } }, fieldOnInput: function ( fieldRef ){ // when input is given to the field, determine if the label should be hidden // get the LIVE value of the field var liveValue = ContactFormManager.get.inputElementLiveValueByRef( fieldRef ).toUpperCase(); // check if the live value is EMPTY or EQUAL to the initial label value if( liveValue == "" || liveValue == ContactFormManager.get.inputElementLabelByRef( fieldRef ).toUpperCase() ) // no user input, show the label ContactFormManager.actions.showLabel( fieldRef ); else { // user input exists, hide the label ContactFormManager.actions.hideLabel( fieldRef ); // remove the field error class when input is given ContactFormManager.process.removeErrorClassFromField( fieldRef ); } }, hideLabel: function ( fieldRef ){ // update label visibility ContactFormManager.actions.updateLabelVisibility( fieldRef, 0 ); }, labelOnClick: function ( labelId ){ // extract the field ref from the incoming ID var fieldRef = StringUtility.remove.prefix( labelId, ContactFormManager.CONST.ELEMENT_ID_PREFIX_LABEL ); // focus the input field ContactFormManager.get.inputElementByRef( fieldRef ).focus(); }, showLabel: function ( fieldRef ){ // update label visibility ContactFormManager.actions.updateLabelVisibility( fieldRef, 1 ); }, updateLabelVisibility: function ( fieldRef, isVisible ){ // update the hidden style on the label ElementClassUtility.process.addOrRemoveClassUsingFlag( ContactFormManager.get.labelElementByRef( fieldRef ), "is-hidden", !isVisible ); } }, process: { removeAllErrorClasses: function (){ // create loop containers var fieldObject; // cycle through all field objects for( var i = 0; i < ContactFormManager.CONST.ARRAY_OF_FIELD_OBJECTS.length; ++i ){ // get the next field object fieldObject = ContactFormManager.CONST.ARRAY_OF_FIELD_OBJECTS[ i ]; // remove the error class from the field ContactFormManager.process.removeErrorClassFromField( fieldObject.ref ); } }, removeErrorClassFromField: function ( fieldRef ){ // get the field wrapper var wrapElement = ContactFormManager.get.wrapElementByRef( fieldRef ); // remove the error class name from the element ElementClassUtility.removeClass.fromElement( wrapElement, ContactFormManager.CONST.CLASS_NAME_FIELD_ERROR ); } }, processSubmit: function (){ // verify that the form is not already validating if( !ContactFormManager.settings.isValidating ){ // check if the form is VALID if( ContactFormManager.validate() ){ // run re-captcha grecaptcha.execute(); } else { // form is invalid // create a visible delay before calling post validation window.setTimeout( ContactFormManager.updatePostValidationErrors, 500 ); window.setTimeout( ContactFormManager.endValidation, 1200 ); } } }, executeSubmit: function (){ // submit the form document[ ContactFormManager.CONST.FORM_ID ].submit(); }, validate: function (){ // raise the is validating flag ContactFormManager.settings.isValidating = 1; // add the PROCESSING state to the form btn ElementClassUtility.addClass.toElement_byId( ContactFormManager.CONST.ELEMENT_ID_SUBMIT_BTN, "is-processing" ); // remove any previous error classes ContactFormManager.process.removeAllErrorClasses(); // get formatted live values var liveValue_email = StringUtility.trim.whitespace.bothEnds( ContactFormManager.get.liveValue_email() ); var liveValue_message = StringUtility.trim.whitespace.bothEnds( ContactFormManager.get.liveValue_message() ); var liveValue_name = StringUtility.trim.whitespace.bothEnds( ContactFormManager.get.liveValue_name() ); var liveValue_phone = StringUtility.trim.whitespace.bothEnds( ContactFormManager.get.liveValue_phone() ); var liveValue_website = StringUtility.trim.whitespace.bothEnds( ContactFormManager.get.liveValue_website() ); // validate each field ContactFormManager.settings.isValid_email = ( !( liveValue_email == "" ) && StringUtility.verify.isValidEmail( liveValue_email ) ); ContactFormManager.settings.isValid_message = ( liveValue_message.length >= 8 ); ContactFormManager.settings.isValid_name = ( liveValue_name.length >= 2 ); ContactFormManager.settings.isValid_phone = ( liveValue_phone.length >= 10 ); // re-apply the formatted live values ContactFormManager.get.liveValue_email( liveValue_email ); ContactFormManager.get.liveValue_message( liveValue_message ); ContactFormManager.get.liveValue_name( liveValue_name ); ContactFormManager.get.liveValue_phone( liveValue_phone ); ContactFormManager.get.liveValue_website( liveValue_website ); // return a boolean for if the entire form is valid return ( ContactFormManager.settings.isValid_email && ContactFormManager.settings.isValid_message && ContactFormManager.settings.isValid_name && ContactFormManager.settings.isValid_phone ); }, updatePostValidationErrors: function (){ // update error classes // EMAIL ElementClassUtility.process.addOrRemoveClassUsingFlag( ContactFormManager.get.wrapElement_email(), ContactFormManager.CONST.CLASS_NAME_FIELD_ERROR, !ContactFormManager.settings.isValid_email ); // MESSAGE ElementClassUtility.process.addOrRemoveClassUsingFlag( ContactFormManager.get.wrapElement_message(), ContactFormManager.CONST.CLASS_NAME_FIELD_ERROR, !ContactFormManager.settings.isValid_message ); // NAME ElementClassUtility.process.addOrRemoveClassUsingFlag( ContactFormManager.get.wrapElement_name(), ContactFormManager.CONST.CLASS_NAME_FIELD_ERROR, !ContactFormManager.settings.isValid_name ); // PHONE ElementClassUtility.process.addOrRemoveClassUsingFlag( ContactFormManager.get.wrapElement_phone(), ContactFormManager.CONST.CLASS_NAME_FIELD_ERROR, !ContactFormManager.settings.isValid_phone ); }, endValidation: function (){ // lower the is validating flag ContactFormManager.settings.isValidating = 0; // remove the PROCESSING state ElementClassUtility.removeClass.fromElement_byId( ContactFormManager.CONST.ELEMENT_ID_SUBMIT_BTN, "is-processing" ); } } /******************************************************************************************** | | ElementAccessor | SCRIPT REACTION LIBRARY | | Created by : Kevin Biskaborn | Copyright (c) 2005-2015 ScriptReaction Ltd. All Rights Reserved. | https://www.scriptreaction.ca | |-- LATEST REVISION ------------------------------------------------------------------------- | | K. Biskaborn | |-- CLASSES REQUIRED ------------------------------------------------------------------------ | | ElementClassUtility | |-- HISTORY --------------------------------------------------------------------------------- | | NOV.07.2012 : Nested tags group created. | MAY.01.2011 : Class created. | ********************************************************************************************/ var ElementAccessor = { CONST: { // AA Standard Constant Collection (v1) ELEMENT_COUNT_ONE: 1, ELEMENT_COUNT_ZERO: 0, FLAG_VALUE_TRUE: 1, FLAG_VALUE_FALSE: 0, INDEX_FIRST_ELEMENT: 0, INDEX_SECOND_ELEMENT: 1, INVALID_ID: -1, INVALID_INDEX: -1, INVALID_OBJECT: null }, //************************************************************************************************************** // begin ElementAccessor.verify verify: { // verify if an element with the requested id exists elementExistsById: function ( elementId ){ return ( !( elementId == "" ) && !( ElementAccessor.get( elementId ) == null ) ); } }, // end ElementAccessor.verify //************************************************************************************************************** // gets the element on the page with the requested id get: function ( elementId ){ return document.getElementById( elementId ); }, //************************************************************************************************************** // begin ElementAccessor.getArrayOfElements getArrayOfElements: { byTagClass: function ( elementTagName, classNameString ){ // create the output container var arrayOfElements = []; // get all elements with the requested tag name var arrayOfTagElements = ElementAccessor.getArrayOfElements.byTagName( elementTagName ); // create loop containers var element; // cycle through all of the tag elements for( var i in arrayOfTagElements ){ // get the next element element = arrayOfTagElements[ i ]; // test if the element is using the requested class if( ElementClassUtility.verify.classExistsOnElement( element, classNameString ) ) // add the element to the output array arrayOfElements.push( element ); } return arrayOfElements; }, // gets an array of all elements on the page with the requested tag name byTagName: function ( tagName ){ return document.getElementsByTagName( tagName ); }, // gets ALL elements in a series // running from the specified starting number to the ending number inSeries: function ( elementIdPrefix, startNum, endNum ){ // create the output container var arrayOfElements = []; // cycle through the requested series for( var i = startNum; i <= endNum; ++i ) arrayOfElements.push( ElementAccessor.get( elementIdPrefix + i ) ); return arrayOfElements; }, // gets ALL elements in a series // running from element ZERO to element TOTAL - 1 inSeries_fromElementZero: function ( elementIdPrefix, elementTotal ){ // verify that the number of elements is valid return ( elementTotal > ElementAccessor.CONST.ELEMENT_COUNT_ZERO ) // return the series of elements ? ElementAccessor.getArrayOfElements.inSeries( elementIdPrefix, ElementAccessor.CONST.INDEX_FIRST_ELEMENT, elementTotal - ElementAccessor.CONST.ELEMENT_COUNT_ONE ) // return an empty array : []; } }, // end ElementAccessor.getArrayOfElements //************************************************************************************************************** //************************************************************************************************************** // begin ElementAccessor.getNestedTag getNestedTag: { // get the tag with the requested index inside the specified element byIndex: function ( element, tagName, tagIndex ){ return ( element == null ) ? null : element.getElementsByTagName( tagName )[ tagIndex ]; }, byIndex_anchor: function ( element, tagIndex ){ return ElementAccessor.getNestedTag.byIndex( element, "a", tagIndex ); }, byIndex_div: function ( element, tagIndex ){ return ElementAccessor.getNestedTag.byIndex( element, "div", tagIndex ); }, byIndex_table: function ( element, tagIndex ){ return ElementAccessor.getNestedTag.byIndex( element, "table", tagIndex ); }, byPosition: { first: { // gets the FIRST link ANCHOR tag inside the requested element tag_anchor: function ( element ){ return ElementAccessor.getNestedTag.byIndex_anchor( element, ElementAccessor.CONST.INDEX_FIRST_ELEMENT ); }, tag_div: function ( element ){ return ElementAccessor.getNestedTag.byIndex_div( element, ElementAccessor.CONST.INDEX_FIRST_ELEMENT ); }, tag_table: function ( element ){ return ElementAccessor.getNestedTag.byIndex_table( element, ElementAccessor.CONST.INDEX_FIRST_ELEMENT ); } } } } // end ElementAccessor.getNestedTag //************************************************************************************************************** } /******************************************************************************************** | | SCRIPT REACTION | email-embedder.js | | Created by : Kevin Biskaborn | Copyright (c) 2005-2015 ScriptReaction | https://www.scriptreaction.ca | |-- LATEST REVISION ------------------------------------------------------------------------- | | K. Biskaborn | |-- CLASSES REQUIRED ------------------------------------------------------------------------ | | ElementAccessor | ElementPropUtility | StringUtility | ********************************************************************************************/ var EmailEmbedder = { CONST: { ELEMENT_ID_PREFIX_CONTAINER: "email-embed-", ENCRYPTION_LENGTH: 3 }, register: function ( id ){ // get the container element var element = ElementAccessor.get( EmailEmbedder.CONST.ELEMENT_ID_PREFIX_CONTAINER + id ); // get the raw email address (encrypted) var rawEmail = ElementPropUtility.get.innerContent.by_element( element ); // remove HTML tags and reverse the string rawEmail = StringUtility.process.reverseString( StringUtility.strip.htmlTags( rawEmail ) ); // split the email on the AT symbol var arrayOfPieces = rawEmail.split( "@" ); // get the email pieces from the array var userString = arrayOfPieces[ 0 ]; var domainString = arrayOfPieces[ 1 ]; // re-build the real email var realEmail = StringUtility.trim.nchars.right( userString, EmailEmbedder.CONST.ENCRYPTION_LENGTH ) + "@" + StringUtility.trim.nchars.left( domainString, EmailEmbedder.CONST.ENCRYPTION_LENGTH ); // replace the contents of the container ElementPropUtility.set.innerContent.by_element( element, "" + realEmail + "" ); // update the CSS text direction on the container element.style.direction = "ltr"; } } /******************************************************************************************** | | SCRIPT REACTION | global-director.js | | Created by : Kevin Biskaborn | Copyright (c) 2005-2015 ScriptReaction | https://www.scriptreaction.ca | |-- LATEST REVISION ------------------------------------------------------------------------- | | K. Biskaborn | |-- CLASSES REQUIRED ------------------------------------------------------------------------ | | BrowserDetector | ********************************************************************************************/ var GlobalDirector = { settings: { clearImageAltParamsOnLaunch: 1 // Flag for if the "alt" parameter of image tags // should be cleared / emptied upon the launch of this class. // This disables the "title" pop-up when an image is hovered over. }, preload: function (){ GlobalDirector.addEvent( window, "load", GlobalDirector.postload ); }, postload: function (){ GlobalDirector.process.injectAnimatedAnchorScrolling(); GlobalDirector.process.formatPageImages(); }, //************************************************************************************************************** // begin GlobalDirector.verify verify: { exists: function ( object ){ return !( typeof( object ) == "undefined" ); } }, // end GlobalDirector.verify //************************************************************************************************************** addEvent: function ( object, eventType, functionName ){ if( object.addEventListener ){ object.addEventListener( eventType, functionName, false ); return true; } else if( object.attachEvent ) return object.attachEvent( "on" + eventType, functionName ); else return false; }, //************************************************************************************************************** // begin GlobalDirector.attachAsset attachAsset: { cssLink: function ( filePath ){ output = ""; output += ""; GlobalDirector.attachAsset.toDoc( output ); }, jsLink: function ( filePath ){ output = ""; output += ""; GlobalDirector.attachAsset.toDoc( output ); }, toDoc: function ( content ){ document.writeln( content ); } }, // end GlobalDirector.attachAsset //************************************************************************************************************** //************************************************************************************************************** // begin GlobalDirector.process process: { formatPageImages: function (){ // verify that the detected brower is Internet Explorer if( GlobalDirector.verify.exists( BrowserDetector ) && BrowserDetector.verify.isIE() ){ // get the array of all page images var arrayOfPageImages = document.images; // create loop containers var imgElement; // ----------------------------------------------------------------- // cycle through all images on the page for( var i = 0; i < arrayOfPageImages.length; i++ ){ // get the next image element imgElement = arrayOfPageImages[ i ]; // disable the galleryimg property imgElement.galleryimg = "no"; // check if alt params should be cleared if( GlobalDirector.settings.clearImageAltParamsOnLaunch ) // clear the alt param of the image imgElement.alt = ""; } } }, injectAnimatedAnchorScrolling: function (){ // this function requires jQuery $(function() { $('a[href*=#]:not([href=#])').click(function() { // verify the anchor is on the same page if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) { var target = $(this.hash); target = target.length ? target : $('[name=' + this.hash.slice(1) +']'); if (target.length) { $('html,body').animate({ scrollTop: target.offset().top }, 500); return false; } } }); }); }, scrollToPageTop: function (){ var y1 = y2 = y3 = 0; if( document.documentElement ) y1 = document.documentElement.scrollTop || 0; if( document.body ) y2 = document.body.scrollTop || 0; y3 = window.scrollY || 0; var y = Math.max( y1, Math.max( y2, y3 ) ); window.scrollTo( 0, Math.floor( y / 1.4 ) ); if( y > 0 ) window.setTimeout( "GlobalDirector.process.scrollToPageTop()", 25 ); } } // end GlobalDirector.process //************************************************************************************************************** } // ----------------------------------------------------------------- // Class preload actions GlobalDirector.preload(); /******************************************************************************************** | | SCRIPT REACTION | live-page.js | | Created by : Kevin Biskaborn | Copyright (c) 2005-2015 ScriptReaction | https://www.scriptreaction.ca | |-- LATEST REVISION ------------------------------------------------------------------------- | | K. Biskaborn | |-- CLASSES REQUIRED ------------------------------------------------------------------------ | | ********************************************************************************************/ var LivePage = { CONST: { PAGE_REF_HOME: "home" }, settings: { isHome: 0, ref: "" }, launch: function ( ref ){ // save the live page ref LivePage.settings.ref = ref; // set flags LivePage.settings.isHome = ( ref == LivePage.CONST.PAGE_REF_HOME ); }, //************************************************************************************************************** // begin LivePage.verify verify: { isHome: function (){ return LivePage.settings.isHome; } }, // end LivePage.verify //************************************************************************************************************** } /******************************************************************************************** | | SCRIPT REACTION | software-downloader.js | | Created by : Kevin Biskaborn | Copyright (c) 2005-2015 ScriptReaction | https://www.scriptreaction.ca | |-- LATEST REVISION ------------------------------------------------------------------------- | | K. Biskaborn | |-- CLASSES REQUIRED ------------------------------------------------------------------------ | | ********************************************************************************************/ var SoftwareDownloader = { ask: function ( packageName, versionCode ){ var msg = "ScriptReaction.ca\n"; msg += "Software Download: " + packageName + " v" + versionCode + "\n\n\n"; msg += "TERMS OF DOWNLOAD:\n\n"; msg += "You agree that this program is provided as-is, without warranty of any kind"; msg += " (either express or implied) including, without limitation, any implied warranty"; msg += " of merchantability and fitness for a particular purpose, and any warranty of non infringement."; msg += " In no event shall ScriptReaction Ltd., or anyone involved with this software, be liable for any direct,"; msg += " indirect, incidental, special, exemplary, or consequential damages (including, but not limited to,"; msg += " procurement of substitute goods or services; loss of use, data, or profits; or business interruption)"; msg += " however caused and on any theory of liability, whether in contract, strict liability, or tort"; msg += " (including negligence or otherwise) arising in any way out of the use of the program, even if"; msg += " advised of the possibility of such damage."; msg += "\n\n\nBy clicking OK, you accept these terms of download.\n"; return confirm( msg ); }, request: function ( packageRef ){ // create package containers var fileExt = ""; var fileName = ""; var filePath = ""; var packageName = ""; var versionCode = ""; // populate package properties switch( packageRef ) { case "fleet-timer-sailing-regatta-sequence": packageName = "Fleet Timer"; fileName = "fleet-timer"; fileExt = "zip"; versionCode = "1.2"; break; case "month-maker-calendars": packageName = "monthMAKER"; fileName = "month-maker"; fileExt = "exe"; versionCode = "1.0.1"; break; case "regatta-data-sailing-results": packageName = "regattaDATA"; fileName = "regatta-data"; fileExt = "zip"; versionCode = "1.3"; break; } // prompt the user if( SoftwareDownloader.ask( packageName, versionCode ) ) // proceed with download SoftwareDownloader.execute( packageRef + "/" + fileName + "-v" + versionCode + "-script-reaction." + fileExt ); }, execute: function ( filePath ){ location.href = filePath; } } /******************************************************************************************** | | ArrayUtility | SCRIPT REACTION LIBRARY | | Created by : Kevin Biskaborn | Copyright (c) 2005-2015 ScriptReaction Ltd. All Rights Reserved. | https://www.scriptreaction.ca | |-- LATEST REVISION ------------------------------------------------------------------------- | | K. Biskaborn | |-- CLASSES REQUIRED ------------------------------------------------------------------------ | | NumberUtility | |-- HISTORY --------------------------------------------------------------------------------- | | OCT.22.2013 : Class reorganized. Search sorted ascending integer array function added. | SEP.18.2012 : ArrayToString{} collection created. | MAY.01.2011 : Class created. | ********************************************************************************************/ var ArrayUtility = { CONST: { // AA Standard Constant Collection (v1) ELEMENT_COUNT_ONE: 1, ELEMENT_COUNT_ZERO: 0, FLAG_VALUE_TRUE: 1, FLAG_VALUE_FALSE: 0, INDEX_FIRST_ELEMENT: 0, INDEX_SECOND_ELEMENT: 1, INVALID_ID: -1, INVALID_INDEX: -1, INVALID_OBJECT: null }, //************************************************************************************************************** // begin ArrayUtility.verify verify: { //>> //-> FUNCTION NAME >> ArrayUtility.verify.arrayIsEmpty //-> DESCRIPTION >> Checks if an array is empty (contains zero elements) //-> PARAMETERS >> inputArray [Array]: the array to check if empty //-> RETURN >> [Boolean]: true if the array is empty; false otherwise //<< arrayIsEmpty: function ( inputArray ){ return ( inputArray.length == ArrayUtility.CONST.ELEMENT_COUNT_ZERO ); }, itemExistsInArray: function ( needle, haystackArray ){ // create an existence flag var itemExists = ArrayUtility.CONST.FLAG_VALUE_FALSE; // ----------------------------------------------------------------- // cycle through all array items for( var i = 0; i < haystackArray.length && !itemExists; ++i ){ // check for a match if( haystackArray[ i ] == needle ) // raise the existence flag // this will exit the loop itemExists = ArrayUtility.CONST.FLAG_VALUE_TRUE; } return itemExists; }, //>> //-> FUNCTION NAME >> ArrayUtility.verify.itemExistsInSortedAlphabeticalStringArray //-> DESCRIPTION >> Checks an array of strings ALREADY SORTED in ascending order // for the requested string value //-> PARAMETERS >> stringNeedle [string]: the string value to search for // >> haystackArray [Array]: the array of strings sorted in ascending order //-> RETURN >> [Boolean]: true if the search value is found; false otherwise //<< itemExistsInSortedAlphabeticalStringArray: function ( stringNeedle, haystackArray ){ // create an existence flag var itemExists = false; // create a continue search flag var continueSearch = true; // create loop containers var stringValue; // ----------------------------------------------------------------- // cycle through all array items for( var i = 0; i < haystackArray.length && !itemExists && continueSearch; ++i ){ // get the next string value stringValue = haystackArray[ i ]; // check for a match if( stringValue == stringNeedle ) // raise the existence flag itemExists = true; // check if the value is larger than the needle else if( stringValue > stringNeedle ) // stop searching // since the array is sorted, the value cannot exist continueSearch = false; } return itemExists; }, //>> //-> FUNCTION NAME >> ArrayUtility.verify.itemExistsInSortedAscendingIntegerArray //-> DESCRIPTION >> Checks an array of integers ALREADY SORTED in ascending order // for the requested integer value //-> PARAMETERS >> intNeedle [int]: the integer value to search for // >> haystackArray [Array]: the array of integers sorted in ascending order //-> RETURN >> [Boolean]: true if the search value is found; false otherwise //<< itemExistsInSortedAscendingIntegerArray: function ( intNeedle, haystackArray ){ // create an existence flag var itemExists = false; // create a continue search flag var continueSearch = true; // create loop containers var intValue; // ----------------------------------------------------------------- // cycle through all array items for( var i = 0; i < haystackArray.length && !itemExists && continueSearch; ++i ){ // get the next int value intValue = haystackArray[ i ]; // check for a match if( intValue == intNeedle ) // raise the existence flag itemExists = true; // check if the value is larger than the needle else if( intValue > intNeedle ) // stop searching // since the array is sorted, the value cannot exist continueSearch = false; } return itemExists; } }, // end ArrayUtility.verify //************************************************************************************************************** //************************************************************************************************************** // begin ArrayUtility.get get: { //>> //-> FUNCTION NAME >> ArrayUtility.get.itemIndexInArray //-> DESCRIPTION >> Gets the index of the requested element within the submitted array //-> PARAMETERS >> needle [value]: the value to get the index of // >> haystackArray [Array]: the array of elements to search //-> RETURN >> [int]: the index if the needle value is found; -1 otherwise //<< itemIndexInArray: function ( needle, haystackArray ){ // output an invalid index by default var index = ArrayUtility.CONST.INVALID_INDEX; // ----------------------------------------------------------------- // cycle through all array items until all have been checked // OR until a match has been found for( var i = 0; i < haystackArray.length && index == ArrayUtility.CONST.INVALID_INDEX; ++i ){ // check for a match if( haystackArray[ i ] == needle ){ // save the matching index // this will exit the loop index = i; } } return index; } }, // end ArrayUtility.get //************************************************************************************************************** //************************************************************************************************************** // begin ArrayUtility.arrayToString arrayToString: { //>> //-> FUNCTION NAME >> ArrayUtility.arrayToString.stringDelimited //-> DESCRIPTION >> Returns the elements of an array as a string separated // by the requested string delimiter //-> PARAMETERS >> btnElementId [String]: the HTML element id of the btn //-> RETURN >> None //<< stringDelimited: function ( inputArray, delimitString ){ return inputArray.join( delimitString ); }, commaDelimited: function ( inputArray ){ return ArrayUtility.arrayToString.stringDelimited( inputArray, "," ); } }, // end ArrayUtility.arrayToString //************************************************************************************************************** //************************************************************************************************************** // begin ArrayUtility.process process: { //>> //-> FUNCTION NAME >> ArrayUtility.process.addUniqueItem //-> DESCRIPTION >> Adds an item to the requested array ONLY if the // item does not already exist in the array //-> PARAMETERS >> itemToAdd [Generic]: the element to add // >> haystackArray [Array]: the array to add the element to //-> RETURN >> [Array]: the array containing one copy of the unique item //<< addUniqueItem: function ( itemToAdd, haystackArray ){ // verify that the element does not already exist if( !ArrayUtility.verify.itemExistsInArray( itemToAdd, haystackArray ) ) // the item does NOT exist in the array haystackArray.push( itemToAdd ); return haystackArray; }, // deletes all items in an array clearArray: function ( inputArray ){ // delete all items from the requested array return inputArray.splice( ArrayUtility.CONST.INDEX_FIRST_ELEMENT, inputArray.length ); }, copyArray: function ( inputArray ){ // create a PASS-BY-VALUE COPY of the input array // this is a complete new array copy of the original // with no reference to the original array return inputArray.slice( ArrayUtility.CONST.INDEX_FIRST_ELEMENT ); }, mergeArrays: function ( inputArray_A, inputArray_B ){ // merges two arrays into one return inputArray_A.concat( inputArray_B ); }, // removes an item from an array (if the item exists) removeItem: function ( itemToRemove, haystackArray ){ // cycle through all items in the array for( var i = 0; i < haystackArray.length; ++i ){ // check for a match if( haystackArray[ i ] == itemToRemove ){ // delete the item haystackArray.splice( i, ArrayUtility.CONST.ELEMENT_COUNT_ONE ); // exit the loop break; } } return haystackArray; } }, // end ArrayUtility.process //************************************************************************************************************** //************************************************************************************************************** // begin ArrayUtility.reorder reorder: { applySort: { integerAscending: function ( inputArray ){ // integer ascending sort: 0, 2, 5, 10, 12 return inputArray.sort( function( a ,b ){ return a - b } ); } }, // reverses the order of all items in an array reverseArray: function ( inputArray ){ return inputArray.reverse(); }, // shuffles the order of all array elements shuffle: function ( inputArray ){ var output = []; var index; // continue extracting items while the array has more to give while( inputArray.length > ArrayUtility.CONST.ELEMENT_COUNT_ZERO ){ // get the next index to be extracted index = NumberUtility.generateRandom.fromZero( inputArray.length ); // add the element at that index to the output output.push( inputArray[ index ] ); // remove the element from the array inputArray.splice( index, ArrayUtility.CONST.ELEMENT_COUNT_ONE ); } return output; } }, // end ArrayUtility.reorder //************************************************************************************************************** //************************************************************************************************************** // begin ArrayUtility.strip strip: { // removes the last element from the array (if it is empty) lastElement_ifEmpty: function ( inputArray ){ // get the last index in the array var lastIndex = inputArray.length - ArrayUtility.CONST.ELEMENT_COUNT_ONE; // get the last element in the array var lastElement = inputArray[ lastIndex ]; // determine if the element is empty if( lastElement == "" || lastElement == null ) // remove the last element inputArray.splice( lastIndex, ArrayUtility.CONST.ELEMENT_COUNT_ONE ); return inputArray; } } // end ArrayUtility.strip //************************************************************************************************************** } /******************************************************************************************** | | ElementClassUtility | SCRIPT REACTION LIBRARY | | Created by : Kevin Biskaborn | Copyright (c) 2005-2015 ScriptReaction Ltd. All Rights Reserved. | https://www.scriptreaction.ca | |-- LATEST REVISION ------------------------------------------------------------------------- | | K. Biskaborn | |-- CLASSES REQUIRED ------------------------------------------------------------------------ | | ArrayUtility | ElementAccessor | |-- HISTORY --------------------------------------------------------------------------------- | | OCT.22.2013 : Class reorganized. | APR.13.2012 : Add / remove functions by ID added. | MAY.01.2011 : Class created. | ********************************************************************************************/ var ElementClassUtility = { CONST: { ELEMENT_CLASS_NAME_SEPARATOR: " " // space character separator for element classNames }, //************************************************************************************************************** // begin ElementClassUtility.verify verify: { classExistsOnElement: function ( element, classNameToVerify ){ // create a class exists flag var classExists = false; // verify that the object has a className parameter if( element.className ){ // get the string of class names on the element var stringOfClasses = element.className; // get an array of the individual class names var arrayOfClassNames = stringOfClasses.split( ElementClassUtility.CONST.ELEMENT_CLASS_NAME_SEPARATOR ); // check whether the requested class exists in the array classExists = ArrayUtility.verify.itemExistsInArray( classNameToVerify, arrayOfClassNames ); } return classExists; }, classExistsOnElement_byId: function ( elementId, classNameToVerify ){ return ElementClassUtility.verify.classExistsOnElement( ElementAccessor.get( elementId ), classNameToVerify ); } }, // end ElementClassUtility.verify //************************************************************************************************************** //************************************************************************************************************** // begin ElementClassUtility.set set: { elementClass: function ( element, stringOfClasses ){ element.className = stringOfClasses; } }, // end ElementClassUtility.set //************************************************************************************************************** //************************************************************************************************************** // begin ElementClassUtility.addClass addClass: { toElement: function ( element, classToAdd ){ // verify the requested element exists if( !( element == null ) ) // add the new class to the requested element ElementClassUtility.set.elementClass( element, ElementClassUtility.addClass.toStringOfClasses( classToAdd, element.className ) ); }, toElement_byId: function ( elementId, classToAdd ){ // redirect to the element function ElementClassUtility.addClass.toElement( ElementAccessor.get( elementId ), classToAdd ); }, toStringOfClasses: function ( classToAdd, stringOfClasses ){ // get an array of the individual class names // which are always separated by a space character var arrayOfClassNames = stringOfClasses.split( ElementClassUtility.CONST.ELEMENT_CLASS_NAME_SEPARATOR ); // add the requested class ArrayUtility.process.addUniqueItem( classToAdd, arrayOfClassNames ); // return the classes as ONE string return arrayOfClassNames.join( ElementClassUtility.CONST.ELEMENT_CLASS_NAME_SEPARATOR ); } }, // end ElementClassUtility.addClass //************************************************************************************************************** //************************************************************************************************************** // begin ElementClassUtility.removeClass removeClass: { fromElement: function ( element, classToRemove ){ // DEBUG ERROR OUTPUT //if( typeof( element ) == "undefined" || element == null ) //console.log( "Error removing className: " + classToRemove + " on DOMobject: " + element ); // verify the requested element exists if( !( element == null ) ) // remove the class from the requested element ElementClassUtility.set.elementClass( element, ElementClassUtility.removeClass.fromStringOfClasses( classToRemove, element.className ) ); }, fromElement_byId: function ( elementId, classToRemove ){ // redirect to the element function ElementClassUtility.removeClass.fromElement( ElementAccessor.get( elementId ), classToRemove ); }, fromStringOfClasses: function ( classToRemove, stringOfClasses ){ // get an array of the individual class names var arrayOfClassNames = stringOfClasses.split( ElementClassUtility.CONST.ELEMENT_CLASS_NAME_SEPARATOR ); // remove the requested class ArrayUtility.process.removeItem( classToRemove, arrayOfClassNames ); // return the classes as ONE string return arrayOfClassNames.join( ElementClassUtility.CONST.ELEMENT_CLASS_NAME_SEPARATOR ); } }, // end ElementClassUtility.removeClass //************************************************************************************************************** //************************************************************************************************************** // begin ElementClassUtility.process process: { addOrRemoveClassUsingFlag: function ( element, classToAddOrRemove, addClassFlag ){ // check the add class flag if( addClassFlag ) ElementClassUtility.addClass.toElement( element, classToAddOrRemove ); else ElementClassUtility.removeClass.fromElement( element, classToAddOrRemove ); }, addOrRemoveClassUsingFlag_byId: function ( elementId, classToAddOrRemove, addClassFlag ){ // redirect to the element function ElementClassUtility.process.addOrRemoveClassUsingFlag( ElementAccessor.get( elementId ), classToAddOrRemove, addClassFlag ); }, applyDualStateClassUsingFlag: function ( element, trueStateClass, falseStateClass, stateFlag ){ // check the state flag if( stateFlag ){ // FLAG IS RAISED / TRUE // remove the FALSE state ElementClassUtility.removeClass.fromElement( element, falseStateClass ); // add the TRUE state ElementClassUtility.addClass.toElement( element, trueStateClass ); } else { // FLAG IS LOWERED / FALSE // remove the TRUE state ElementClassUtility.removeClass.fromElement( element, trueStateClass ); // add the FALSE state ElementClassUtility.addClass.toElement( element, falseStateClass ); } } } // end ElementClassUtility.process //************************************************************************************************************** } /******************************************************************************************** | | ElementPropUtility | SCRIPT REACTION LIBRARY | | Created by : Kevin Biskaborn | Copyright (c) 2005-2015 ScriptReaction Ltd. All Rights Reserved. | https://www.scriptreaction.ca | |-- LATEST REVISION ------------------------------------------------------------------------- | | K. Biskaborn | |-- CLASSES REQUIRED ------------------------------------------------------------------------ | | ElementAccessor | |-- HISTORY --------------------------------------------------------------------------------- | | OCT.22.2013 : Class renamed from "DivElementUtility" to "ElementPropUtility". | APR.05.2012 : Class created. | ********************************************************************************************/ var ElementPropUtility = { CONST: { // Property IDs PROP_ID_STYLE_BACKGROUND_IMAGE: "backgroundImage", PROP_ID_STYLE_DISPLAY: "display", PROP_ID_STYLE_VISIBILITY: "visibility", // Property Values PROP_VALUE_STYLE_BACKGROUND_IMAGE_NONE: "none", PROP_VALUE_STYLE_DISPLAY_BLOCK: "block", PROP_VALUE_STYLE_DISPLAY_NONE: "none", PROP_VALUE_STYLE_VISIBILITY_HIDDEN: "hidden", PROP_VALUE_STYLE_VISIBILITY_VISIBLE: "visible" }, //************************************************************************************************************** // begin ElementPropUtility.verify verify: { elementDisplay_isBlock: function ( element ){ return ( ElementPropUtility.get.style.display.by_element( element ) == ElementPropUtility.CONST.PROP_VALUE_STYLE_DISPLAY_BLOCK ); } }, // end ElementPropUtility.verify //************************************************************************************************************** //************************************************************************************************************** // begin ElementPropUtility.get get: { innerContent: { by_element: function ( element ){ return ( element == null ) ? null : element.innerHTML; }, by_id: function ( elementId ){ return ElementPropUtility.get.innerContent.by_element( ElementAccessor.get( elementId ) ); } }, style: { display: { by_element: function ( element ){ return ElementPropUtility.get.style.property.by_element( element, ElementPropUtility.CONST.PROP_ID_STYLE_DISPLAY ); }, by_id: function ( elementId ){ return ElementPropUtility.get.style.display.by_element( ElementAccessor.get( elementId ) ); } }, property: { by_element: function ( element, propId ){ return ( element == null ) ? null : element.style[ propId ]; } } } }, // end ElementPropUtility.get //************************************************************************************************************** //************************************************************************************************************** // begin ElementPropUtility.set set: { innerContent: { as_propRefresh: function ( element ){ // refreshes the inner content of the requested element ElementPropUtility.set.innerContent.by_element( element, ElementPropUtility.get.innerContent.by_element( element ) ); }, by_element: function ( element, propValue ){ // verify the element exists if( !( element == null ) ) // set the div content element.innerHTML = propValue; }, //>> //-> FUNCTION NAME >> ElementPropUtility.set.innerContent.by_id //-> DESCRIPTION >> Sets the content of the specified HTML element //-> PARAMETERS >> elementId [String]: the ID of the target HTML element // >> propValue [String]: the inner content to insert into the element //-> RETURN >> None //<< by_id: function ( elementId, propValue ){ ElementPropUtility.set.innerContent.by_element( ElementAccessor.get( elementId ), propValue ); } }, //************************************************************************************************************** // begin ElementPropUtility.set.style style: { //************************************************************************************************************** // begin ElementPropUtility.set.style.backgroundImage backgroundImage: { by_element: function ( element, propValue ){ // format the background image value // check for NO background propValue = ( propValue == ElementPropUtility.CONST.PROP_VALUE_STYLE_BACKGROUND_IMAGE_NONE ) // no background, maintain value ? propValue // assume a background image path : "url(" + propValue + ")"; // set the property value ElementPropUtility.set.style.property.by_element( element, ElementPropUtility.CONST.PROP_ID_STYLE_BACKGROUND_IMAGE, propValue ); }, by_id: function ( elementId, propValue ){ ElementPropUtility.set.style.backgroundImage.by_element( ElementAccessor.get( elementId ), propValue ); } }, // end ElementPropUtility.set.style.backgroundImage //************************************************************************************************************** //************************************************************************************************************** // begin ElementPropUtility.set.style.display display: { as_block: function ( element ){ ElementPropUtility.set.style.display.by_element( element, ElementPropUtility.CONST.PROP_VALUE_STYLE_DISPLAY_BLOCK ); }, as_none: function ( element ){ ElementPropUtility.set.style.display.by_element( element, ElementPropUtility.CONST.PROP_VALUE_STYLE_DISPLAY_NONE ); }, by_element: function ( element, propValue ){ ElementPropUtility.set.style.property.by_element( element, ElementPropUtility.CONST.PROP_ID_STYLE_DISPLAY, propValue ); }, by_id: function ( elementId, propValue ){ ElementPropUtility.set.style.display.by_element( ElementAccessor.get( elementId ), propValue ); }, fromFlag_byElement: function ( element, isVisibleFlag ){ // set the display of the element as block if it visible if( isVisibleFlag ) ElementPropUtility.set.style.display.as_block( element ); else ElementPropUtility.set.style.display.as_none( element ); }, //>> //-> FUNCTION NAME >> ElementPropUtility.set.style.display.fromFlag_byId //-> DESCRIPTION >> Sets the BLOCK/NONE CSS style property of the requested element // based on the submitted flag. //-> PARAMETERS >> elementId [String]: the HTML element id // >> isVisibleFlag [Boolean]: true if the element is to be visible, // false otherwise //-> RETURN >> None //<< fromFlag_byId: function ( elementId, isVisibleFlag ){ ElementPropUtility.set.style.display.fromFlag_byElement( ElementAccessor.get( elementId ), isVisibleFlag ); } }, // end ElementPropUtility.set.style.display //************************************************************************************************************** //************************************************************************************************************** // begin ElementPropUtility.set.style.visibility visibility: { as_hidden: function ( element ){ ElementPropUtility.set.style.visibility.by_element( element, ElementPropUtility.CONST.PROP_VALUE_STYLE_VISIBILITY_HIDDEN ); }, as_visible: function ( element ){ ElementPropUtility.set.style.visibility.by_element( element, ElementPropUtility.CONST.PROP_VALUE_STYLE_VISIBILITY_VISIBLE ); }, by_element: function ( element, propValue ){ ElementPropUtility.set.style.property.by_element( element, ElementPropUtility.CONST.PROP_ID_STYLE_VISIBILITY, propValue ); }, by_id: function ( elementId, propValue ){ ElementPropUtility.set.style.visibility.by_element( ElementAccessor.get( elementId ), propValue ); }, fromFlag_byElement: function ( element, isVisibleFlag ){ // set the display of the element as block if it visible if( isVisibleFlag ) ElementPropUtility.set.style.visibility.as_visible( element ); else ElementPropUtility.set.style.visibility.as_hidden( element ); }, //>> //-> FUNCTION NAME >> ElementPropUtility.set.style.visibility.fromFlag_byId //-> DESCRIPTION >> Sets the VISIBLE/HIDDEN CSS style property of the requested element // based on the submitted flag. //-> PARAMETERS >> elementId [String]: the HTML element id // >> isVisibleFlag [Boolean]: true if the element is to be visible, // false otherwise //-> RETURN >> None //<< fromFlag_byId: function ( elementId, isVisibleFlag ){ ElementPropUtility.set.style.visibility.fromFlag_byElement( ElementAccessor.get( elementId ), isVisibleFlag ); } }, // end ElementPropUtility.set.style.visibility //************************************************************************************************************** //************************************************************************************************************** // begin ElementPropUtility.set.style.property property: { by_element: function ( element, propId, propValue ){ // verify the element exists if( !( element == null ) ) // set the requested style property element.style[ propId ] = propValue; } } // end ElementPropUtility.set.style.property //************************************************************************************************************** } } // end ElementPropUtility.set //************************************************************************************************************** } /******************************************************************************************** | | NumberUtility | SCRIPT REACTION LIBRARY | | Created by : Kevin Biskaborn | Copyright (c) 2005-2015 ScriptReaction Ltd. All Rights Reserved. | https://www.scriptreaction.ca | |-- LATEST REVISION ------------------------------------------------------------------------- | | K. Biskaborn | |-- CLASSES REQUIRED ------------------------------------------------------------------------ | | StringUtility | |-- HISTORY --------------------------------------------------------------------------------- | | NOV.07.2012 : Class created. | ********************************************************************************************/ var NumberUtility = { CONST: { // AA Standard Constant Collection (v1) ELEMENT_COUNT_ONE: 1, ELEMENT_COUNT_ZERO: 0, FLAG_VALUE_TRUE: 1, FLAG_VALUE_FALSE: 0, INDEX_FIRST_ELEMENT: 0, INDEX_SECOND_ELEMENT: 1, INVALID_ID: -1, INVALID_INDEX: -1, INVALID_OBJECT: null, // parsing radix for decimal numbers PARSE_INT_RADIX_DECIMAL: 10 }, //************************************************************************************************************** // begin NumberUtility.verify verify: { isInteger_allowPointZero: function ( value ){ // Note: // if 1.0 needs to be valid, use: // verify the value IS a number, // that the parsed int is a number, // AND the float (decimal point) value EQUALS the int value (ie: 1 = 1.0) return !isNaN( value ) && !isNaN( NumberUtility.get.valueAsInteger( value ) ) && ( parseFloat( value ) == parseInt( value ) ); }, isInteger_noDecimal: function ( value ){ // verify the value IS a number, // that the parsed int is a number, // AND that NO DECIMAL POINT is used return !isNaN( value ) && !isNaN( NumberUtility.get.valueAsInteger( value ) ) && !StringUtility.verify.contains( value.toString(), "." ); } }, // end NumberUtility.verify //************************************************************************************************************** //************************************************************************************************************** // begin NumberUtility.get get: { absoluteValue: function ( value ){ return ( value < NumberUtility.CONST.ELEMENT_COUNT_ZERO ) ? value * -1 : value; }, valueAsInteger: function ( value ){ return parseInt( value, NumberUtility.CONST.PARSE_INT_RADIX_DECIMAL ); } }, // end NumberUtility.get //************************************************************************************************************** //************************************************************************************************************** // begin NumberUtility.generateRandom generateRandom: { fromOneToMax: function ( maximum ){ return NumberUtility.generateRandom.fromZero( maximum ) + NumberUtility.CONST.ELEMENT_COUNT_ONE; }, fromZero: function ( maximum ){ return Math.floor( Math.random() * maximum ); } } // end NumberUtility.generateRandom //************************************************************************************************************** } /******************************************************************************************** | | StringUtility | SCRIPT REACTION LIBRARY | | Created by : Kevin Biskaborn | Copyright (c) 2005-2015 ScriptReaction Ltd. All Rights Reserved. | https://www.scriptreaction.ca | |-- LATEST REVISION ------------------------------------------------------------------------- | | K. Biskaborn | |-- CLASSES REQUIRED ------------------------------------------------------------------------ | | ArrayUtility | |-- HISTORY --------------------------------------------------------------------------------- | | OCT.20.2014 : Reverse function and nChar left and right trim functions added. | OCT.22.2013 : Class reorganized. | MAR.24.2012 : Class created. | |-- NOTES --------------------------------------------------------------------------------- | | - Regular Expressions consider a string AS A WHOLE; they do NOT iterate by character. | The expression searches a string for any matching patterns and executes from there. } ********************************************************************************************/ var StringUtility = { CONST: { // AA Standard Constant Collection (v1) ELEMENT_COUNT_ONE: 1, ELEMENT_COUNT_ZERO: 0, FLAG_VALUE_TRUE: 1, FLAG_VALUE_FALSE: 0, INDEX_FIRST_ELEMENT: 0, INDEX_SECOND_ELEMENT: 1, INVALID_ID: -1, INVALID_INDEX: -1, INVALID_OBJECT: null, NEGATIVE_ONE: -1 }, //************************************************************************************************************** // begin StringUtility.verify verify: { beginsWith: function ( inputString, prefix ){ // test if the input string begins with the requested prefix return ( inputString.substring( StringUtility.CONST.INDEX_FIRST_ELEMENT, prefix.length ) == prefix ); }, contains: function ( inputString, searchNeedleString ){ // searches the inputString for the requested needle // in the event the needle is a number, the var is cast to a string below return ( inputString.indexOf( "" + searchNeedleString ) >= StringUtility.CONST.ELEMENT_COUNT_ZERO ); }, endsWith: function ( inputString, suffix ){ // test if the input string ends with the requested suffix return ( inputString.substring( inputString.length - suffix.length, inputString.length ) == suffix ); }, isValidEmail: function ( inputString ){ var regex = /^[a-z0-9\._-]+@([a-z0-9_-]+\.)+[a-z]{2,6}$/i; return regex.test( inputString ); } }, // end StringUtility.verify //************************************************************************************************************** //************************************************************************************************************** // begin StringUtility.get get: { charAtIndex: function ( inputString, charIndex ){ return inputString.charAt( charIndex ); }, firstChar: function ( inputString ){ return StringUtility.get.charAtIndex( inputString, StringUtility.CONST.INDEX_FIRST_ELEMENT ); }, stringLength: function ( inputString ){ return inputString.length; } }, // end StringUtility.get //************************************************************************************************************** //************************************************************************************************************** // begin StringUtility.process process: { addPadding: { prefix: function ( inputValue, padCharString, size ){ // the inputValue must be cast to a string (value may be a number) inputString = inputValue.toString(); // pad string with requested pad character while( inputString.length < size ) inputString = padCharString + inputString; return inputString; }, prefix_zero: function ( inputValue, size ){ return StringUtility.process.addPadding.prefix( inputValue, "0", size ); } }, //>> //-> FUNCTION NAME >> StringUtility.process.decodeHtmlSpecialChars //-> DESCRIPTION >> Replaces all occurances of safe web code characters // with HTML special characters (&,<,>,",') //-> PARAMETERS >> inputString [String]: the string to format //-> RETURN >> The string with UNSAFE HTML characters //<< decodeHtmlSpecialChars: function ( inputString ){ // Note: the amperstand replacement must occur FIRST return inputString .replace( /&/g, "&" ) .replace( /</g, "<" ) .replace( />/g, ">" ) .replace( /"/g, "\"" ) .replace( /'/g, "'" ); }, //>> //-> FUNCTION NAME >> StringUtility.process.encodeHtmlSpecialChars //-> DESCRIPTION >> Replaces all occurances of HTML special characters // (&,<,>,",') in the submitted string with // safe web code alternatives //-> PARAMETERS >> inputString [String]: the string to format //-> RETURN >> The string with safe web characters //<< encodeHtmlSpecialChars: function ( inputString ){ // Note: the amperstand replacement must occur FIRST return inputString .replace( /&/g, "&" ) .replace( //g, ">" ) .replace( /"/g, """ ) .replace( /'/g, "'" ); }, parseQueryStringToObject: function ( queryString ){ // breaks up a query string into an object representation // For example, INPUT: ?name=AdminArea&dev=ScriptReaction // OUTPUT: { name: "AdminArea", dev: "ScriptReaction" } var output = new Object(); //remove the leading query string char queryString = StringUtility.remove.prefix( queryString, "?" ); //remove the trailing query string char queryString = StringUtility.remove.suffix( queryString, "&" ); //split the query string //into individual data items var dataItemArray = queryString.split( "&" ); //create variable containers var dataItem = ""; var itemArray = []; //cycle through all data items for( var i = 0; i < dataItemArray.length; i++ ){ dataItem = dataItemArray[ i ]; //split the data item //into id and value pairs itemArray = dataItem.split( "=" ); //add the item to the output output[ itemArray[ 0 ] ] = itemArray[ 1 ]; } return output; }, reverseString: function ( str ){ return str.split( "" ).reverse().join( "" ); } }, // end StringUtility.process //************************************************************************************************************** //************************************************************************************************************** // begin StringUtility.remove remove: { //>> //-> FUNCTION NAME >> StringUtility.remove.prefix //-> DESCRIPTION >> Removes the specified prefix (if it exists) // from the specified string //-> PARAMETERS >> inputString [String]: the string to remove the prefix from // >> prefix [String]: the prefix to remove //-> RETURN >> The string with the prefix removed if the prefix existed, // else the original string //<< prefix: function ( inputString, prefix ){ // removes ONE INSTANCE of the prefix from the inputString // to remove ALL instances of the prefix, use StringUtility.strip.leadingChars() if( StringUtility.verify.beginsWith( inputString, prefix ) ) return inputString.substring( prefix.length, inputString.length ); else return inputString; }, suffix: function ( inputString, suffix ){ // removes ONE INSTANCE of the suffix from the inputString // to remove ALL instances of the suffix, use StringUtility.strip.trailingChars() if( StringUtility.verify.endsWith( inputString, suffix ) ) return inputString.substring( 0, inputString.length - suffix.length ); else return inputString; } }, // end StringUtility.remove //************************************************************************************************************** //************************************************************************************************************** // begin StringUtility.replaceOccurances replaceOccurances: { allOccurances: function ( inputString, searchNeedleString, replacementString, isCaseSensitive ){ // use a regular expression // set the regex parameters // g: global search (all occurances) // i: case IN-sensitive var regEx_param = "g"; // check for a case in-sensitive search if( !isCaseSensitive ) regEx_param += "i"; // create the regular expression // for the string to be search for var regEx = new RegExp( searchNeedleString, regEx_param ); // execute the replace on the target string return inputString.replace( regEx, replacementString ); } }, // end StringUtility.replaceOccurances //************************************************************************************************************** //************************************************************************************************************** // begin StringUtility.strip strip: { doubleSpaces: function ( inputString ){ return inputString.replace( /\s\s/, " " ); }, htmlSpecialCharCodes: function ( inputString ){ return inputString .replace( /&/g, "" ) .replace( /</g, "" ) .replace( />/g, "" ) .replace( /"/g, "" ) .replace( /'/g, "" ); }, htmlTags: function ( inputString ){ return inputString.replace( /(<([^>]+)>)/ig, "" ); }, leadingChars: function ( inputString, charToStrip ){ // removes ALL OCCURANCES of the specified leading character to strip // from the beginning of the inputString // create the regex pattern // new RegExp (pattern, modifiers) var regex = new RegExp( "^" + charToStrip + "+", "g" ); // execute the replace return inputString.replace( regex, "" ); }, nonIntegerChars_allowNegatives: function ( inputString ){ // get the first char of the string var firstChar = StringUtility.get.firstChar( inputString ); // test for a negative value var isNegative = ( firstChar == "-" ); // remove ALL HTML special character codes inputString = StringUtility.strip.htmlSpecialCharCodes( inputString ); // remove ALL non-numeric characters // (including any dashes) inputString = StringUtility.strip.nonIntegerChars_noNegatives( inputString ); // re-attached the first char (if negative) if( isNegative ) inputString = firstChar + inputString; return inputString; }, nonIntegerChars_noNegatives: function ( inputString ){ // remove ALL HTML special character codes inputString = StringUtility.strip.htmlSpecialCharCodes( inputString ); // regex matches the chars to be REPLACED // [^0-9] = not one of 0 through 9 (any non-numeric char) return inputString.replace( /[^0-9]+/g, "" ); }, trailingChars: function ( inputString, charToStrip ){ // create the regex pattern var regex = new RegExp( charToStrip + "+$", "g" ); // execute the replace return inputString.replace( regex, "" ); }, tripleSpaces: function ( inputString ){ return inputString.replace( /\s\s\s/, " " ); } }, // end StringUtility.strip //************************************************************************************************************** //************************************************************************************************************** // begin StringUtility.trim trim: { nchars: { // these functions trim a specified NUMBER of characters left: function ( inputString, numChars ){ return inputString.slice( numChars ); }, right: function ( inputString, numChars ){ return inputString.slice( StringUtility.CONST.ELEMENT_COUNT_ZERO, numChars * StringUtility.CONST.NEGATIVE_ONE ); } }, whitespace: { // these functions trim WHITESPACE (space / tab chars) bothEnds: function ( inputString ){ return StringUtility.trim.whitespace.left( StringUtility.trim.whitespace.right( inputString ) ); }, left: function ( inputString ){ // note that space character is LITERALLY entered // in the regular expression string (\s is NOT used) var regex = new RegExp( "^ +", "g" ); return inputString.replace( regex, "" ); }, right: function ( inputString ){ var regex = new RegExp( " +$", "g" ); return inputString.replace( regex, "" ); } } }, // end StringUtility.trim //************************************************************************************************************** //************************************************************************************************************** // begin StringUtility.build build: { collapsedRangeDisplay_forArrayOfIntegers: function ( inputObject ){ var output = ""; // Accepts an array of integers and creates a compressed display of all integers present. // Example Input: [ 4, 6, 7, 8, 10, 11, 12, 15 ] // Example Output: "4, 6-8, 10-12, 15" // Notes: duplicate values are ignored, negative values are allowed. // extract incoming var arrayOfIntegers = ( typeof( inputObject.arrayOfIntegers ) != "undefined" ) ? inputObject.arrayOfIntegers : []; var elementList_delimiter = ( typeof( inputObject.elementList_delimiter ) != "undefined" ) ? inputObject.elementList_delimiter : ", "; var collapsedRange_delimiter = ( typeof( inputObject.collapsedRange_delimiter ) != "undefined" ) ? inputObject.collapsedRange_delimiter : "-"; var collapsedRange_minSize = ( typeof( inputObject.collapsedRange_minSize ) != "undefined" ) ? inputObject.collapsedRange_minSize : 3; // ------------------------------------------------------------- // get the number of elements var numElements = arrayOfIntegers.length; // verify integers exist if( numElements > StringUtility.CONST.ELEMENT_COUNT_ZERO ){ // sort the collection of integers arrayOfIntegers = ArrayUtility.reorder.applySort.integerAscending( arrayOfIntegers ); // check if the number of entries is LESS THAN the minimum size of a collapsed range if( numElements < collapsedRange_minSize ) // use a simple list of elements output += "" + ArrayUtility.arrayToString.stringDelimited( arrayOfIntegers, elementList_delimiter ); else { // ------------------------------------------------------------- // enough elements exist for AT LEAST ONE collapsed range // create an array to store range collections var arrayOfRangeCollections = []; // create an array to store list groups (final output) var arrayOfListGroups = []; // populate the range collections with nested arrays, one for each element for( var i = StringUtility.CONST.INDEX_FIRST_ELEMENT; i < numElements; i++ ) arrayOfRangeCollections.push( [] ); // create loop containers // active range index counter var activeRangeIndex = StringUtility.CONST.INVALID_INDEX; // previous numver value // value is equal to TWO less than the first integer // (so no previous number match occurs in the first loop execution var prevNumber = arrayOfIntegers[ StringUtility.CONST.INDEX_FIRST_ELEMENT ] - 2; // ------------------------------------------------------------- // create loop containers var integerValue; // cycle through the array of elements for( i in arrayOfIntegers ){ // get the next int value integerValue = arrayOfIntegers[ i ]; // verify the next number is NOT THE SAME as the previous // duplicate values are not included if( !( integerValue == prevNumber ) ){ // check if the next integer is NOT a number, or it is a number // that does NOT immediately follow the previous number in sequence if( isNaN( integerValue ) || !( integerValue == prevNumber + StringUtility.CONST.ELEMENT_COUNT_ONE ) ) // increment the active range index // on the first pass of the loop, this increment MUST occur ++activeRangeIndex; // add the element to the active range arrayOfRangeCollections[ activeRangeIndex ].push( integerValue ); // update the previous number prevNumber = integerValue; } } // ------------------------------------------------------------- // create loop containers var rangeArray; // cycle through the range collections for( i in arrayOfRangeCollections ){ // get the next range array rangeArray = arrayOfRangeCollections[ i ]; // get the number of elements in the range rangeSize = rangeArray.length; // verify that at least ONE element exists in the range if( rangeSize >= StringUtility.CONST.ELEMENT_COUNT_ONE ){ // check if the range has LESS THAN the minimum size if( rangeSize < collapsedRange_minSize ) // use a simple list of elements for that range collection arrayOfListGroups.push( ArrayUtility.arrayToString.stringDelimited( rangeArray, elementList_delimiter ) ); else { // the range collection needs to be collapsed // get the first element of the range var firstElement = rangeArray[ StringUtility.CONST.INDEX_FIRST_ELEMENT ]; // get the last element of the range var lastElement = rangeArray[ rangeSize - StringUtility.CONST.ELEMENT_COUNT_ONE ]; // add the collapsed range to the array of list elements arrayOfListGroups.push( firstElement + collapsedRange_delimiter + lastElement ); } } } // merge the list elements output += ArrayUtility.arrayToString.stringDelimited( arrayOfListGroups, elementList_delimiter ); } } return output; } } // end StringUtility.build //************************************************************************************************************** }