﻿/* JPositioner START */
function JPositioner(element) {
    this.x = 0;
    this.y = 0;

    var parent = element;
    while (parent.offsetParent) {
        parent = parent.offsetParent;
        this.x += parent.offsetLeft;
        this.y += parent.offsetTop;
    }

    this.x += element.offsetLeft;
    this.y += element.offsetTop;
    this.w = element.offsetWidth;
    this.h = element.offsetHeight;
}
/* JPositioner END */


/* JEvent START */
function JEvent() {
    this.events = [];
}

JEvent.prototype.getActionIdx = function(obj, evt, action) {
    if (obj && evt) {
        var curel = this.events[obj][evt];
        if (curel) {
            var len = curel.length;
            for (var i = len - 1; i >= 0; i--) {
                if (curel[i].action == action) {
                    return i;
                }
            }
        }
        else {
            return -1;
        }
    }
    return -1;
};

JEvent.prototype.addListener = function(obj, evt, action) {
    if (this.events[obj]) {
        if (this.events[obj][evt]) {
            if (this.getActionIdx(obj, evt, action, false) == -1) {
                var curevt = this.events[obj][evt];
                curevt[curevt.length] = { action: action };
            }
        }
        else {
            this.events[obj][evt] = [];
            this.events[obj][evt][0] = { action: action };
        }
    }
    else {
        this.events[obj] = [];
        this.events[obj][evt] = [];
        this.events[obj][evt][0] = { action: action };
    }
};

JEvent.prototype.removeListener = function(obj, evt, action) {
    if (this.events[obj]) {
        if (this.events[obj][evt]) {
            var idx = this.getActionIdx(obj, evt, action);
            if (idx >= 0) {
                this.events[obj][evt].splice(idx, 1);
            }
        }
    }
};

JEvent.prototype.fireEvent = function(obj, evt, args) {
    if (obj && this.events) {
        var evtel = this.events[obj];
        if (evtel) {
            var curel = evtel[evt];
            if (curel) {
                for (var i = 0; i < curel.length; i++) {
                    var action = curel[i].action;
                    return action(args);
                }
            }
        }
    }

    return true;
};
/* JEvent END */


/* JTemplate START */
function JTemplate(template) {
    this.template = template;
}

JTemplate.prototype.evaluate = function(data) {
    var result = this.template;
    if (typeof (data) == 'string') {
        result = result.replace(new RegExp("{Value}", "g"), data);
    }
    else {
        for (var property in data) {
            result = result.replace(new RegExp("{" + property + "}", "g"), eval("data." + property));
        }
    }
    return result;
}
/* JTemplate END */

/* JRepeater START */
function JRepeater() {
    // private fields
    var _jevent = new JEvent();
    var _element;
    var _template;
    var _groupByTemplate;
    var _groupByProperty;
    var _isGroupBy = false;
    var _html;

    // public fields
    this.dataSource = null;
    this.columns = 1;
    this.columnBorderStyle = "solid 1px black;";
    this.columnAlign = "center";

    // public setters
    this.setTemplate = function(value) { _template = new JTemplate(value); }
    this.setGroupBy = function(groupByProperty, groupByTemplate) {
        _groupByProperty = groupByProperty;
        _groupByTemplate = new JTemplate(groupByTemplate);
        _isGroupBy = true;
    }

    // public getters 
    this.getTemplate = function() { return _template; }
    this.getEvent = function() { return _jevent; }
    this.getHtml = function() { return _html; }

    // public events
    this.onDataBind = function(action) { this.getEvent().addListener(this, "onDataBind", action); };
    this.onDataBindRemove = function(action) { this.getEvent().removeListener(this, "onDataBind", action); };
    this.onRender = function(action) { this.getEvent().addListener(this, "onRender", action); };

    this.dataBind = function() {

        var groubByValue = "";

        // start to evaluate columns
        var html = (this.columns <= 1) ? "" : "<table>";

        // validate data source
        if (this.dataSource == null || this.dataSource.length == 0) {
            _html = html;
        }

        for (var i = 0; i < this.dataSource.length; i++) {
            // format data item
            var dataItem;
            if (typeof (this.dataSource[i]) == 'string') {
                dataItem = { "Value": this.dataSource[i], "Index": i };
            }
            else {
                dataItem = this.dataSource[i];
                dataItem.Index = i;
            }

            // fire event
            var dataArgs = { "dataItem": dataItem, "index": i };
            this.getEvent().fireEvent(this, 'onDataBind', dataArgs);

            var itemHtml = "";

            if (_isGroupBy) {
                if (groubByValue != eval("dataItem." + _groupByProperty)) {
                    itemHtml += _groupByTemplate.evaluate(dataArgs.dataItem);
                    groubByValue = eval("dataItem." + _groupByProperty);
                }
            }

            // evaluate item             
            itemHtml += this.getTemplate().evaluate(dataArgs.dataItem);

            // item evaluate columns
            if (this.columns > 1) {
                var currentColumn = ((i + 1) % this.columns);
                if (currentColumn == 1)
                    itemHtml = "<tr><td style='vertical-align:top;border:" + this.columnBorderStyle + "' align='" + this.columnAlign + "'>" + itemHtml + "</td>";
                else if (currentColumn == 0)
                    itemHtml = "<td style='vertical-align:top;border:" + this.columnBorderStyle + "' align='" + this.columnAlign + "'>" + itemHtml + "</td></tr>";
                else
                    itemHtml = "<td style='vertical-align:top;border:" + this.columnBorderStyle + "' align='" + this.columnAlign + "'>" + itemHtml + "</td>";
            }

            html += itemHtml;
        }

        // end to evaluate columns
        if (this.columns > 1) {
            var currentColumn = -1;
            var i = this.dataSource.length;

            if (this.dataSource.length > this.columns) {
                while (currentColumn != 1) {
                    i += 1;
                    currentColumn = (i % this.columns);


                    if (currentColumn == 0)
                        html += "<td></td></tr>";
                    else if (currentColumn > 1)
                        html += "<td></td>";
                }
            }
            else {
                html += "</tr>";
            }
            html += "</table>";
        }

        // set html
        _html = html;

        this.getEvent().fireEvent(this, 'onRender', html);
    }
}
/* JRepeater END */

/* JSession START */
function JSession() {
    this.getItem = function(name) {
        var results = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
        if (results)
            return (unescape(results[2]));
        else
            return null;
    }

    this.setItem = function(name, value, persistent) {

        var cookie_string = name + "=" + escape(value);
        if (persistent) {
            var expires = new Date(2010, 01, 01);
            cookie_string += "; expires=" + expires.toGMTString();
        }
        document.cookie = cookie_string;
    }

    this.deleteItem = function(name) {
        var date = new Date();  // current date & time
        date.setTime(date.getTime() - 1);
        document.cookie = name += "=; expires=" + date.toGMTString();
    }
}

var _session = new JSession();
/* JSession END */

/* JValidator START */
function JValidator() {
    var _messages = [];
    var _errorClass = null;

    this.setErrorClass = function(value) {
        _errorClass = value;
    };

    this.validate = function(id, required, message, re) {
        var control = getControl(id);

        if (required && control.value == "") {
            addMessage(control, control.title + " is required.");
        } else if (control.value != "" && re != null) {
            if (control.value.search(re) == -1) {
                if (message == null) {
                    addMessage(control, "Bad " + control.title + " format.");
                } else {
                    addMessage(control, message);
                }
            } else {
                markValid(control);
            }
        } else {
            markValid(control);
        }
    }

    this.validateLength = function(id, minLength) {
        var control = getControl(id);
        if (control.value.length < minLength)
            addMessage(control, control.title + " requires minimum " + minLength + " characters.");
        else
            markValid(control);
    };

    this.validateText = function(id) {
        var control = getControl(id);
        if (control.value.length == 0)
            addMessage(control, control.title + " is required.");
        else
            markValid(control);
    };

    this.validateEmail = function(id, required, message) {
        this.validate(id, required, message, /^[\w\.=-]+@[\w\.-]+\.[\w]{2,4}$/);
    };

    this.validatePhone = function(id, required, message) {
        this.validate(id, required, message, /^[2-9]\d{2}-\d{3}-\d{4}$/);
    };

    this.validateZip = function(id, required, message) {
        this.validate(id, required, message, /^\d{5}$/);
    };

    this.validateNumber = function(id, required, message) {
        this.validate(id, required, message, /^\d$/);
    };

    this.validateUrl = function(id, required, message) {
        this.validate(id, required, message, /^[a-zA-Z0-9\-\.]+\.(com|org|net|mil|edu|COM|ORG|NET|MIL|EDU)$/);
    };

    this.validateRadioCheck = function(id, message) {
        var control = getControl(id);

        var radio = document.getElementsByName(control.name);
        var checked = false;
        for (var i = 0; i < radio.length; i++) {
            if (radio[i].checked) {
                checked = true;
                break;
            }
        }
        if (!checked) {
            if (message == null)
                addMessage(control, control.title + " is required.");
            else
                addMessage(control, message);
        } else {
            markValid(control);
        }
    };

    this.validateCustom = function(id, message, fn) {
        var control = getControl(id);
        if (!fn(control))
            addMessage(control, message);
        else
            markValid(control);
    };

    this.isValid = function() {
        if (_messages.length == 0)
            return true;
        else
            return false;
    };

    this.getErrors = function() {
        return _messages;
    }

    function markInvalid(control) {
        if (_errorClass != null) {
            if (control.className.indexOf(" " + _errorClass) == -1)
                control.className = (control.className == "") ? _errorClass : control.className + " " + _errorClass
        }
    }

    function markValid(control) {
        if (control.className == _errorClass)
            control.className = "";
        else
            control.className = control.className.replace(" " + _errorClass, "")
    }

    function getControl(id) {
        return document.getElementById(id);
    }

    function addMessage(control, message) {
        _messages[_messages.length] = { "id": control.id, "message": message };
        markInvalid(control);
    }
}
/* JValidator END */

function JBrowser() {
    var userAgent = navigator.userAgent.toLowerCase();
    this.version = parseInt((userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1]);
    this.safari = /webkit/.test(userAgent);
    this.opera = /opera/.test(userAgent);
    this.msie = /msie/.test(userAgent) && !/opera/.test(userAgent);
    this.mozilla = /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent);
    return this;
}

var $browser = JBrowser();

var __hiddenSelects = new Array();
function JCore(element) {

    var _elem;
    if (typeof (element) == "object")
        _elem = element;
    else if (typeof (element) == "string")
        _elem = document.getElementById(element);

    this.me = _elem;

    this.locate = function() {
        var loc = { x: 0, y: 0, w: 0, h: 0 };

        if (_elem.style.position != "absolute") {
            var parent = _elem;
            while (parent.offsetParent) {
                parent = parent.offsetParent;
                loc.x += parent.offsetLeft;
                loc.y += parent.offsetTop;
            }
        }
        loc.x += _elem.offsetLeft;
        loc.y += _elem.offsetTop;
        loc.w = _elem.offsetWidth;
        loc.h = _elem.offsetHeight;
        return loc;
    }

    this.intersect = function() {
        var loc = this.locate();
        var elLoc = $core(_elem).locate();
        return (loc.x + loc.w > elLoc.x && loc.x < elLoc.x + elLoc.w && loc.y + loc.h > elLoc.y && loc.y < elLoc.y + elLoc.h);
    }

    this.undoHideSelects = function() {
        for (i = 0; i < __hiddenSelects.length; i++) {
            __hiddenSelects[i].style.visibility = "visible";
        }
        __hiddenSelects = new Array();
    }

    this.hideSelects = function() {

        if ($browser.msie && $browser.version < 7) {
            var elLoc = new $core(_elem).locate();

            var sel = document.getElementsByTagName("SELECT");

            for (var i = 0; i < sel.length; i++) {
                var loc = $core(sel[i]).locate();
                if (loc.x + loc.w > elLoc.x && loc.x < elLoc.x + elLoc.w && loc.y + loc.h > elLoc.y && loc.y < elLoc.y + elLoc.h) {
                    var obj = sel[i];
                    var shouldHide = true;
                    while (true) {
                        if (obj.style.visibility == "hidden" || obj.style.display == "none") {
                            shouldHide = false;
                            break;
                        }
                        obj = obj.parentNode;
                        if (obj == null || obj.style == null)
                            break;
                    }

                    if (shouldHide) {
                        sel[i].style.visibility = "hidden";
                        __hiddenSelects[__hiddenSelects.length] = sel[i];
                    }
                }
            }
        }
    }

    return this;
}

function JKeyBord() {

    var _jevent = new JEvent();

    this.onKeyDown = function(action) { _jevent.addListener(this, "onKeyDown", action); };
    this.onKeyUp = function(action) { _jevent.addListener(this, "onKeyUp", action); };
    this.onEnter = function(action) { _jevent.addListener(this, "onEnter", action); };
    this.onEscape = function(action) { _jevent.addListener(this, "onEscape", action); };
    this.onType = function(action) { _jevent.addListener(this, "onType", action); };

    this.type = function(e) {
        var keyCode = this.getKeyCode(e);

        switch (keyCode) {
            case 40:
                _jevent.fireEvent(this, 'onKeyDown', null);
                break;
            case 38:
                _jevent.fireEvent(this, 'onKeyUp', null);
                break;
            case 13:
                _jevent.fireEvent(this, 'onEnter', null);
                break;
            default:
                _jevent.fireEvent(this, 'onType', null);
                break;
        }
    }

    this.getKeyCode = function(e) {
        var keynum;
        if (e != null) {
            if (window.event) // IE
                keynum = e.keyCode;
            else if (e.which) // Netscape/Firefox/Opera
                keynum = e.which;
        }

        return keynum;
    };
}


function $core(element) {
    return new JCore(element);
}


/* RegExp definitions */

// matches multiple emails separated by a comma or semicolon
var emailPattern = new RegExp("^([,;]?[ a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?)+$");