String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/g, "");
}
String.prototype.ltrim = function() {
    return this.replace(/^\s+/, "");
}
String.prototype.rtrim = function() {
    return this.replace(/\s+$/, "");
}
String.prototype.validateEmail = function() {
    var pattern = /^([a-zA-Z0-9_.-])+@([a-zA-Z0-9_.-])+\.([a-zA-Z])+([a-zA-Z])+/;
    return pattern.test(this);
}
String.prototype.stripTags = function() {
    return this.replace(/(<([^>]+)>)/ig, "");
}

// enable the png fix for I6 & under.
if (document.all && /MSIE (5\.5|6)/.test(navigator.userAgent) &&
    document.styleSheets && document.styleSheets[0] && document.styleSheets[0].addRule) {
    // document.styleSheets[0].addRule('*', 'behavior: url(iepngfix.htc)');
    // Feel free to add rules for specific elements only, as above.
    // You have to call this once for each selector, like so:
    document.styleSheets[0].addRule('img', 'behavior: url(iepngfix.htc)');
    document.styleSheets[0].addRule('div', 'behavior: url(iepngfix.htc)');
}


/////////// ALIASES //////////////////
function de(elementId) {
    return document.getElementById(elementId);
}
function sf(form, name, value) {
    form.elements[name].value = value;
}

// keyboard enter?
function kH(e) {
    var code;

    if (!e) var e = window.event;
    if (e.keyCode) { code = e.keyCode; }
    else if (e.which) { code = e.which; }

    return ((code == 13) || (code == 9));
}

function hideObj(objId) {
    var o = document.getElementById(objId);
    if (o != null) {
        o.style.display = "none";
    }
}
function showObj(objId) {
    var o = document.getElementById(objId);
    if (o != null) {
        o.style.display = "block";
    }
}
function setClass(objId, className) {
    var o = document.getElementById(objId);
    if (o != null) {
        o.className = className;
    }
}

var _debug_ajax = false;
var _ajax_bad_chars = "<>&'\"";
var _ajax_bad_chars_html = "&lt; &gt; &amp; &#39; &quot;";
var _ajax_bad_chars_text = "< > & ' \"";

function AjaxHasBadChars(value) {
    for (var i = 0; i < _ajax_bad_chars.length; i++) {
        var c = _ajax_bad_chars.charAt(i);
        if (value.indexOf("" + c) >= 0) {
            return true;
        }
    }
    return false;
}

function AjaxGetBadChars() {
    return _ajax_bad_chars_html;
}

function AjaxGetBadChars2() {
    return _ajax_bad_chars_text;
}

// get the Ajax object (XmlHttp)
function GetXmlHttp() {
    var obj = null;
    try {
        obj = new ActiveXObject("Msxml2.XMLHTTP");
        return obj;
    } catch (e) {
        try {
            obj = new ActiveXObject("Microsoft.XMLHTTP");
            return obj;
        } catch (E) {
            // didn't work
        }
    }

    if (typeof XMLHttpRequest != 'undefined') {
        try {
            obj = new XMLHttpRequest();
            return obj;
        } catch (e) {
            // didn't work
        }
    }
    if (window.createRequest) {
        try {
            obj = window.createRequest();
            return obj;
        } catch (e) {
            // didn't work
        }
    }
    return obj;
}

function LoadXml(xmlString) {
    var xdoc;

    if (window.ActiveXObject && /Win/.test(navigator.userAgent)) {
        // IE code
        xdoc = new ActiveXObject("Microsoft.XMLDOM");
        xdoc.async = false;
        xdoc.loadXML(xmlString);
        return xdoc;
    } else if (document.implementation && document.implementation.createDocument) {
        // FF and Opera
        var parser = new DOMParser();
        xdoc = parser.parseFromString(xmlString, 'text/xml');
        return xdoc;
    } else {
        return null;
    }
}


function toDOM(HTMLstring) {
    var d = document.createElement('div');
    d.innerHTML = HTMLstring;
    var docFrag = document.createDocumentFragment();

    while (d.firstChild) {
        docFrag.appendChild(d.firstChild)
    };

    d.innerHTML = "";   // remove it

    return docFrag;
}


function AjaxRefreshAsync(formObj, divId) {
    // sniff form script and params
    var script = formObj.action;
    if (script == "") {
        script = document.location.href;
    }
    var httpreq = "";
    for (var i = 0; i < formObj.elements.length; i++) {
        var name = escape(formObj.elements[i].name);
        var value = escape(formObj.elements[i].value);
        if (name == "") {
            continue;
        }

        if (httpreq.length > 0) {
            httpreq += "&";
        }
        httpreq += name + "=" + value;
    }
    if (_debug_ajax) {
        alert("running script=" + script + "\nhttpreq=" + httpreq);
    }
    // get the ajax object
    var xmlhttp = GetXmlHttp();
    if (xmlhttp != null) {
        // post form
        xmlhttp.open("POST", script, true);
        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4) {
                if (xmlhttp.status == 200) {
                    if (_debug_ajax) {
                        alert("ok: text= " + xmlhttp.responseText);
                    }
                    var htmlString = xmlhttp.responseText;

                    var dom = toDOM(htmlString);
                    var htmlDiv1 = dom.getElementById(divId);
                    var htmlDiv2 = document.getElementById(divId);
                    if (htmlDiv1 != null && htmlDiv2) {
                        htmlDiv2.innerHTML = htmlDiv1.innerHTML;
                        if (_debug_ajax) alert('target DIV updated successfully');
                    } else {
                        if (_debug_ajax) alert('target DIV not found');
                    }

                } else {
                    if (_debug_ajax) {
                        alert("error: " + xmlhttp.status);
                    }
                }
            }
        }
        xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
        xmlhttp.send(httpreq);
    }
}

////////////////////////////// lvsys string object /////////////////////////
// TODO: move these into string.prototype
function lvsysStr() {
    // encode the quotes and newlines so that we can use the string in javascript
    this.encodeEntities = function(s) {
        if (s == null) return "";
        s = s.replace(/\'/g, "&#39;");
        s = s.replace(/\r\n/g, "<br/>");
        s = s.replace(/\n/g, "<br/>");
        return s;
    }
    // decodes the quotes and newlines so that we can use the string in javascript
    this.restoreEntities = function(s) {
        if (s == null) return "";
        s = s.replace(/&#39;/, "'");
        s = s.replace(/<br\/>/, "\n");
        return s;
    }
}
var lvsysStr = new lvsysStr();

////////////////////////////// lvsys object /////////////////////////
// this object is a singleton (only one static instance)
function lvsys() {
    this.imgCycleEnabled = true;    // use this to disable slideshows for IE6 (it interferes with droppy)
    this.imgIdArray = new Array();
    this.imgCycleIdArray = new Array();
    this.imgInterval = null;
    this.wsCS = ""; // global webservice setting

    this.prepImg = function(sImageId) {
        this.imgIdArray.push(sImageId);
    }
    this.prepCycle = function(sCycleId, sCycleEffect, iTransitionInterval, iSpeed) {
        var o = new Object();
        o.sCycleId = sCycleId;
        o.sCycleEffect = sCycleEffect;
        o.iTransitionInterval = iTransitionInterval;
        o.iSpeed = iSpeed;
        this.imgCycleIdArray.push(o);
    }

    this.imgReady = function() {

        var bImgLoaded = true;


        for (var i = 0; i < this.imgIdArray.length; i++) {
            var imgObj = document.getElementById(this.imgIdArray[i]);
            if (imgObj.complete == false) {
                var sLocation = new String(imgObj['src']);
                if (sLocation.match("/$") != "/") {
                    bImgLoaded = false;
                }
            }
        }
        return bImgLoaded;
    }

    this.imgCheckStatus = function() {
       
        if (this.imgReady()) {

            // all images are ready.
            clearInterval(this.imgInterval);

            if (this.imgCycleEnabled && typeof (lvsysCycler) == "function") {
                // start all cycles.

                var cycler = new lvsysCycler();
                var paramsArr = new Array();

                for (var i = 0; i < this.imgCycleIdArray.length; i++) {
                    var cycleParams = new lvsysCyclerParams();
                    cycleParams.id = this.imgCycleIdArray[i].sCycleId;
                    cycleParams.fx = this.imgCycleIdArray[i].sCycleEffect,
                    cycleParams.speed = this.imgCycleIdArray[i].iTransitionInterval,
                    cycleParams.timeout = this.imgCycleIdArray[i].iSpeed  // still duration
                    paramsArr[i] = cycleParams;
                }

                cycler.startSlides('.slideshow', paramsArr);

                /*    for (var i = 0; i < this.imgCycleIdArray.length; i++) {
                $("#" + this.imgCycleIdArray[i].sCycleId).cycle({
                fx: this.imgCycleIdArray[i].sCycleEffect,
                speed: this.imgCycleIdArray[i].iTransitionInterval,
                timeout: this.imgCycleIdArray[i].iSpeed  // still duration
                //delay: -2000,
                //startingSlide: 0
                });
                }*/
            }

            // reset array
            this.imgCycleIdArray = new Array();
        }
    }

    // return an array of [width,height] where we guarantee width or height is at the correct thumbsize.
    this.imgScaleRatio = function(width, height, toWidth, toHeight) {
        var ratioArray1 = new Array();
        var ratioArray2 = new Array();
        if (width > toWidth) {
            ratioArray1[0] = toWidth;
        } else {
            ratioArray1[0] = width;
        }
        ratioArray1[1] = Math.floor((ratioArray1[0] * height) / width);

        if (height > toHeight) {
            ratioArray2[1] = toHeight;
        } else {
            ratioArray2[1] = height;
        }
        ratioArray2[0] = Math.floor((ratioArray2[1] * width) / height);

        if (ratioArray1[1] < toHeight) {
            return ratioArray1;
        } else {
            return ratioArray2;
        }
    }

    this.ajaxInvokePluginCalendar = function(options) {
        var backgroundColor = $('#' + options['pluginHtmlID']).css('background-color');
        var backgroundImage = $('#' + options['pluginHtmlID']).css('background-image');
        var backgroundRepeat = $('#' + options['pluginHtmlID']).css('background-repeat');
        var backgroundPosition = $('#' + options['pluginHtmlID']).css('background-position');
        if (backgroundPosition == undefined) {
            backgroundPosition = 'center center';
        }
        $.post(
				'index.php',
		 				{
		 				    ajax: '1',
		 				    func: 'invokePlugin',
		 				    page: options['page'],
		 				    inputName: options['inputName'],
		 				    offset: options['offset'],
		 				    date: options['date'],
		 				    pluginHtmlID: options['pluginHtmlID']
		 				},
		 				function(data, textStatus) {
		 				    //alert('get pager, status:' + textStatus);
		 				    //alert('get pager, data:' + data);
		 				    if (textStatus == 'success') {
		 				        var dom = toDOM(data);
		 				        $('#' + options['pluginHtmlID'] + ' > *').remove();
		 				        $('#' + options['pluginHtmlID'])
		 				            .css('opacity', '1')
		 				            .css('z-index', '1')
		 				            .css('background-color', backgroundColor)
		 				            .css('background-image', backgroundImage)
		 				            .css('background-repeat', backgroundRepeat)
		 				            .css('background-position', backgroundPosition);
		 				        $('#' + options['pluginHtmlID']).html(dom.firstChild.innerHTML);
		 				        $('#' + options['pluginHtmlID']).attr('rel', $(data).attr('rel'));
		 				    }
		 				},
		 				'html'
		 			);
        // this div gets inserted behind the plugin div, and will fail to show its animated GIF 
        // if the plugin has a background set
        $("#" + options['pluginHtmlID']).wrapInner('<div />')
            .css('opacity', '0.5')
            .css('z-index', '2')
            .css('background', 'no-repeat url(admin/img/ajax-loader.gif) center center')
            .attr('id', options['pluginHtmlID']);
    }

    // update a plugin pager
    this.ajaxInvokePluginPager = function(options) {
        var backgroundColor = $('#' + options['pluginHtmlID']).css('background-color');
        var backgroundImage = $('#' + options['pluginHtmlID']).css('background-image');
        var backgroundRepeat = $('#' + options['pluginHtmlID']).css('background-repeat');
        var backgroundPosition = $('#' + options['pluginHtmlID']).css('background-position');
        if (backgroundPosition == undefined) {
            backgroundPosition = 'center center';
        }
        $.post(
				'index.php',
		 				{
		 				    ajax: '1',
		 				    func: 'invokePlugin',
		 				    page: options['page'],
		 				    ref: options['ref'],
		 				    inputName: options['inputName'],
		 				    pluginParams: options['pluginParams'],
		 				    pluginHtmlID: options['pluginHtmlID'],
		 				    pluginPageNo: options['pluginPageNo']
		 				},
		 				function(data, textStatus) {
		 				    //alert('get pager, status:' + textStatus);
		 				    //alert('get pager, data:' + data);
		 				    if (textStatus == 'success') {
		 				        var dom = toDOM(data);
		 				        $('#' + options['pluginHtmlID'] + ' > *').remove();
		 				        $('#' + options['pluginHtmlID'])
		 				            .css('opacity', '1')
		 				            .css('z-index', '1')
		 				            .css('background-color', backgroundColor)
		 				            .css('background-image', backgroundImage)
		 				            .css('background-repeat', backgroundRepeat)
		 				            .css('background-position', backgroundPosition);
		 				        $('#' + options['pluginHtmlID']).html(dom);
		 				    }
		 				},
		 				'html'
		 			);
        $("#" + options['pluginHtmlID']).wrapInner('<div />')
            .css('opacity', '0.5')
            .css('z-index', '2')
            .css('background', 'no-repeat url(admin/img/ajax-loader.gif) center center')
            .attr('id', options['pluginHtmlID']);

    }
    this.ajaxInvokePluginContent = function(options) {
        $.post(
				'index.php',
 				{
 				    ajax: '1',
 				    func: 'invokePlugin',
 				    page: options['page'],
 				    ref: options['ref'],
 				    inputName: options['inputName'],
 				    pluginParams: options['pluginParams'],
 				    pluginHtmlID: options['pluginHtmlID'],
 				    pluginData: options['pluginData']
 				},
 				function(data, textStatus) {
 				    //alert('get content, status:'+textStatus);
 				    //alert('get content, data:' + data);
 				    if (textStatus == 'success') {
 				        var dom = toDOM(data);
 				        $('#' + options['pluginHtmlID'] + ' > *').remove();
 				        $('#' + options['pluginHtmlID']).html(dom);
 				    }
 				},
 				'html'
 			);

    }

    //Cancels the event if it is cancelable, without stopping further propagation of the event.
    this.disableDefaultEvent = function(event) {
        if (event.preventDefault) {
            event.preventDefault();
        } else if (event.returnValue) {
            event.returnValue = false;
        }
    }

    // method called when window is ready
    this.ready = function() {
        this.imgInterval = setInterval("lvsys.imgCheckStatus()", 1000);
    }

    // method hides a group of rows
    this.uiToggleGroup = function(options) {
        var idButton = options['button'];
        var group = options['group'];
        var imgShow = options['imgShow'];
        var imgHide = options['imgHide'];

        // collapse the rows
        var img = $("#" + idButton).attr("src");
        var bShow = (img == imgShow);

        $("*[group='" + group + "']").each(function(i) {
            if (bShow) {
                if ($(this).is("tr")) {
                    $(this).css("display", ""); // jQuery show() does not work well for TR
                } else {
                    $(this).show("fast");
                }
            } else {
                if ($(this).is("tr")) {
                    $(this).css("display", "none"); // jQuery show() does not work well for TR
                } else {
                    $(this).hide("fast");
                }
            }
        });
        if (bShow) {
            $("#" + idButton).attr("src", imgHide);
        } else {
            $("#" + idButton).attr("src", imgShow);
        }
    }
}

// load lvsys when the document is ready
var lvsys = new lvsys();
$(document).ready(function() {
    lvsys.ready();
});

// base 64 encoding - modified to work in XML documents, especially in attribute strings
(function ($) {

    //var keyString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; original
    var keyString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-#"; // modified

    var uTF8Encode = function (string) {
        string = string.replace(/\x0d\x0a/g, "\x0a");
        var output = "";
        for (var n = 0; n < string.length; n++) {
            var c = string.charCodeAt(n);
            if (c < 128) {
                output += String.fromCharCode(c);
            } else if ((c > 127) && (c < 2048)) {
                output += String.fromCharCode((c >> 6) | 192);
                output += String.fromCharCode((c & 63) | 128);
            } else {
                output += String.fromCharCode((c >> 12) | 224);
                output += String.fromCharCode(((c >> 6) & 63) | 128);
                output += String.fromCharCode((c & 63) | 128);
            }
        }
        return output;
    };

    var uTF8Decode = function (input) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;
        while (i < input.length) {
            c = input.charCodeAt(i);
            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            } else if ((c > 191) && (c < 224)) {
                c2 = input.charCodeAt(i + 1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            } else {
                c2 = input.charCodeAt(i + 1);
                c3 = input.charCodeAt(i + 2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }
        }
        return string;
    }

    $.extend({
        base64XmlEncode: function (input) {
            var output = "";
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
            var i = 0;
            input = uTF8Encode(input);
            while (i < input.length) {
                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);
                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;
                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                }
                output = output + keyString.charAt(enc1) + keyString.charAt(enc2) + keyString.charAt(enc3) + keyString.charAt(enc4);
            }
            return output;
        },
        base64XmlDecode: function (input) {
            var output = "";
            var chr1, chr2, chr3;
            var enc1, enc2, enc3, enc4;
            var i = 0;
            //input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); original
            input = input.replace(/[^A-Za-z0-9\_\-\#]/g, ""); // modified
            while (i < input.length) {
                enc1 = keyString.indexOf(input.charAt(i++));
                enc2 = keyString.indexOf(input.charAt(i++));
                enc3 = keyString.indexOf(input.charAt(i++));
                enc4 = keyString.indexOf(input.charAt(i++));
                chr1 = (enc1 << 2) | (enc2 >> 4);
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                chr3 = ((enc3 & 3) << 6) | enc4;
                output = output + String.fromCharCode(chr1);
                if (enc3 != 64) {
                    output = output + String.fromCharCode(chr2);
                }
                if (enc4 != 64) {
                    output = output + String.fromCharCode(chr3);
                }
            }
            output = uTF8Decode(output);
            return output;
        }
    });
})(jQuery);