﻿// ------------------------------------------------------------------------------------
// 
// Rf Client Script Library
// 
// Requires: 
// - ASP.NET AJAX Client Library
// - TrimPath template library (optional for templating support)
//
// ------------------------------------------------------------------------------------
/// <reference path="./MicrosoftAjax.js" />

$isDefined = function(objName) { return eval("typeof(" + objName + ") != 'undefined';"); }

Type.registerNamespace("Rf");

Rf.__noGlobals = false;
// ------------------------------------------------------------------------------------
// Rf/Animator.js
//
// Number animation class
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

// ------------------------------------------------------------------------------------
// Rf.Animator
// ------------------------------------------------------------------------------------

Rf.Animator = function(transform)
{
    var _this = this;

    this.speed = 0; // fps
    this.length = 2000 // msec
    this.delay = 0; // msec

    this.value = 0.0; // result value (animating from 0.0 to 1.0)
    this.progress = 0.0 // animation progress
    this.progressPerFrame = 0.0;

    this.timeElapsed = 0 // msec
    this.isRunning = false;
    this.framesTicked = 0;

    this.onStart = null; // animation start callback
    this.onEnd = null; // animation end callback
    this.onFrameTick = null; // frame tick callback

    if (transform && typeof (transform) == "function")
        this.calculateValue = transform;
    else
        this.calculateValue = Rf.Animator.Linear;

    this.start = function()
    {
        if (_this.isRunning)
            return;

        if (_this.speed > 0)
            _this.delay = 1000 / _this.speed;

        if (_this.delay > 0)
        {
            _this.progressPerFrame = (_this.delay + 0.0) / _this.length;
            _this.value = 0.0;
            _this.progress = 0.0;
            _this.timeElapsed = 0;
            _this.framesTicked = 0;
            _this.isRunning = true;

            if (_this.onStart)
                _this.onStart();

            setTimeout(_this.doFrame, _this.delay);
        }
    }

    this.stop = function()
    {
        _this.isRunning = false;
    }

    this.doFrame = function()
    {
        if (!_this.isRunning)
            return;

        _this.progress += _this.progressPerFrame;
        _this.value = _this.calculateValue(_this.progress);

        _this.timeElapsed += _this.delay;
        _this.framesTicked++;

        if (_this.onFrameTick)
            _this.onFrameTick(_this.value);

        if (_this.value == 1.0 || _this.timeElapsed >= _this.length)
        {
            _this.stop();

            if (_this.onEnd)
                _this.onEnd();
        }
        else
        {
            var timeDiff = _this.length - _this.timeElapsed; // time left to amination end

            if (timeDiff > _this.delay) // if greater than frame duration
                setTimeout(_this.doFrame, _this.delay); // do another frame normally
            else
                setTimeout(_this.doFrame, timeDiff); // else do next frame in shorter time
        }
    }
}

Rf.Animator.Linear = function(value)
{
    return value;
}

Rf.Animator.ReversedLinear = function(value)
{
    return 1.0 - value;
}

Rf.Animator.Quadratic = function(value)
{
    return value * value;
}

Rf.Animator.ReversedQuadratic = function(value)
{
    return Rf.Animator.Cubic(1.0 - value);
}

Rf.Animator.Cubic = function(value)
{
    return Math.pow(value, 3);
}

Rf.Animator.ReversedCubic = function(value)
{
    return Rf.Animator.Cubic(1.0 - value);
}


Rf.Animator.registerClass("Rf.Animator");

// ----------------------------------------------------------------------------









// ------------------------------------------------------------------------------------
// Rf.Controls.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

Type.registerNamespace("Rf.Controls");

// ------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------
// Rf.Date.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");


// ------------------------------------------------------------------------------------
// Date extensions
// ------------------------------------------------------------------------------------

Date.prototype.toUTC = function()
{
    return new Date(Date.UTC(
        this.getFullYear(),
        this.getMonth(),
        this.getDate(),
        this.getHours(),
        this.getMinutes(),
        this.getSeconds(),
        this.getMilliseconds()));
}

// ------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------
// Rf/DomUtility.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

// ------------------------------------------------------------------------------------
// Rf.DomUtility
// ------------------------------------------------------------------------------------

Type.registerNamespace("Rf.DomUtility");

Rf.DomUtility.__createElement = document.createElement;

if (document.all) // if ie
{
    document.createElement = function(tagName)
    {
        return Rf.DomUtility.applyDomInheritance(Rf.DomUtility.__createElement(tagName), new Object());
    }
}

Rf.DomUtility.applyDomInheritance = function(element,baseObject)
{
    for (method in baseObject)
        element[method] = baseObject[method];

    return element;
}

Rf.DomUtility.getElementStyle = function(el, styleProp)
{
    var x = el;
    var y = 0;

    if (typeof (el) != "object")
        x = document.getElementById(el);

    if (x.currentStyle)
        y = x.currentStyle[styleProp];
    else if (window.getComputedStyle)
        y = document.defaultView.getComputedStyle(x, null).getPropertyValue(styleProp);

    return y;
}

Rf.DomUtility.getElementStyleNumeric = function(el, styleProp, unit)
{
    if (!unit)
        unit = "px";

    var value = Rf.DomUtility.getElementStyle(el, styleProp);

    if (!value)
        return Number.NaN;

    return parseFloat(value.replace(unit, ""));
}

Rf.DomUtility.insertAtCursor = function(obj, text)
{
    obj.focus();

    if (document.selection)
    {
        var range = document.selection.createRange();
        range.text = text;
        range.select();
    }
    else if (obj.selectionStart)
    {
        var start = obj.selectionStart;
        var end = obj.selectionEnd;
        var pos = (obj.value.substr(0, start) + text).length;

        obj.value = obj.value.substr(0, start) + text + obj.value.substr(end, obj.value.length);
        obj.setSelectionRange(pos, pos);
    }
    else
    {
        // Fallback for any other browser   
    }
}

Rf.DomUtility.getSelectionText = function(obj)
{
    if (document.selection)
    {
        var range = document.selection.createRange();
        return range.text;
    }
    else if (obj.selectionStart)
    {
        var start = obj.selectionStart;
        var end = obj.selectionEnd;
        var result = obj.value.substr(start, end - start);

        return result;
    }
    else
    {
        // Fallback for any other browser
        return "";
    }
}

Rf.DomUtility.cloneElement = function(origin)
{
    /// <summary>Clones innerHTML along with style and class attributes.</summary>
    // TODO: make it copy all element attributes

    var result = document.createElement(origin.tagName);
    result.innerHTML = origin.innerHTML;

    if (origin.style.cssText)
        result.style.cssText = origin.style.cssText;
    else
        result.setAttribute("style", origin.getAttribute("style"));

    if (origin.className)
        result.className = origin.className;

    return result;
}

Rf.DomUtility.getElementByClassName = function(attributeValue, scope)
{
    /// <summary>Finds an element with a given class name. Returns null if not found.
    /// Scope parameter is optional. The default scope is document.documentElement.</summary>
    var root = document.documentElement;

    if (scope)
        root = scope;

    return Rf.DomUtility.getElementByAttribute("className", attributeValue, false, root);
}


Rf.DomUtility.getElementByAttribute = function(attributeName, attributeValue, exactMatch, scope)
{
    var root = document.documentElement;
    var result = null;
    var exact = false;

    if (exactMatch)
        exact = true;

    if (scope)
        root = scope;

    for (var n = 0; n < root.childNodes.length; n++)
    {
        if (Rf.DomUtility.elementHasAttribute(root.childNodes[n], attributeName, attributeValue, exact))
            return scope.childNodes[n];
    }

    for (n = 0; n < root.childNodes.length; n++)
    {
        result = Rf.DomUtility.getElementByAttribute(attributeName, attributeValue, exact, root.childNodes[n]);

        if (result != null)
            break;
    }

    return result;
}

Rf.DomUtility.getElementsByAttribute = function(attributeName, attributeValue, exactMatch, scope)
{
    var root = document.documentElement;
    var result = [];
    var exact = false;

    if (exactMatch)
        exact = true;

    if (scope)
        root = scope;

    for (var n = 0; n < root.childNodes.length; n++)
    {
        var node = root.childNodes[n];

        if (Rf.DomUtility.elementHasAttribute(node, attributeName, attributeValue, exact))
            result.push(node);
    }

    for (n = 0; n < root.childNodes.length; n++)
    {
        node = root.childNodes[n];

        result = result.concat(Rf.DomUtility.getElementsByAttribute(attributeName, attributeValue, exact, node));
    }

    return result;
}

Rf.DomUtility.elementHasAttribute = function(element, attributeName, attributeValue, exactMatch)
{
    if (!element[attributeName])
        return false;

    var attribute = element[attributeName];

    if (exactMatch)
        return attribute == attributeValue;

    var index = attribute.indexOf(attributeValue);

    if (index < 0)
        return false;

    var indexBefore = index - 1;
    var indexAfter = index + attributeValue.length;

    if (index == 0) // is first
        return attribute.length == attributeValue.length || attribute.charAt(indexAfter) == " ";
    else if (index + attributeValue.length == attribute.length) // is last
        return attribute.charAt(indexBefore) == " ";
    else // middle?
        return attribute.charAt(indexBefore) == " " && attribute.charAt(indexAfter) == " ";

    return false;
}

// ------------------------------------------------------------------------------------

// ------------------------------------------------------------------------------------
// Rf/Extensions.js
//
// JavaScript and DOM base type extensions
// ------------------------------------------------------------------------------------






// ------------------------------------------------------------------------------------
// Object extensions
// ------------------------------------------------------------------------------------

Object.prototype.clone = function()
{
    /// <summary>Creates a simple clone of an object. Use with caution. 
    /// The cloned objects are not always identical to their sources</summary>

    myObj = this;

    if (typeof (myObj) != 'object')
        return myObj;

    if (myObj == null)
        return myObj;

    var myNewObj = new Object();

    for (var i in myObj)
    {
        myNewObj[i] = Object.clone( myObj[i] );
    }

    return myNewObj;
}

var $byId = function(elementId)
{
    var result;
    
    if (typeof (elementId) == "string")
        result = $get(elementId);
    else
        result = elementId;

    if (document.all)
        Rf.DomUtility.applyDomInheritance(result, new Object());

    return result;
}
Object.prototype.$byId = function(elementId) { return $byId(elementId, this); }

var $byClass = Object.prototype.$byClass = function(elementClassName, scope)
{
    var result;

    if (typeof (elementClassName) == "string")
        result = Rf.DomUtility.getElementByClassName(elementClassName, scope);
    else
        result = elementClassName;

    if (document.all)
        Rf.DomUtility.applyDomInheritance(result, new Object());

    return result;
}
Object.prototype.$byClass = function(elementClassName) { return $byClass(elementClassName, this); }


var $byAttribute = Object.prototype.$byAttribute = function(attributeName, attributeValue, scope)
{
    var result;
    
    if (typeof (attributeName) == "string")
        result = Rf.DomUtility.getElementByAttribute(attributeName, attributeValue, true, scope);
    else
        result = attributeName;

    if (document.all)
        Rf.DomUtility.applyDomInheritance(result, new Object());
        
    return result;
}
Object.prototype.$byAttribute = function(attributeName, attributeValue) { return $byAttribute(elementClassName, attributeValue, this); }

var $clone = function(element)
{
    if (typeof (element.innerHTML) != "undefined")
        return Rf.DomUtility.cloneElement(element);
    else
        return element.clone();
}

Object.prototype.$clone = function()
{
    return $clone(this);
}







// ------------------------------------------------------------------------------------
// Function extensions
// ------------------------------------------------------------------------------------

Function.prototype.$delegate = Function.prototype.createDelegate = function(obj)
{
    return Function.createDelegate(obj, this);
}

// ------------------------------------------------------------------------------------




// ------------------------------------------------------------------------------------
// String extensions
// ------------------------------------------------------------------------------------

String.prototype.toCapitalic = function()
{
    return this.toLocaleLowerCase().replace(
        /(^|\s)\S/gi,
        function(myStr) { return myStr.toLocaleUpperCase(); });
}

// ------------------------------------------------------------------------------------




// ------------------------------------------------------------------------------------
// Window extensions
// ------------------------------------------------------------------------------------


window.setCookie = function(name, value, days)
{
    var expires;
    
    if (days)
    {
        var date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
        expires = "; expires=" + date.toGMTString();
    }
    else
        expires = "";
        
    document.cookie = name + "=" + value + expires + "; path=/";
}

window.getCookie = function(name)
{
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++)
    {
        var c = ca[i];
        while (c.charAt(0) == ' ') c = c.substring(1, c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
    }
    return null;
}

window.clearCookie = function(name)
{
    window.setCookie(name, "", -1);
}

// ------------------------------------------------------------------------------------









// ------------------------------------------------------------------------------------
// Document extensions
// ------------------------------------------------------------------------------------

document.getHeight = function()
{
    return document.getElementsByTagName('body')[0].offsetHeight;
}

document.getWidth = function()
{
    if (document.width)
        return document.width;
    else
        return document.body.offsetWidth;
}

// ------------------------------------------------------------------------------------

// ------------------------------------------------------------------------------------
// Rf/FormUtility.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

// ------------------------------------------------------------------------------------
// Rf.FormUtility
// ------------------------------------------------------------------------------------

Type.registerNamespace("Rf.FormUtility");

Rf.FormUtility.SetSelect = function(selectElement, value)
{
    if (typeof (selectElement) != "object")
        selectElement = $get(selectElement);

    if (!selectElement)
        throw "Invalid select form object.";

    for (var n = 0; n < selectElement.length; n++)
    {
        if (selectElement[n].value.toString() == value.toString())
        {
            selectElement.selectedIndex = n;
            break;
        }
    }
}

// ------------------------------------------------------------------------------------

















// ------------------------------------------------------------------------------------
// Rf/OnLoad.js
//
// Script loading helpers
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

// ------------------------------------------------------------------------------------
// Rf.OnLoad
// ------------------------------------------------------------------------------------

Rf.OnLoad = new Object();
Rf.OnLoad.handlers = new Array();

Rf.OnLoad.addFunction = function(func)
{
    // TODO: improve this. Make it work like OnInit.
    var oldonload = window.onload;

    if (typeof window.onload != 'function')
    {
        window.onload = func;
    }
    else
    {
        window.onload = function()
        {
            oldonload();
            func();
        }
    }
}


Rf.OnLoad.register = function(handler)
{
    var e = Function._validateParams(arguments, [
        { name: "handler", type: Function }
    ]);
    if (e) throw e;

    //if ( !Rf.OnLoad.Registered( handler ) )
    Rf.OnLoad.handlers.push(handler);
}

Rf.OnLoad.perform = function()
{
    for (n = 0; n < Rf.OnLoad.handlers.length; n++)
    {
        var handler = Rf.OnLoad.handlers[n];

        if (handler)
            handler();
    }
}

// ------------------------------------------------------------------------------------




// ------------------------------------------------------------------------------------
// Rf.OnInit
// ------------------------------------------------------------------------------------

Rf.OnInit = new Object();
Rf.OnInit.defaultPriority = 100;
Rf.OnInit.handlers = new Array();
Rf.OnInit.reached = false;
Rf.OnInit.performed = false;

Rf.OnInit.register = function(handler, priority)
{
    if (!priority)
        priority = Rf.OnInit.defaultPriority

    Rf.OnInit.handlers.push({ "priority": priority, "handler": handler });
}

Rf.OnInit.perform = function()
{
    Rf.OnInit.reached = true;

    Rf.OnInit.handlers.sort(
    function(e1, e2)
    {
        if (e1.priotity == e2.priority) return 0;
        return e1.priority < e2.priority ? -1 : 1;
    });

    for (n = 0; n < Rf.OnInit.handlers.length; n++)
    {
        var handler = Rf.OnInit.handlers[n].handler;

        if (handler)
            handler();
    }

    Rf.OnInit.performed = true;
}

// ------------------------------------------------------------------------------------






// ------------------------------------------------------------------------------------
// Rf.Controls.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

// ------------------------------------------------------------------------------------
// Rf.Screen
// ------------------------------------------------------------------------------------

Type.registerNamespace("Rf.Screen");

Rf.Screen.getCursorX = function(evt)
{
    if (evt.pageX)
        return evt.pageX;
    else if (evt.clientX)
        return evt.clientX + (document.documentElement.scrollLeft ?
        document.documentElement.scrollLeft :
        document.body.scrollLeft);
    else
        return null;
}

Rf.Screen.getCursorY = function(evt)
{
    if (evt.pageY)
        return evt.pageY;
    else if (evt.clientY)
        return evt.clientY + (document.documentElement.scrollTop ?
        document.documentElement.scrollTop :
        document.body.scrollTop);
    else
        return null;
}

Rf.Screen.getViewportWidth = function()
{
    return self.innerWidth || (document.documentElement.clientWidth || document.body.clientWidth);
}

Rf.Screen.getViewportHeight = function()
{
    return self.innerHeight || (document.documentElement.clientHeight || document.body.clientHeight);
}

Rf.Screen.getScrollX = function()
{
    return document.documentElement.scrollLeft;
}

Rf.Screen.getScrollY = function()
{
    return document.documentElement.scrollTop;
}

// ------------------------------------------------------------------------------------



// ------------------------------------------------------------------------------------
// Rf/Template.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

// ------------------------------------------------------------------------------------
// Template
// ------------------------------------------------------------------------------------

Type.registerNamespace("Rf.Template");

Rf.Template.fill = function(element)
{
    if (!element)
        return;

    if (!element.__template)
        element.__template = Rf.Template.getTemplate(element);

    element.innerHTML = Rf.Template.parseFinal(element.__template, arguments);
}

Rf.Template.parseString = function(template)
{
    if (!template)
        return "";

    if (arguments.length < 2)
        return template;

    return Rf.Template.parseFinal(template, arguments);
}


Rf.Template.parseElement = function(templateElement)
{
    if (typeof (templateElement) != "object")
        templateElement = $get(templateElement);

    var template = Rf.Template.getTemplate(templateElement);

    if (!template)
        return "";

    if (arguments.length < 2)
        return template;

    return Rf.Template.parseFinal(template, arguments);
}

Rf.Template.getTemplate = function(templateElement)
{
    var result = "";

    for (var n = 0; n < templateElement.childNodes.length; n++)
    {
        var node = templateElement.childNodes[n];

        if (node.nodeType == 8) // 8 = html comment
        {
            result = node.nodeValue
            break;
        }
    }

    return result;
}

Rf.Template.getTemplateByID = function(templateElementID)
{
    return Rf.Template.getTemplate($get(templateElementID));
}

Rf.Template.parseFinal = function(template, allArgs)
{
    var result = template;
    var search = "";

    var dataObject = new Object();

    for (var n = 1; n < allArgs.length; n++)
    {
        if (typeof (allArgs[n]) == "string")
        {
            if (allArgs.length <= n + 1 || allArgs[n] == allArgs[n + 1])
                continue;

            dataObject[allArgs[n]] = allArgs[n + 1];

            n++;
        }
        else
        {
            for (attribute in allArgs[n])
            {
                dataObject[attribute] = allArgs[n][attribute];
            }
        }
    }

    return template.process(dataObject);
}

// ------------------------------------------------------------------------------------












// ------------------------------------------------------------------------------------
// Rf/WebMethod.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

// ------------------------------------------------------------------------------------
// WebMethod
// ------------------------------------------------------------------------------------

Rf.WebMethod = function(serviceName, methodName)
{
    var _this = this;

    var _requestUrl = null;

    this.serviceName = serviceName;

    this.methodName = methodName;

    if (!_this.serviceName || !_this.methodName)
        throw "Invalid WebMethod constructor parameters";

    this.onCompleted = function() { }

    this.onFailed = function() { }

    this.timeout = Rf.WebMethod.requestTimeout;

    this.useHttpGet = false;

    this.userContext = "none";

    this.acceptLanguage = Sys.CultureInfo.CurrentCulture.name;

    this.invoke = function()
    {
        var path = Rf.WebMethod.servicesUrl + _this.serviceName + Rf.WebMethod.servicesUrlSuffix;
        var params = arguments.length > 0 ?
                        (arguments.length > 1 ? Rf.WebMethod.createRequestParameters(arguments) : arguments[0]) :
                        {};

        var request = new Sys.Net.WebRequest();
        request.get_headers()['Content-Type'] = 'application/json; charset=utf-8';
        request.get_headers()['Accept-Language'] = String.format("{0},{1};q=0.5", _this.acceptLanguage, _this.acceptLanguage.substr(0, _this.acceptLanguage.indexOf("-")));

        var urlParams = params;
        if (!_this.useHttpGett || !urlParams) urlParams = {};
        request.set_url(Sys.Net.WebRequest._createUrl(path + "/" + encodeURIComponent(_this.methodName), urlParams));

        var body = null;
        if (!_this.useHttpGett)
        {
            body = Sys.Serialization.JavaScriptSerializer.serialize(params);
            if (body === "{}") body = "";
        }
        request.set_body(body);
        request.add_completed(onComplete);

        if (_this.timeout && _this.timeout > 0) request.set_timeout(_this.timeout);
        request.invoke();

        function onComplete(response, eventArgs)
        {
            if (response.get_responseAvailable())
            {
                var statusCode = response.get_statusCode();
                var result = null;

                try
                {
                    var contentType = response.getResponseHeader("Content-Type");
                    if (contentType.startsWith("application/json"))
                    {
                        result = response.get_object();
                    }
                    else if (contentType.startsWith("text/xml"))
                    {
                        result = response.get_xml();
                    }
                    else
                    {
                        result = response.get_responseData();
                    }
                } catch (ex)
                {
                }
                var error = response.getResponseHeader("jsonerror");
                var errorObj = (error === "true");
                if (errorObj)
                {
                    if (result)
                    {
                        result = new Sys.Net.WebServiceError(false, result.Message, result.StackTrace, result.ExceptionType);
                    }
                }
                else if (contentType.startsWith("application/json"))
                {
                    if (!result || typeof (result.d) === "undefined")
                    {
                        throw Sys.Net.WebServiceProxy._createFailedError(_this.methodName, String.format(Sys.Res.webServiceInvalidJsonWrapper, _this.methodName));
                    }
                    result = result.d;
                }
                if (((statusCode < 200) || (statusCode >= 300)) || errorObj)
                {
                    if (_this.onFailed)
                    {
                        if (!result || !errorObj)
                        {
                            result = new Sys.Net.WebServiceError(false, String.format(Sys.Res.webServiceFailedNoMsg, _this.methodName), "", "");
                        }
                        result._statusCode = statusCode;
                        _this.onFailed(result, _this.userContext, _this.methodName);
                    }
                    else
                    {
                        var error;
                        if (result && errorObj)
                        {
                            error = result.get_exceptionType() + "-- " + result.get_message();
                        }
                        else
                        {
                            error = response.get_responseData();
                        }
                        throw Sys.Net.WebServiceProxy._createFailedError(_this.methodName, String.format(Sys.Res.webServiceFailed, _this.methodName, error));
                    }
                }
                else if (_this.onCompleted)
                {
                    _this.onCompleted(result, _this.userContext, _this.methodName);
                }
            }
            else
            {
                var msg;
                if (response.get_timedOut())
                {
                    msg = String.format(Sys.Res.webServiceTimedOut, _this.methodName);
                }
                else
                {
                    msg = String.format(Sys.Res.webServiceFailedNoMsg, _this.methodName)
                }
                if (_this.onFailed)
                {
                    _this.onFailed(new Sys.Net.WebServiceError(response.get_timedOut(), msg, "", ""), _this.userContext, _this.methodName);
                }
                else
                {
                    throw Sys.Net.WebServiceProxy._createFailedError(methodName, msg);
                }
            }
        }
    }
}

Rf.WebMethod.createRequestParameters = function(params)
{
    var result = new Object();

    for (var n = 0; (n + 1) < params.length; n += 2)
    {
        result[params[n]] = params[n + 1];
    }

    return result;
}

Rf.WebMethod.servicesUrl = "http://cantoso.org/WebServices/";
Rf.WebMethod.servicesUrlSuffix = ".asmx";
Rf.WebMethod.requestTimeout = 3000;

Rf.WebMethod.registerClass("Rf.WebMethod");

// ------------------------------------------------------------------------------------







// ------------------------------------------------------------------------------------
// Rf.WebService
// ------------------------------------------------------------------------------------

Rf.WebService = function(serviceName)
{
    var _this = this;

    this.serviceName = serviceName;

    this.call(methodName, completedCallback, failedCallback, parameters)
    {
        var wmMethod = new Rf.WebMethod(_this.serviceName, methodName);
        wmMethod.onCompleted = completedCallback;
        wmMethod.onFailed = failedCallback;
        
        wmMethod.invoke(parameters);
    }
}

Rf.WebService.registerClass("Rf.WebService");

// ------------------------------------------------------------------------------------





// ------------------------------------------------------------------------------------
// Rf/Controls/BoxPanel.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.Controls"))
    Type.registerNamespace("Rf.Controls");

// ------------------------------------------------------------------------------------
// BoxPanel
// ------------------------------------------------------------------------------------

Rf.Controls.BoxPanel = function(contentElement, boxElementOrigin)
{
    var _this = this;

    this.className_Visible = "visible";
    this.className_Hidden = "hidden";

    this.className_Original = "";

    this.contentElement = contentElement;

    this.boxElement = null;
    this.boxElementOrigin = Rf.Controls.BoxPanel.boxElementID;

    this.holderElementClassName = Rf.Controls.BoxPanel.boxElementHolderClass;
    this.holderElement = null;

    this.loadingControl = null;

    if (boxElementOrigin)
        _this.boxElementOrigin = boxElementOrigin;

    this.isVisible = true;

    this.initialize = function()
    {
        if (typeof (_this.contentElement) != "object")
            _this.contentElement = $get(_this.contentElement);

        if (typeof (_this.boxElementOrigin) != "object")
            _this.boxElementOrigin = $get(_this.boxElementOrigin);

        if (!_this.boxElementOrigin)
            throw "Invalid box element.";

        if (!_this.contentElement)
            throw "Invalid content element.";

        _this.boxElement = Rf.DomUtility.cloneElement(_this.boxElementOrigin);

        if (_this.boxElement.className)
            _this.className_Original = _this.boxElement.className;

        _this.holderElement = Rf.DomUtility.getElementByClassName(_this.holderElementClassName, _this.boxElement);

        _this.contentElement.parentNode.replaceChild(_this.boxElement, _this.contentElement);
        _this.holderElement.appendChild(_this.contentElement);

        _this.loadingControl = new Rf.Controls.LoadingControl(_this.contentElement);

        if (_this.isVisible)
            _this.show();
        else
            _this.hide();
    }

    this.show = function()
    {
        _this.isVisible = true;
        _this.boxElement.className = _this.className_Original + " " + _this.className_Visible;
    }

    this.hide = function()
    {
        _this.isVisible = false;
        _this.boxElement.className = _this.className_Original + " " + _this.className_Hidden;
    }

    this.setLoading = function(isLoading)
    {
        if (isLoading)
            _this.loadingControl.start();
        else
            _this.loadingControl.stop();
    }

    if (Rf.OnInit.reached)
        this.initialize();
    else
        Rf.OnInit.register(this.initialize);
}

Rf.Controls.BoxPanel.boxElementID = "Rf.Controls.BoxPanel";
Rf.Controls.BoxPanel.boxElementHolderClass = "Rf.Controls.BoxPanelHolder";

Rf.Controls.BoxPanel.registerClass("Rf.Controls.BoxPanel");

// ------------------------------------------------------------------------------------











// ------------------------------------------------------------------------------------
// Rf/Controls/Button.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.Controls"))
    Type.registerNamespace("Rf.Controls");

// ------------------------------------------------------------------------------------
// Generic button class
// ------------------------------------------------------------------------------------
    
Rf.Controls.Button = function(buttonElement)
{
    var _this = this;

    this.disabledClassName = "disabled";
    this.buttonClassName = "button";
    this.hiddenClassName = "hidden";

    this.buttonElement = buttonElement;

    this.visible = true;
    this.enabled = true;

    this.onClick = function() { };

    var initialize = this.initialize = function()
    {
        if (typeof (_this.buttonElement) != "object")
            _this.buttonElement = $get(_this.buttonElement);

        if (!_this.buttonElement)
            throw "Invalid button element.";

        _this.enabled = !Rf.DomUtility.elementHasAttribute("className", _this.disabledClassName, false, _this.buttonElement);
        _this.visible = !Rf.DomUtility.elementHasAttribute("className", _this.hiddenClassName, false, _this.buttonElement);

        //$clearHandlers( _this.buttonElement, "click" );
        $addHandler(_this.buttonElement, "click",
            function(evt) { evt.preventDefault(); _this.onClickCallback(); });

        if (_this.buttonElement.onclick)
            _this.onClick = _this.buttonElement.onclick;

        if (_this.buttonElement.className)
            _this.buttonClassName = _this.buttonElement.className;

        //_this.buttonElement.onclick = function() { _this.onClickCallback(); return false; };
    }

    var setEnabled = this.setEnabled = function(value)
    {
        _this.enabled = value;
        _this.updateButtonElementState();
    }

    var setVisible = this.setVisible = function(value)
    {
        _this.visible = value;
        _this.updateButtonElementState();
    }

    var updateButtonElementState = this.updateButtonElementState = function()
    {
        var className = _this.buttonClassName;

        if (!_this.enabled)
            className += " " + _this.disabledClassName;

        if (!_this.visible)
            className += " " + _this.hiddenClassName;

        _this.buttonElement.className = className;
    }

    var onClickCallback = this.onClickCallback = function()
    {
        if (_this.enabled && _this.visible)
            _this.onClick();

        return false;
    }

    if (Rf.OnInit.reached)
        this.initialize();
    else
        Rf.OnInit.register(this.initialize);
}

Rf.Controls.Button.registerClass("Rf.Controls.Button");

// ------------------------------------------------------------------------------------









// ------------------------------------------------------------------------------------
// Rf/Controls/ClickEditor.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.Controls"))
    Type.registerNamespace("Rf.Controls");

// ------------------------------------------------------------------------------------
// ClickEditor
// ------------------------------------------------------------------------------------

Rf.Controls.ClickEditor = function(hostElement, multiline, serviceName, getterMethodName, setterMethodName, format)
{
    var _this = this;

    var _originalHostClassName = "";
    var _originalHostDisplayMode = "";

    var _isAborting = false;
    var _isLoading = false;
    var _isSaving = false;
    var _isEditing = false;

    this.isMultiline = multiline;
    this.isEnabled = true;
    this.hoverClassName = Rf.Controls.ClickEditor.hoverClassName;
    this.inputClassName = Rf.Controls.ClickEditor.inputClassName;

    this.autoStretch = true;

    this.serviceName = serviceName;
    this.getterMethodName = getterMethodName;
    this.setterMethodName = setterMethodName;

    this.stripHTML = false;
    this.newLinesAsHTML = false;

    if (format)
        this.format = format;
    else
        this.format = null;

    this.getterArgs = {};
    this.setterArgs = null;

    this.setterValueArgumentName = "value";

    this.hostElement = hostElement;
    this.editorElement = null;

    this.emptyAs = "";
    this.tmpValue = "";

    this.initialize = function()
    {
        if (typeof (_this.hostElement) != "object")
            _this.hostElement = $get(_this.hostElement);

        if (!_this.hostElement)
            throw "Invalid ClickEditor host element."

        if (_this.isMultiline)
        {
            _this.editorElement = document.createElement("textarea");
        }
        else
        {
            _this.editorElement = document.createElement("input");
            _this.editorElement["type"] = "text";
        }

        _this.hostElement.parentNode.insertBefore(_this.editorElement, _this.hostElement);
        _this.editorElement.style["display"] = "none";
        _this.editorElement.className = _this.inputClassName;

        try
        {
            _this.adjustEditorDimensions();
        }
        catch (ex)
        {
            alert(ex.message);
        }

        if (_this.hostElement.className)
            _originalHostClassName = _this.hostElement.className;

        if (_this.hostElement.style["display"])
            _originalHostDisplayMode = _this.hostElement.style["display"];

        // Host element handlers
        $addHandler(_this.hostElement.parentNode, "mouseover",
            function(evt) { evt.preventDefault(); _this.hostElement_mouseOver(); });

        $addHandler(_this.hostElement.parentNode, "mouseout",
            function(evt) { evt.preventDefault(); _this.hostElement_mouseOut(); });

        $addHandler(_this.hostElement.parentNode, "click",
            function(evt) { evt.preventDefault(); _this.hostElement_click(); });

        $addHandler(_this.editorElement, "blur",
            function(evt) { evt.preventDefault(); _this.editorElement_blur(); });

        $addHandler(_this.editorElement, "keypress",
            function(evt) { _this.editorElement_keypress(evt); });
    }

    this.adjustEditorDimensions = function()
    {
        var editorStyleWidth = Rf.DomUtility.getElementStyleNumeric(_this.editorElement, "width");
        var editorStyleHeight = Rf.DomUtility.getElementStyleNumeric(_this.editorElement, "height");

        var editorStyleMinWidth = Rf.DomUtility.getElementStyleNumeric(_this.editorElement, "min-width");
        var editorStyleMinHeight = Rf.DomUtility.getElementStyleNumeric(_this.editorElement, "min-height");

        var editorStyleMaxWidth = Rf.DomUtility.getElementStyleNumeric(_this.editorElement, "max-width");
        var editorStyleMaxHeight = Rf.DomUtility.getElementStyleNumeric(_this.editorElement, "max-height");

        if (!editorStyleWidth)
            editorStyleWidth = 0;

        if (!editorStyleHeight)
            editorStyleHeight = 0;

        if (!editorStyleMinWidth)
            editorStyleMinWidth = 0;

        if (!editorStyleMinHeight)
            editorStyleMinHeight = 0;

        if (!editorStyleMaxWidth)
            editorStyleMaxWidth = 0;

        if (!editorStyleMaxHeight)
            editorStyleMaxHeight = 0;

        if (!editorStyleHeight && _this.isMultiline)
        {
            var height = editorStyleMinHeight;

            if (_this.autoStretch && _this.hostElement.offsetHeight > height)
                height = _this.hostElement.offsetHeight;

            if (editorStyleMaxHeight > 0 && height > editorStyleMaxHeight)
                height = editorStyleMaxHeight;

            if (height != 0)
                _this.editorElement.style["height"] = height + "px";
        }

        if (!editorStyleWidth)
        {
            var width = editorStyleMinWidth;

            if (_this.autoStretch && _this.hostElement.offsetWidth > width)
                width = _this.hostElement.offsetWidth;

            if (editorStyleMaxWidth > 0 && width > editorStyleMaxWidth)
                width = editorStyleMaxWidth;

            if (width != 0)
                _this.editorElement.style["width"] = width + "px";
        }
    }

    this.showEditor = function()
    {
        _isAborting = false;
        _isSaving = false;

        _this.hostElement.style["display"] = "none";
        try
        { 
            _this.editorElement.style["display"] = "-moz-inline-box";
        }
        catch (ex)
        {
        }
        
        _this.editorElement.style["display"] = "inline-block";

        _this.editorElement.focus();

        _isEditing = true;
    }

    this.closeEditor = function()
    {
        _isLoading = false;
        _isEditing = false;

        _this.hostElement.style["display"] = _originalHostDisplayMode;
        _this.editorElement.style["display"] = "none";
    }

    this.loadEdit = function()
    {
        _isLoading = true;

        // async load
        var wmGet = new Rf.WebMethod(_this.serviceName, _this.getterMethodName);

        wmGet.onCompleted = _this.loadEdit_onComplete;
        wmGet.onFailed = _this.loadEdit_onError;

        _this.setLoading(true);
        _this.showEditor();

        wmGet.invoke(_this.getterArgs);
    }

    this.loadEdit_onComplete = function(data)
    {
        _isLoading = false;
        _this.setLoading(false);
        _this.showEditor();

        if (data == null)
            _this.editorElement.value = "";
        else
        {
            data = _this.processValueReversed(data);

            if (data.localeFormat && _this.format)
                _this.editorElement.value = data.localeFormat(_this.format);
            else
                _this.editorElement.value = data;
        }
    }

    this.loadEdit_onError = function()
    {
        _isLoading = false;
        _this.setLoading(false);
        // some error msg    
    }

    this.submitEdit = function()
    {
        _isSaving = true;
        // async save

        var wmGet = new Rf.WebMethod(_this.serviceName, _this.setterMethodName);

        wmGet.onCompleted = _this.submitEdit_onComplete;
        wmGet.onFailed = _this.submitEdit_onError;

        if (!_this.setterArgs)
            _this.setterArgs = _this.getterArgs;

        _this.setterArgs[_this.setterValueArgumentName] = _this.processValue(_this.editorElement.value);

        _this.setLoading(true);
        _this.tmpValue = _this.setterArgs[_this.setterValueArgumentName];

        wmGet.invoke(_this.setterArgs);
    }

    this.setLoading = function(value)
    {
        if (value)
        {
            _this.editorElement.enabled = false;
            _this.tmpValue = _this.editorElement.value;
            _this.editorElement.value = "...";
        }
        else
        {
            _this.editorElement.enabled = true;
            _this.editorElement.value = _this.tmpValue;
        }
    }

    this.processValue = function(value)
    {
        if (typeof (value) != "string")
            return value;

        if (_this.stripHTML)
        {
            value =
                value.replace(/<\s*\/?\s*\w+\s*\/?\s*>/gim, "");

            if (_this.newLinesAsHTML)
            {
                value =
                    value.replace(/\n/gim, "\n<br/>");
            }
        }

        return value;
    }

    this.processValueReversed = function(value)
    {
        if (typeof (value) != "string")
            return value;

        if (_this.stripHTML)
        {
            value =
                value.replace(/<\s*\/?\s*\w+\s*\/?\s*>/gim, "");
        }

        return value;
    }

    this.submitEdit_onComplete = function()
    {
        _isSaving = false;

        if (_this.tmpValue.length > 0)
            _this.hostElement.innerHTML = _this.tmpValue;
        else
            _this.hostElement.innerHTML = _this.emptyAs;

        _this.closeEditor();
        _this.setLoading(false);
    }

    this.submitEdit_onError = function()
    {
        _isSaving = false;
        _this.setLoading(false);
        // some error msg
    }

    this.abortEdit = function()
    {
        _isAborting = true;
        _this.closeEditor();
    }

    this.editorElement_keypress = function(evt)
    {
        var escCharCode = 27;
        var enterCharCode = 13;

        if (evt.charCode == escCharCode)
            _this.abortEdit();
        else if (evt.charCode == enterCharCode && !_this.isMultiline)
            _this.submitEdit();
    }

    this.editorElement_blur = function()
    {
        if (_isLoading || _isSaving)
            return;
            
        if (_isAborting)
        {
            _isAborting = false;
            return;
        }

        _this.submitEdit();
    }

    this.hostElement_click = function()
    {
        if (!_this.isEnabled || _isEditing || _isLoading || _isSaving || _isAborting)
            return;

        _this.loadEdit();
    }

    this.hostElement_mouseOver = function()
    {
        if (!_this.isEnabled)
            return;

        // add hover class
        if (!_isEditing)
            _this.hostElement.className += " " + Rf.Controls.ClickEditor.hoverClassName;
    }

    this.hostElement_mouseOut = function()
    {
        // restore original classname
        _this.hostElement.className = _originalHostClassName;
    }


    // Safe initialize
    if (Rf.OnInit.reached)
        this.initialize();
    else
        Rf.OnInit.register(this.initialize);
}

Rf.Controls.ClickEditor.hoverClassName = "clickEditorHover";
Rf.Controls.ClickEditor.inputClassName = "clickEditorInput";

Rf.Controls.ClickEditor.registerClass("Rf.Controls.ClickEditor");

// ------------------------------------------------------------------------------------







// ------------------------------------------------------------------------------------
// Rf/Controls/Control.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.Controls"))
    Type.registerNamespace("Rf.Controls");

// ------------------------------------------------------------------------------------
// Control
// ------------------------------------------------------------------------------------

Rf.Controls.Control = function()
{
    if (Rf.OnInit.reached)
        this.initialize();
    else
        Rf.OnInit.register(this.initialize.$delegate(this));
}

Rf.Controls.Control.prototype =
{
    initialize: function()
    {
    }
}

Rf.Controls.Control.registerClass("Rf.Controls.Control");

// ------------------------------------------------------------------------------------






// ------------------------------------------------------------------------------------
// Rf/Controls/ImagePopup.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.Controls"))
    Type.registerNamespace("Rf.Controls");

// ------------------------------------------------------------------------------------
// ImagePopup
// ------------------------------------------------------------------------------------

Rf.Controls.ImagePopup = function() { };

Rf.Controls.ImagePopup.single = function(imageUrl, popupClassName)
{
    if (!popupClassName)
        popupClassName = "tplImagePopup";

    var contentElement = $byClass("tplImagePopup").$clone();

    var imageElement = contentElement.$byClass("ctlImage");
    var buttonElement = contentElement.$byClass("btnClose");

    var popup = new Rf.Controls.Popup(contentElement);
    var globalLoading = new Rf.Controls.GlobalLoading();
    
    globalLoading.start();
    
    $addHandler(imageElement, "load", function(evt) { evt.preventDefault(); });
    $addHandler(imageElement, "load", globalLoading.stop.$delegate(globalLoading));
    $addHandler(imageElement, "load", popup.show.$delegate(popup));

    imageElement.src = imageUrl;

    $addHandler(buttonElement, "click", function(evt) { evt.preventDefault(); popup.destroy(); });
}

Rf.Controls.ImagePopup.registerClass("Rf.Controls.ImagePopup");

// ------------------------------------------------------------------------------------






// ------------------------------------------------------------------------------------
// Rf/Controls/LoadingControl.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.Controls"))
    Type.registerNamespace("Rf.Controls");

// ------------------------------------------------------------------------------------
// LoadingControl
// ------------------------------------------------------------------------------------

Rf.Controls.LoadingControl = function(hostElement, originElement)
{
    this.hostElement = hostElement;
    this.originElement = originElement;
    this.mainElement = null;

    Rf.Controls.LoadingControl.initializeBase(this, [hostElement, originElement]);
}

Rf.Controls.LoadingControl.prototype =
{
    initialize: function()
    {
        Rf.Controls.LoadingControl.callBaseMethod(this, "initialize");

        if (!this.originElement)
            this.originElement = Rf.Controls.LoadingControl.getOriginElement();
        else
            this.originElement = $byId(this.originElement);

        this.hostElement = $byId(this.hostElement);

        this.mainElement = this.originElement.$clone();
        this.hostElement.parentNode.appendChild(this.mainElement);
    },

    start: function()
    {
        this.hostElement.style.visibility = "hidden";
        this.mainElement.style.display = "block";

        this.updatePosition();
    },

    updatePosition: function()
    {
    },

    stop: function()
    {
        this.mainElement.style.display = "none";
        this.hostElement.style.visibility = "visible";
    }
};


Rf.Controls.LoadingControl.originElement = "tplLoadingControl";

Rf.Controls.LoadingControl.getOriginElement = function()
{
    if (typeof (Rf.Controls.LoadingControl.originElement) == "string" )
        Rf.Controls.LoadingControl.originElement = $byClass(Rf.Controls.LoadingControl.originElement);

    return Rf.Controls.LoadingControl.originElement;
}

Rf.Controls.LoadingControl.registerClass("Rf.Controls.LoadingControl", Rf.Controls.Control);

// ------------------------------------------------------------------------------------





// ------------------------------------------------------------------------------------
// GlobalLoading singleton
// ------------------------------------------------------------------------------------

Rf.Controls.GlobalLoading = function()
{
    if (Rf.Controls.GlobalLoading.instance != null)
        return Rf.Controls.GlobalLoading.instance;

    this.popup = null;
    this.LoadingControl = null;

    Rf.Controls.GlobalLoading.initializeBase(this);

    Rf.Controls.GlobalLoading.instance = this;
}

Rf.Controls.GlobalLoading.instance = null;

Rf.Controls.GlobalLoading.prototype =
{
    initialize: function()
    {
        Rf.Controls.GlobalLoading.callBaseMethod(this, "initialize");

        this.popup = new Rf.Controls.Popup($byClass("tplGlobalLoading"));
        this.loadingControl = new Rf.Controls.LoadingControl(this.popup.contentElement);
        this.loadingControl.start();
    },

    start: function()
    {
        this.popup.show();
    },

    stop: function()
    {
        this.popup.close();
    }
};

Rf.Controls.GlobalLoading.registerClass("Rf.Controls.GlobalLoading", Rf.Controls.Control);

// ------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------
// Rf/Controls/MessageBox.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.Controls"))
    Type.registerNamespace("Rf.Controls");

// ------------------------------------------------------------------------------------
// MessageBox
// ------------------------------------------------------------------------------------

Rf.Controls.MessageBox = function() { };

Rf.Controls.MessageBox.message = function(text, title, btnOk_callback)
{
    if (title && typeof (title) == "function")
    {
        btnOk_callback = title;
        title = null;
    }

    Rf.Controls.MessageBox.showDialog("tplMessageBox_message", text, title, btnOk_callback);
}

Rf.Controls.MessageBox.success = function(text, title, btnOk_callback)
{
    if (title && typeof (title) == "function")
    {
        btnOk_callback = title;
        title = null;
    }

    Rf.Controls.MessageBox.showDialog("tplMessageBox_success", text, title, btnOk_callback);
}

Rf.Controls.MessageBox.error = function(text, title, btnOk_callback)
{
    if (title && typeof (title) == "function")
    {
        btnOk_callback = title;
        title = null;
    }

    Rf.Controls.MessageBox.showDialog("tplMessageBox_error", text, title, btnOk_callback);
}

Rf.Controls.MessageBox.question = function(text, title, btnYes_callback, btnNo_callback)
{
    if (title && typeof (title) == "function")
    {
        if (btnYes_callback && typeof (btnNo_callback) == "function")
            btnNo_callback = btnYes_callback;
            
        btnYes_callback = title;
        title = null;
    }

    Rf.Controls.MessageBox.showDialog("tplMessageBox_question", text, title, btnYes_callback, btnNo_callback);    
}


Rf.Controls.MessageBox.showDialog = function(dialogClassName, text, title, btnOk_callback, btnCancel_callback)
{
    var contentElement = $clone($byClass(dialogClassName));

    var textElement = contentElement.$byClass("ctlText");
    textElement.innerHTML = text;

    if (title)
    {
        var titleElement = contentElement.$byClass("ctlTitle");
        titleElement.innerHTML = title;
    }

    var buttonOkElement = contentElement.$byClass("btnOk");
    var buttonCancelElement = contentElement.$byClass("btnCancel");

    var popup = new Rf.Controls.Popup(contentElement);

    if (buttonOkElement)
    {
        if (btnOk_callback)
            buttonOkElement.onclick = function() { popup.destroy(); btnOk_callback(); return false; };
        else
            buttonOkElement.onclick = function() { popup.destroy(); return false; };
    }
    if (buttonCancelElement)
    {
        if (btnCancel_callback)
            buttonCancelElement.onclick = function() { popup.destroy(); btnCancel_callback(); return false; };
        else
            buttonCancelElement.onclick = function() { popup.destroy(); return false; };
    }

    popup.show();
}


Rf.Controls.MessageBox.registerClass("Rf.Controls.MessageBox");

// ------------------------------------------------------------------------------------










// --------------------------------------------------------------------------------
// Rf/Controls/MultiEditor.js
// --------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.Controls"))
    Type.registerNamespace("Rf.Controls");

// ------------------------------------------------------------------------------------
// MultiEditor
// ------------------------------------------------------------------------------------

Rf.Controls.MultiEditor = function(hostElementID, listTemplateID, addFormTemplateID, editFormTemplateID)
{
    var _this = this;

    this.hostElementID = hostElementID;
    this.listTemplateID = listTemplateID;
    this.addFormTemplateID = addFormTemplateID;
    this.editFormTemplateID = editFormTemplateID;

    this.hostElement = null;
    this.loadingControl = null;

    this.formsHostType = "li";

    this.data = [];

    this.dataElementName = null;

    this.webService = "Service";
    this.webMethod_LoadList = "Load";
    this.webMethod_Delete = "Delete";
    this.webMethod_Update = "Update";
    this.webMethod_Add = "Add";

    this.webMethodArguments_LoadList = {};
    this.webMethodArguments_Delete = {};
    this.webMethodArguments_Update = {};
    this.webMethodArguments_Add = {};

    this.templateDataSources = [];
    // { "webService" : "SomeService", "webMethod" : "SomeMethod", "elementName" : "SomeElement", "arguments": {} }
    this.templateData = null;
    this.templateDataSourcesWorking = 0;
    this.templateDataSourcesFailed = 0;

    this.onListLoading = function() { return true; };
    this.onListLoaded = function() { return true; };
    this.onListLoadError = function() { return true; };

    this.onTemplateDataLoading = function() { return true; }
    this.onTemplateDataLoaded = function() { return true; }
    this.onTemplateDataError = function() { return true; } // called 

    this.onItemAdding = function() { return true; };
    this.onItemAdded = function() { return true; };
    this.onItemAddError = function() { return true; };

    this.onItemDeleting = function() { return true; };
    this.onItemDeleted = function() { return true; };
    this.onItemDeleteError = function() { return true; };

    this.onItemUpdating = function() { return true; };
    this.onItemUpdated = function() { return true; };
    this.onItemUpdateError = function() { return true; };

    this.isLoading = false;
    this.isEditing = false;
    this.isAdding = false;
    this.isModified = true;

    this.currentControlElement = null;
    this.currentFormHost = null;
    this.currentForm = null;
    this.currentDataItem = null;

    this.initialize = function()
    {
        _this.hostElement = $get(_this.hostElementID);

        if (!_this.hostElement)
            throw "Invalid host element.";

        _this.hostElement.multiEditor = _this;

        _this.loadingControl = new LoadingControl(_this.hostElement);
    }

    this.reset = function()
    {
        _this.isModified = true;
        _this.isAdding = false;
        _this.isEditing = false;
        _this.isLoading = false;
        _this.currentControlElement = null;
        _this.currentFormHost = null;
        _this.currentForm = null;
        _this.currentDataItem = null;
        _this.templateData = null;
    }

    this.loadList = function()
    {
        if (!_this.isModified) // nothing new
            return;

        var wmLoadList = new Rf.WebMethod(_this.webService, _this.webMethod_LoadList);

        wmLoadList.onCompleted = _this.loadList_onSuccess;
        wmLoadList.onFailed = _this.loadList_onError;

        if (!_this.onListLoading())
            return;

        _this.loadingControl.start();
        _this.loadTemplateData();
        _this.isLoading = true;
        wmLoadList.invoke(_this.webMethodArguments_LoadList);
    }

    this.loadTemplateData = function()
    {
        if (_this.templateData != null)
            return;

        _this.templateData = {};
        _this.templateDataSourcesWorking = 0;
        _this.templateDataSourcesFailed = 0;

        if (!_this.onTemplateDataLoading())
            return;

        for (var n = 0; n < _this.templateDataSources.length; n++)
        {
            var sourceDef = _this.templateDataSources[n];
            var wmGet = new Rf.WebMethod(sourceDef.webService, sourceDef.webMethod);

            wmGet.onCompleted =
            function(data) { _this.loadTemplateData_onMethodCompleted(data, sourceDef.elementName); };

            wmGet.onFailed = _this.loadTemplateData_onMethodFailed;

            _this.templateDataSourcesWorking++;

            if (sourceDef.arguments)
                wmGet.invoke(sourceDef.arguments);
            else
                wmGet.invoke();
        }
    }

    this.loadTemplateData_onMethodCompleted = function(data, elementName)
    {
        _this.templateData[elementName] = data;
        _this.templateDataSourcesWorking--;

        if (_this.templateDataSourcesWorking <= 0 && !_this.isLoading)
        {
            if (_this.templateDataSourcesFailed > 0)
            {
                if (_this.onTemplateDataError())
                    MessageBox.error("Could not load some of the editor data."); // TODO: localize this somehow
            }
            else
            {
                _this.onTemplateDataLoaded();
            }

            _this.loadingControl.stop();
        }
    }

    this.loadTemplateData_onMethodFailed = function()
    {
        _this.templateDataSourcesWorking--;
        _this.templateDataSourcesFailed++;

        if (_this.templateDataSourcesWorking <= 0 && !_this.isLoading)
        {
            _this.loadingControl.stop();
        }

    }

    this.loadList_onSuccess = function(data)
    {
        if (_this.templateDataSourcesWorking > 0)
        {
            //Rf.Controls.MessageBox.message("Waiting for sources: " + _this.templateDataSourcesWorking);
            setTimeout(_this.loadList_onSuccess.$delegate(data), 200); // wait for template data to load
            return;
        }

        _this.isLoading = false;
        _this.loadingControl.stop();

        if (_this.dataElementName)
            _this.data = data[_this.dataElementName];
        else
            _this.data = data;

        if (!_this.data)
            throw "Invalid data element name."; // TODO: localize this somehow

        _this.templateData["items"] = _this.data;
        _this.hostElement.innerHTML = Rf.Template.parseElement(_this.listTemplateID, _this.templateData);

        _this.isModified = false;
        _this.onListLoaded();
    }

    this.loadList_onError = function()
    {
        _this.isLoading = false;

        if (_this.dataSourcesWorking <= 0)
            _this.loadingControl.stop();

        if (!_this.onListLoadError())
            return;

        MessageBox.error("Could not load element list."); // TODO: localize this somehow
    }

    this.openAddForm = function(controlElement)
    {
        if (_this.isEditing || _this.isAdding)
            return;
        //_this.closeForm(); // one form at a time

        _this.currentControlElement = controlElement;
        _this.currentFormHost = document.createElement(_this.formsHostType);

        _this.currentControlElement.parentNode.replaceChild(_this.currentFormHost, _this.currentControlElement);
        _this.currentFormHost.innerHTML = Rf.Template.parseElement(_this.addFormTemplateID, _this.templateData);
        _this.currentForm = _this.currentFormHost.getElementsByTagName("form")[0];

        _this.isAdding = true;
    }

    this.closeForm = function()
    {
        if (!_this.currentControlElement || !_this.currentFormHost)
            return;

        _this.currentFormHost.parentNode.replaceChild(_this.currentControlElement, _this.currentFormHost);
        _this.currentForm = _this.currentFormHost = _this.currentControlElement = null;

        _this.isAdding = false;
        _this.isEditing = false;
    }

    this.submitAddForm = function()
    {
        if (!_this.currentControlElement || !_this.currentForm)
            return;

        if (!_this.onItemAdding())
            return;

        _this.addItem();
    }

    this.addItem = function()
    {
        var wmAdd = new Rf.WebMethod(_this.webService, _this.webMethod_Add);

        wmAdd.onCompleted = _this.addItem_onCompleted;
        wmAdd.onFailed = _this.addItem_onFailed;

        _this.loadingControl.start();
        wmAdd.invoke(_this.webMethodArguments_Add);
    }

    this.addItem_onCompleted = function()
    {
        _this.closeForm();
        _this.loadingControl.stop();
        _this.isModified = true;

        if (!_this.onItemAdded())
            return;

        _this.reset();
        _this.loadList();
    }

    this.addItem_onFailed = function()
    {
        _this.loadingControl.stop();

        if (!_this.onItemAddError())
            return;

        MessageBox.error("Could not add element."); // TODO: localize this somehow
    }


    this.deleteItem = function(index)
    {
        if (!_this.data[index])
            return;

        _this.currentDataItem = _this.data[index];

        var wmDelete = new Rf.WebMethod(_this.webService, _this.webMethod_Delete);
        wmDelete.onCompleted = _this.deleteItem_onCompleted;
        wmDelete.onFailed = _this.deleteItem_onFailed;

        if (!_this.onItemDeleting())
            return;

        MessageBox.question("Do you really want to delete this item?", // TODO: localize this!
            function() { _this.loadingControl.start(); wmDelete.invoke(_this.webMethodArguments_Delete); },
            function() { });
    }

    this.deleteItem_onCompleted = function()
    {
        _this.loadingControl.stop();
        _this.currentDataItem = null;
        _this.isModified = true;

        if (!_this.onItemDeleted())
            return;

        _this.reset();
        _this.loadList();
    }

    this.deleteItem_onFailed = function()
    {
        _this.loadingControl.stop();

        if (!_this.onItemDeleteError())
            return;

        MessageBox.error("Could not delete element."); // TODO: localize this somehow
    }

    this.openEditForm = function(controlElement, index)
    {
        if (_this.isEditing || _this.isAdding)
            return;
        //_this.closeForm(); // one form at a time

        if (!_this.data[index])
            return;

        _this.currentDataItem = _this.data[index];

        _this.currentControlElement = controlElement;
        _this.currentFormHost = document.createElement(_this.formsHostType);

        _this.currentControlElement.parentNode.replaceChild(_this.currentFormHost, _this.currentControlElement);

        _this.templateData["item"] = _this.currentDataItem;
        _this.currentFormHost.innerHTML = Rf.Template.parseElement(_this.editFormTemplateID, _this.templateData);

        _this.currentForm = _this.currentFormHost.getElementsByTagName("form")[0];

        _this.isEditing = true;
    }

    this.submitEditForm = function()
    {
        if (!_this.currentControlElement || !_this.currentForm)
            return;

        if (!_this.onItemUpdating())
            return;

        _this.updateItem();
    }

    this.updateItem = function()
    {
        var wmUpdate = new Rf.WebMethod(_this.webService, _this.webMethod_Update);
        wmUpdate.onCompleted = _this.updateItem_onCompleted;
        wmUpdate.onFailed = _this.updateItem_onFailed;

        this.loadingControl.start();
        wmUpdate.invoke(_this.webMethodArguments_Update);
    }

    this.updateItem_onCompleted = function()
    {
        _this.closeForm();
        _this.loadingControl.stop();
        _this.currentDataItem = null;
        _this.isModified = true;

        if (!_this.onItemUpdated())
            return;

        _this.reset();
        _this.loadList();
    }

    this.updateItem_onFailed = function()
    {
        _this.loadingControl.stop();

        if (!_this.onItemUpdateError())
            return;

        MessageBox.error("Could not update element."); // TODO: localize this somehow
    }

    // Safe init
    if (Rf.OnInit.reached)
        this.initialize();
    else
        Rf.OnInit.register(this.initialize);
}

Rf.Controls.MultiEditor.getCurrent = function(controlElement)
{
    if (controlElement.multiEditor)
        return controlElement.multiEditor;
    else if (controlElement.parentNode)
        return Rf.Controls.MultiEditor.getCurrent(controlElement.parentNode);
    else
        return null;
}

Rf.Controls.MultiEditor.registerClass("Rf.Controls.MultiEditor");

// --------------------------------------------------------------------------------






// ------------------------------------------------------------------------------------
// Rf/Controls/Pager.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.Controls"))
    Type.registerNamespace("Rf.Controls");

// ------------------------------------------------------------------------------------
// Pager
// ------------------------------------------------------------------------------------

Rf.Controls.Pager = function(hostElement, itemTagName, pageSize, pageIndex, btnBack, btnForward, pagerElement)
{
    // private
    var _this = this;

    var _isLocked = false;

    // public
    this.hostElement = hostElement;
    this.itemTagName = itemTagName;
    this.pageSize = pageSize;
    this.pageIndex = pageIndex;
    this.pagerElement = pagerElement;

    this.btnForward = btnForward;
    this.btnBack = btnBack;

    this.items = [];

    this.visibleDisplayMode = 'block';
    this.totalPages = 0;

    this.sizeLocked = true;
    this.hostElementWidth = 0;
    this.hostElementHeight = 0;

    this.initialize = function()
    {
        if (typeof (_this.hostElement) != "object")
            _this.hostElement = $get(_this.hostElement);

        if (_this.pagerElement)
        {
            if (typeof (_this.pagerElement) != "object")
                _this.pagerElement = $get(_this.pagerElement);
        }

        if (_this.btnForward)
        {
            _this.btnForward = new Rf.Controls.Button(_this.btnForward);
            _this.btnForward.onClick = _this.btnForward_click;
        }

        if (_this.btnBack)
        {
            _this.btnBack = new Rf.Controls.Button(_this.btnBack);
            _this.btnBack.onClick = _this.btnBack_click;
        }

        _this.items = _this.hostElement.getElementsByTagName(_this.itemTagName);

        if (_this.items[0] && _this.items[0].style.display)
            _this.visibleDisplayMode = _this.items[0].style.display;

        _this.totalPages = Math.ceil(_this.items.length / (0.0 + _this.pageSize));

        _this.update();
    }

    this.update = function()
    {
        minIndex = _this.pageSize * _this.pageIndex;
        maxIndex = minIndex + _this.pageSize - 1;

        for (var n = 0; n < _this.items.length; n++)
        {
            if (n >= minIndex && n <= maxIndex)
                _this.items[n].style.display = _this.visibleDisplayMode;
            else
                _this.items[n].style.display = 'none';
        }

        if (_this.totalPages > 1)
        {
            if (_this.btnBack && _this.btnForward)
            {
                _this.btnBack.setVisible(_this.pageIndex > 0);
                _this.btnForward.setVisible((_this.pageIndex + 1) < _this.totalPages);
            }        
        }
        else if (_this.pagerElement)
            _this.pagerElement.style["display"] = "none";

    }

    this.lockSize = function()
    {
        if (_this.hostElementWidth == 0)
            _this.hostElementWidth = _this.hostElement.clientWidth;

        if (_this.hostElementHeight == 0)
            _this.hostElementHeight = _this.hostElement.clientHeight;

        _this.hostElement.style.width = _this.hostElementWidth + "px";
        _this.hostElement.style.height = _this.hostElementHeight + "px";

        _isLocked = true;
    }

    this.btnBack_click = function()
    {
        if (_this.pageIndex > 0)
            _this.pageIndex--;

        _this.update();

        return -1;
    }

    this.btnForward_click = function()
    {
        if (_this.sizeLocked && !_isLocked)
            _this.lockSize();

        if ((_this.pageIndex + 1) < _this.totalPages)
            _this.pageIndex++;

        _this.update();

        return 1;
    }
}

Rf.Controls.Pager.registerClass("Rf.Controls.Pager");

// ------------------------------------------------------------------------------------









// ------------------------------------------------------------------------------------
// Rf/Controls/Popup.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.Controls"))
    Type.registerNamespace("Rf.Controls");

// ------------------------------------------------------------------------------------
// Popup
// ------------------------------------------------------------------------------------

Rf.Controls.Popup = function(content, boxElement)
{
    this.contentElement = content;
    this.boxElementOrigin = boxElement;

    this.backgroundElement = null;
    this.boxElement = null;
    this.holderElement = null;

    this.index = -1;
    this.isActive = false;

    Rf.Controls.Popup.initializeBase(this, [content, boxElement]);
}

Rf.Controls.Popup.prototype =
{
    initialize: function()
    {
        Rf.Controls.Popup.callBaseMethod(this, "initialize");

        Rf.Controls.Popup.prepareElements();

        if (!this.boxElementOrigin)
            this.boxElementOrigin = Rf.Controls.Popup.boxElement;
        else if (typeof (this.boxElementOrigin) != "object")
            this.boxElementOrigin = $get(this.boxElementOrigin);

        if (typeof (this.contentElement) != "object")
            this.contentElement = $get(this.contentElement);

        this.setContents(this.contentElement);

        // create the background element
        this.backgroundElement = document.createElement('div');

        this.backgroundElement.style["display"] = "none";
        this.backgroundElement.style["position"] = "absolute";
        this.backgroundElement.style["top"] = "0px";
        this.backgroundElement.style["left"] = "0px";
        this.backgroundElement.style["height"] = document.documentElement.scrollHeight + "px";
        this.backgroundElement.style["width"] = "100%";
        this.backgroundElement.style["background"] = Rf.Controls.Popup.backgroundColor;
        this.backgroundElement.style["filter"] = "alpha(opacity=" + Rf.Controls.Popup.backgroundAlpha * 100 + ")";
        this.backgroundElement.style["opacity"] = "" + Rf.Controls.Popup.backgroundAlpha;
        this.backgroundElement.style.zIndex = Rf.Controls.Popup.initialIndex;


        // create the box elelment
        this.boxElement = Rf.DomUtility.cloneElement(this.boxElementOrigin);

        this.boxElement.style["position"] = "absolute";
        this.boxElement.style["top"] = "0px";
        this.boxElement.style["left"] = "-9998px";
        this.boxElement.style["display"] = "block";

        // replace the holder element with content element
        for (var n = 0; n < this.boxElement.childNodes.length; n++)
        {
            if (this.boxElement.childNodes[n].className == "Rf.Controls.PopupHolder")
                this.boxElement.replaceChild(this.contentElement, this.boxElement.childNodes[n]);
        }

        if (!this.contentElement.className)
            this.contentElement.className = Rf.Controls.Popup.contentClassName;
        else
            this.contentElement.className +=
                " " + Rf.Controls.Popup.contentClassName;

        // populate the elements
        Rf.Controls.Popup.containerElement.appendChild(this.backgroundElement);
        Rf.Controls.Popup.containerElement.appendChild(this.boxElement);
    },

    show: function(skipPositionUpdate)
    {
        if (this.isActive)
            this.close();

        this.backgroundElement.style["display"] = "block";

        Rf.Controls.Popup.itemStack.push(this);

        Rf.Controls.Popup.updateContainerVisibility();

        this.updateIndex(Rf.Controls.Popup.itemStack.length - 1);

        this.updatePosition();

        Rf.Controls.Popup.updateTopItem();

        this.isActive = true;

        this.boxElement.style["visibility"] = "visible";
    },

    updateIndex: function(newIndex)
    {
        this.index = newIndex;

        this.backgroundElement.style.zIndex = (Rf.Controls.Popup.initialIndex + this.index * 2);
        this.boxElement.style.zIndex = (Rf.Controls.Popup.initialIndex + this.index * 2 + 1);
    },

    setContents: function(content)
    {
        if (content.parentNode)
            content.parentNode.removeChild(content);

        this.contentElement = content;
        this.contentElement.style["display"] = "block";

        if (this.isActive)
            this.updatePosition();
    },


    updatePosition: function()
    {
        this.boxElement.style["width"] = this.contentElement.offsetWidth + "px";
        //boxElement.style["height"] = this.contentElement.offsetHeight + "px";

        var top = (Rf.Screen.getScrollY() + Rf.Screen.getViewportHeight() / 2 - this.contentElement.offsetHeight / 2);

        this.boxElement.style["top"] = (top > 0 ? top : 0) + "px";

        this.boxElement.style["left"] =
            (Rf.Screen.getViewportWidth() / 2 - this.contentElement.offsetWidth / 2) + "px";
    },

    close: function()
    {
        Rf.Controls.Popup.itemStack.splice(this.index, 1);
        this.backgroundElement.style["display"] = "none";
        this.boxElement.style["top"] = "0px";
        this.boxElement.style["left"] = "-9998px";

        this.index = -1;

        Rf.Controls.Popup.updateContainerVisibility();
        Rf.Controls.Popup.updateItemIndexes();
        Rf.Controls.Popup.updateTopItem();

        this.isActive = false;
    },

    destroy: function()
    {
        if (this.isActive)
            this.close();

        this.backgroundElement.parentNode.removeChild(this.backgroundElement);
        this.contentElement.parentNode.removeChild(this.contentElement);
    }
}


Rf.Controls.Popup.backgroundColor = "#aaa";
Rf.Controls.Popup.backgroundAlpha = 0.6;
Rf.Controls.Popup.initialIndex = 200;

Rf.Controls.Popup.containerElement = null;
Rf.Controls.Popup.boxElement = null;
Rf.Controls.Popup.contentClassName = "pupupContent";

Rf.Controls.Popup.itemStack = [];
Rf.Controls.Popup.top = null;

Rf.Controls.Popup.prepareElements = function()
{
    if (Rf.Controls.Popup.containerElement != null ||
         Rf.Controls.Popup.boxElement != null)
        return;

    Rf.Controls.Popup.containerElement = $get("Rf.Controls.PopupContainer");
    Rf.Controls.Popup.boxElement = $get("Rf.Controls.PopupBox");

    var viewportHeight = Rf.Screen.getViewportHeight();
    var height = document.getHeight();

    if (viewportHeight > height)
        height = viewportHeight;

    Rf.Controls.Popup.containerElement.style["height"] = height + "px";
}

Rf.Controls.Popup.updateContainerVisibility = function()
{
    Rf.Controls.Popup.containerElement.style["display"] =
        Rf.Controls.Popup.itemStack.length > 0 ? "block" : "none";

    var viewportHeight = Rf.Screen.getViewportHeight();
    var height = document.getHeight();

    if (viewportHeight > height)
        height = viewportHeight;

    Rf.Controls.Popup.containerElement.style["height"] = height + "px";
}

Rf.Controls.Popup.updateItemIndexes = function()
{
    for (var n = 0; n < Rf.Controls.Popup.itemStack.length; n++)
        Rf.Controls.Popup.itemStack[n].updateIndex(n);
}

Rf.Controls.Popup.updateTopItem = function()
{
    if (Rf.Controls.Popup.itemStack.length > 0)
    {
        Rf.Controls.Popup.top = Rf.Controls.Popup.itemStack[Rf.Controls.Popup.itemStack.length - 1];
    }
    else
        Rf.Controls.Popup.top = null;
}

Rf.Controls.Popup.registerClass("Rf.Controls.Popup",Rf.Controls.Control);

// ------------------------------------------------------------------------------------






// ------------------------------------------------------------------------------------
// Rf/Controls/TabControl.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.Controls"))
    Type.registerNamespace("Rf.Controls");

// ------------------------------------------------------------------------------------
// Rf.Controls.TabPanel
// ------------------------------------------------------------------------------------

Rf.Controls.TabPanel = function(hostElement)
{
    var _this = this;

    var _hostElement = null;

    _this.elements = [];

    var initialize = this.initialize = function()
    {
        var buttons = Rf.DomUtility.getElementsByAttribute("className", "_tabButton", false, _hostElement);
        var panels = Rf.DomUtility.getElementsByAttribute("className", "_tabPanel", false, _hostElement);

        if (buttons.length > panels.length)
            throw "Invalid tabButton/tabPanel count.";

        for (var n = 0; n < buttons.length; n++)
        {
            var tabElement = new Rf.Controls.TabPanelElement(buttons[n], panels[n], _this);
            _this.elements.push(tabElement);
        }

        if (_this.elements.length > 0)
            _this.setActiveIndex(0);
    }

    //    var add = this.add = function( tabElement, contentElement )
    //    {
    //        var tabElement = new Rf.Controls.TabPanelElement( tabElement, contentElement, _this );
    //        
    //        if ( _this.getActiveIndex() < 0 )
    //            tabElement.active = true;
    //    
    //        _this.elements.push( tabElement );
    //        _this.update();
    //    }

    var reset = this.reset = function()
    {
        for (var n = 0; n < _this.elements.length; n++)
            _this.elements[n].active = false;
    }

    var setActiveIndex = this.setActiveIndex = function(index)
    {
        if (!_this.elements[index])
            return;

        for (var n = 0; n < _this.elements.length; n++)
            _this.elements[n].active = n == index ? true : false;

        _this.update();
        _this.elements[index].onActivate.call();
    }

    var getActiveIndex = this.getActiveIndex = function()
    {
        for (var n = 0; n < _this.elements.length; n++)
            if (_this.elements[n].active)
            return n;

        return -1;
    }

    var update = this.update = function()
    {
        var active = false;

        for (var n = 0; n < _this.elements.length; n++)
        {
            var tabElement = _this.elements[n];

            if (tabElement.active)
            {
                if (active)
                    tabElement.active = false;
                else
                    active = true;
            }

            tabElement.update();
        }
    }

    if (hostElement)
    {
        if (typeof (hostElement) == "object")
            _hostElement = hostElement;
        else
            _hostElement = $get(hostElement);

        // Safe initialize
        if (Rf.OnInit.reached)
            this.initialize();
        else
            Rf.OnInit.register(this.initialize);
    }
}

Rf.Controls.TabPanel.registerClass("Rf.Controls.TabPanel");

// ------------------------------------------------------------------------------------







// ------------------------------------------------------------------------------------
// Rf.Controls.TabPanelElement
// ------------------------------------------------------------------------------------

Rf.Controls.TabPanelElement = function(tabElement, contentElement, tabControl)
{
    var _this = this;

    var _tabControl = null;

    if (tabControl)
        _tabControl = tabControl;

    var _tabElement = null;
    _this.contentElement = null;

    _this.active = false;
    _this.disabled = false;
    _this.visible = true;

    _this.onActivate = function() { };

    if (typeof (contentElement) == "object")
        _this.contentElement = contentElement;
    else
        _this.contentElement = $get(contentElement);

    if (typeof (tabElement) == "object")
        _tabElement = tabElement;
    else
        _tabElement = $get(tabElement);

    _tabElement.onclick = function() { _this.activate(); return false; }

    var activate = this.activate = function()
    {
        if (_this.disabled || _this.active)
            return;

        _tabControl.reset();
        _this.active = true;
        _tabControl.update();

        _this.onActivate.call();
    }

    var update = this.update = function()
    {
        if (!_this.visible)
        {
            _this.contentElement.style["display"] = "none";
            _tabElement.style["display"] = "none";

            return;
        }

        if (_this.active)
        {
            _this.contentElement.style["display"] = "block";
            _tabElement.className = Rf.Controls.TabPanelElement.tabActiveClassName;

            return;
        }

        _this.contentElement.style["display"] = "none";
        _tabElement.className = _this.disabled ?
            Rf.Controls.TabPanelElement.tabDisabledClassName : Rf.Controls.TabPanelElement.tabInactiveClassName;
    }
}

Rf.Controls.TabPanelElement.tabActiveClassName = "tabActive";
Rf.Controls.TabPanelElement.tabInactiveClassName = "tabInactive";
Rf.Controls.TabPanelElement.tabDisabledClassName = "tabDisabled";

Rf.Controls.TabPanelElement.registerClass("Rf.Controls.TabPanelElement");

// ------------------------------------------------------------------------------------





// ------------------------------------------------------------------------------------
// Rf/Controls/WizardPopup.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.Controls"))
    Type.registerNamespace("Rf.Controls");

// ------------------------------------------------------------------------------------
// WizardPopup
// ------------------------------------------------------------------------------------

Rf.Controls.WizardPopup = function(hostElementID)
{
    var _this = this;

    var _hostElementID = hostElementID;
    var _box = null;
    this.popup = null;
    var _tabControl = null;

    this.stepIndex = 0;
    this.maxStepIndex = 0;
    this.steps = [];
    this.resetOnClose = false;

    var preInitialize = this.preInitialize = function()
    {
        _box = $get(_hostElementID);
        _this.popup = new Rf.Controls.Popup(_box);

        _tabControl = new Rf.Controls.TabPanel(_box);

        for (var n = 0; n < _tabControl.elements.length; n++)
            _this.steps.push(new Rf.Controls.WizardPopupStep(_this, n, _tabControl.elements[n]));
    }

    var initialize = this.initialize = function()
    {
    }

    var postInitialize = this.postInitialize = function()
    {
        for (var n = 0; n < _this.steps.length; n++)
            _this.steps[n].initialize();
    }

    var updateState = this.updateState = function()
    {
        _this.maxStepIndex = 0;
        var block = false;

        for (var n = 0; n < _this.steps.length; n++)
        {
            var nextIndex = n + 1;
            var isLast = nextIndex >= _tabControl.elements.length;

            if (!block && _this.steps[n].canAdvance())
            {
                if (!isLast)
                    _tabControl.elements[nextIndex].disabled = false;

                _this.maxStepIndex++;
            }
            else if (!isLast)
            {
                _tabControl.elements[nextIndex].disabled = true;
                block = true;
            }
        }

        _this.steps[_this.stepIndex].updateState();
        _tabControl.update();
    }

    var goBack = this.goBack = function()
    {
        if (_this.stepIndex > 0)
        {
            _this.stepIndex--;
            _tabControl.setActiveIndex(_this.stepIndex);
        }
    }

    var advance = this.advance = function()
    {
        if (_this.steps[_this.stepIndex].canAdvance())
        {
            _this.steps[_this.stepIndex].onAdvanceCallback();

            if (_this.maxStepIndex > _this.stepIndex && !_this.steps[_this.stepIndex].isLast)
            {
                _this.stepIndex++;
                _tabControl.setActiveIndex(_this.stepIndex);
            }
        }
    }

    var close = this.close = function()
    {
        if (_this.resetOnClose)
        {
            _tabControl.setActiveIndex(0);
            _this.reset();
        }

        _this.popup.close();
    }

    var start = this.start = function()
    {
        _this.popup.show();
        _this.updateState();
        _this.steps[_this.stepIndex].onActivateCallback();
    }

    var reset = this.reset = function()
    {
        for (var n = 0; n < _this.steps.length; n++)
            _this.steps[n].reset();

        _this.updateState();
    }
}

Rf.Controls.WizardPopup.registerClass("Rf.Controls.WizardPopup");

// ------------------------------------------------------------------------------------







// ------------------------------------------------------------------------------------
// WizardPopupStep
// ------------------------------------------------------------------------------------

Rf.Controls.WizardPopupStep = function(parent, index, tabElement)
{
    var _this = this;

    this.parent = parent;
    var _index = index;
    var _tabElement = tabElement

    this.isFirst = _index == 0;
    this.isLast = _index == (parent.steps.length - 1);

    this.btnCancel = null;
    this.btnBack = null;
    this.btnNext = null;
    this.canAdvance = function() { return false };
    this.onAdvance = function() { };
    this.onActivate = function() { };
    this.reset = function() { };

    var initialize = this.initialize = function()
    {
        if (_this.btnBack)
            _this.btnBack.onClick = _this.parent.goBack;

        if (_this.btnNext)
            _this.btnNext.onClick = _this.parent.advance;

        if (_this.btnCancel)
            _this.btnCancel.onClick = _this.parent.close;

        _tabElement.onActivate = _this.onActivateCallback;
    }

    var updateState = this.updateState = function()
    {
        if (_this.btnBack)
            _this.btnBack.setVisible(!_this.isFirst);

        if (_this.btnNext)
            _this.btnNext.setVisible(_this.canAdvance());
    }

    var onAdvanceCallback = this.onAdvanceCallback = function()
    {
        _this.onAdvance();
    }

    var onActivateCallback = this.onActivateCallback = function()
    {
        _this.parent.stepIndex = _index;
        _this.updateState();
        _this.onActivate();
    }
}

Rf.Controls.WizardPopupStep.registerClass("Rf.Controls.WizardPopupStep");

// ------------------------------------------------------------------------------------










