// JavaScript Document
// This JavaScript contains general functions that are used throughout FAAdmin pages

/*****************************************/
/* Change List                           */
/*****************************************/
// ID				Date			Author				Description
// N/A				2013/Mar/04		Jeyong				Moved setCookie and getCookie from general JS page to current JS page
// N/A				2013/Mar/04		Jeyong				Created initPage function to contain all common operation need to be done for all pages.
//														This function is supposed to contain original function being called in settingsApp page:
//                                                      initRedirectMask.
// N/A				2013/Mar/04		Jeyong				Created createRedirectMaskLayer. This function replaces initial function initRedirectMask.
//														The function was re-named to describe what the function actually does.
// N/A				2013/Mar/04		Jeyong				Created showWindow and hideWindow functions. This function replaces showMessage and hideMessage.
//														In the application, there was already a function about show{xxx}Message and hide{xxx}Message,
// 														and the functionality was very different from current function.
// 														In order to better define what the function was about (which is about creating a modal window
// 														on a separate layer), the showWindow name was chosen.

/*****************************************/
/* Function List                         */
/*****************************************/

// Initial functions:
// 1-1. initPage - initialize common behaviours for all pages

// General functions
// 2-1. addOnLoad - add an additional window.oload
// 2-2. setCookie - helper function create/set cookie with that expires as session
// 2-3. getCookie - helper function to retrieve value stored in a cookie
// 2-4. getBrowserDimension - helper function to get current width and height of a window browser size
// 2-5. getContentDimension - helper function to get current width and height of current content
// 2-6. disableEnter - function to disable enter when an keypress event is triggered

// Layer related functions
// 3-9. disablePage - function to disable all content below masked area for current page
// 3-10. enablePage - function to enable all contents of current page
// 3-11. createLayer - function to create layer
// 3-12. deleteLayer - function to delete layer with specified id
// 3-13. createButton - function to create button
// 3-14. resizeLayer - function to resize indicated layer

// Validation related functions
// 4-1. validateRequired - helper function to validate if field is empty or not
// 4-2. validateText - helper function to validate if field contains any character not allowed
// 4-3. validateInteger - helper function to validate if field contains non-numeric characters
// 4-4. validateDecimal - helper function to validate if field is in numeric format (including decimal)
// 4-5. validatePositive - helper function to validate if field is a positive number
// 4-6. validateRange - helper function to validate if field contains out of range values
// 4-7. validateDate - helper function to validate if field contains valid date
// 4-8. isValidFormat - helper function to check if input value matches whitelist and blacklist criteria

/*****************************************/
/* Global Variables                      */
/*****************************************/
var gLayers = new Array();

/*****************************************/
/* Initial functions                     */
/*****************************************/

// Initialize common behaviours for all pages
function initPage() {

}

/*****************************************/
/* General functions                     */
/*****************************************/

// Add additional function call to existing window.onload event listener
// - this function is cross browser compatible with switch between addEventListener and window.attachEvent
function addOnLoad(func) {
    if (window.addEventListener) // W3C standard
        window.addEventListener('load', func, false); // NB **not** 'onload'

    else if (window.attachEvent) // Microsoft
        window.attachEvent('onload', func);
}

// Creates or updates a cookie.
// - this function creates a cookie with session exipry (expires=0)
// - code reference from: http://www.w3schools.com/js/js_cookies.asp
function setCookie(key, value) {
    document.cookie = escape(key) + "=" + escape(value) + "; expires=0; path=/";
}

// Retrieve value stored in a cookie set by setCookie
// - code reference from: http://www.w3schools.com/js/js_cookies.asp
function getCookie(key) {
    var i, x, y, arrCookies = document.cookie.split(";");
    for (i = 0; i < arrCookies.length; i++) {
        x = arrCookies[i].substr(0, arrCookies[i].indexOf("="));
        y = arrCookies[i].substr(arrCookies[i].indexOf("=") + 1);
        x = x.replace(/^\s+|\s+$/g, "");
        if (x == key)
            return unescape(y);
    }

    return "";
}

// Get current width and height of a window browser
// - code reference from: http://www.java-samples.com/showtutorial.php?tutorialid=1015
function getBrowserDimension() {
    var intH = 0;
    var intW = 0;

    if (typeof window.innerWidth == 'number') {
        // Non IE
        intH = window.innerHeight;
        intW = window.innerWidth;
    }
    else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
        // IE 6+ in 'standards compliant mode'
        intH = document.documentElement.clientHeight;
        intW = document.documentElement.clientWidth;
    }
    else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
        // IE 4 compatible
        intH = document.body.clientHeight;
        intW = document.body.clientWidth;
    }

    return { width: parseInt(intW), height: parseInt(intH) };
}

// Get current width and height of current content
// - Gets maximum dimension of all known method used to retrieve body content size for cross browser compatibility.
function getContentDimension() {
    var winW = Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);
    var winH = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);

    return { width: parseInt(winW), height: parseInt(winH) };
}

// Disable enter when an keypress event is triggered
function disableEnter(e) {
    // disable keyCode 13 - enter
    if (e.which == 13) e.preventDefault();
}

/*****************************************/
/* Layer functions                       */
/*****************************************/

// Disable all content below masked area for current page
// - Creates a layer in current page for all contents (moved from document.body into the new layer)
// - Disables the layer
// - Note that is function needs to be called before creating a separate layer, otherwise, the new layer will also be disabled
function disablePage() {
    //Container ID that holds default content - to be disabled 
    var contentLayerId = "genContentLayer";

    //Create content layer if it does not exist
    if ($("#" + contentLayerId).length == 0) {
        $("body").html("<span id=\"" + contentLayerId + "\">" + $("body").html() + "</span>");
    }

    //Disable actions done in container
    var elmt = document.getElementById(contentLayerId);
    if (elmt != null) {
        //Disable tab to prevent user from tabbing to masked fields
        elmt.onkeydown = function () { return false; };
    }
}

// Enable all contents of current page disabled by disablePage function
function enablePage() {
    //Container ID that holds default content - to be enabled 
    var contentLayerId = "genContentLayer";

    //Enable actions done in container
    var elmt = document.getElementById(contentLayerId);
    if (elmt != null) {
        //Remove keyboard restriction
        elmt.onkeydown = function () { return true; };
    }
}

// Function to create layer
function createLayer(id, className, isVisible) {
    var elmt = document.getElementById(id);
    if (elmt)
        return elmt;

    if (gLayers[id] == undefined) {
        //latest entry
        var maxLayer = 0;
        for (var i = 0; i < gLayers.length; i++) {
            if (maxLayer < gLayers[i][1])
                maxLayer = gLayers[i][1];
        }

        gLayers.push([id, maxLayer + 1]);
    }

    //Create div
    var div = document.createElement("div");
    div.className = className;
    div.id = id;
    div.style.display = "none";

    //Add new div to html body
    document.body.appendChild(div);

    //JQuery animation to prevent from page flickering if the loading time is too short
    //If set to visible, the content will fade in with delay of 0.4
    //If set to hidden, the content will be loaded, but hidden initially
    if (isVisible) {
        $("#" + id).fadeIn(400);
    } else {
        $("#" + id).hide();
    }

    return div;
}

// Delete layer with specified id from current page
function deleteLayer(id) {
    var elmt = document.getElementById(id);
    if (elmt)
        document.body.removeChild(elmt);

    var indexToRemove = -1;
    for (var i = 0; i < gLayers.length; i++) {
        if (gLayers[i][0] == id) {
            indexToRemove = i;
        }
    }

    gLayers.splice(indexToRemove, 1);
}

function createContent(containerId, id, className) {
    var elmt = document.getElementById(id);
    if (elmt)
        return elmt;

    //Create div
    var div = document.createElement("div");
    div.id = id;
    div.className = className;

    //Add new div to container
    var container = document.getElementById(containerId);
    if (container != null)
        container.appendChild(div);

    return div;
}

// Create iframe
function createIframe(containerId, id, className, src) {
    var elmt = document.getElementById(id);
    if (elmt)
        return elmt;

    var iframe = document.createElement("iframe");
    iframe.className = className;
    iframe.id = id;
    iframe.src = src;

    //iframe.scrolling = false; // this does not work in IE

    //Add new iframe to container
    var container = document.getElementById(containerId);
    if (container != null)
        container.appendChild(iframe);

    return iframe;
}

// Create button
function createCloseButton(containerId, id, className) {
    var elmt = document.getElementById(id);
    if (elmt)
        return elmt;

    var btn = document.createElement("a");
    btn.id = id;
    btn.className = className;
    btn.innerHTML = "&nbsp;";
    btn.title = "Close";

    //Add new button to container
    var container = document.getElementById(containerId);
    if (container != null)
        container.appendChild(btn);

    return btn;
}

// Function to resize indicated layer:
// - maximum size of current browser/content dimension
function resizeLayer(id) {
    var elmt = document.getElementById(id);
    if (elmt) {
        var bws = getBrowserDimension();
        var con = getContentDimension();

        elmt.style.width = Math.max(bws.width, con.width) + "px";
        elmt.style.height = Math.max(bws.height, con.height) + "px";
    }
}

// Function to get current layer index
function getLayerIndex(id) {
    for (var i = 0; i < gLayers.length; i++) {
        if (gLayers[i][0] == id) {
            return gLayers[i][1];
        }
    }

    return 0;
}

/*****************************************/
/* Validation functions                  */
/*****************************************/

// Helper function to validate if field is empty or not
function validateRequired(value) {
    if (value == "") {
        return false;
    }

    return true;
}

// Helper function to validate if field contains any character not allowed
function validateText(value) {
    var illegalChars = ["<", ">"];
    if (!isValidFormat(value, null, illegalChars)) {
        return false;
    }

    return true;
}

// Helper function to validate if field contains non-numeric characters
function validateInteger(value) {
    var pattern = /^-?[0-9]*$/;
    if (!pattern.test(value)) {
        return false;
    }

    return true;
}

// Helper function to validate if field is in numeric format (including decimal)
function validateDecimal(value) {
    var pattern = /^-?[0-9]*[.]+[0-9]*$/;
    if (!pattern.test(value)) {
        return false;
    }

    return true;
}

// Helper function to validate if field is a positive number
function validatePositive(value) {
    if (value < 0) {
        return false;
    }

    return true;
}

// Helper function to validate if field contains out of range values
function validateRange(value, begin, end) {
    if (begin > end || value > end || value < begin) {
        return false;
    }

    return true;
}

// Helper function to validate if field contains valid date
// Not yet implemented
function validateDate() {
    // Not yet implemented...
    // Refer to settings.js with 2/27/2013 or older for example in: 
    // FAAdmin/js/settings.js
    // validateEnteringDate - validation of keyCode while entering value
    // validateDate - validate field when entered
    // getMonthAsNumber - helper function to get month
    // isDate - check if value is actually a date
    alert("Not yet implemented");
    return false;
}

// Helper function to check if input value matches whitelist and blacklist criteria
// whitelist - only character that are allowed for the input (ignored if null)
// blacklist - any character not allowed to be part of the input (ignored if null)
function isValidFormat(value, whitelist, blacklist) {
    // whitelist - only character that are allowed for the value (ignored if null)
    if (whitelist != null) {
        var chars = value.split('');
        for (var i = 0; i < chars.length; i++) {
            if (whitelist.indexOf(chars[i]) == -1)
                return false;
        }
    }

    // blacklist - any character not allowed to be part of the value (ignored if null)
    if (blacklist != null) {
        for (var j = 0; j < blacklist.length; j++) {
            if (value.indexOf(blacklist[j]) != -1)
                return false;
        }
    }

    return true;
}