﻿// ------------------------------------------------------------------------------------
// 
// 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.__debug = true;
// ------------------------------------------------------------------------------------
// Rf/WebRequest.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

// ------------------------------------------------------------------------------------
// WebRequest
// ------------------------------------------------------------------------------------

Rf.WebRequest = function(requestUrl)
{
    this.requestUrl = requestUrl;

    this.onCompleted = function() { }
    this.onFailed = function() { }

    this.timeout = Rf.WebRequest.requestTimeout;
    this.acceptLanguage = Sys.CultureInfo.CurrentCulture.name;
    this.contentType = "text/plain; charset=utf-8";
}

Rf.WebRequest.prototype =
{
    invoke: function()
    {
        var params = arguments.length > 0 ?
                        (arguments.length > 1 ? Rf.WebRequest.createRequestParameters(arguments) : arguments[0]) :
                        {};

        var request = new Sys.Net.WebRequest();
        request.get_headers()['Content-Type'] = this.contentType;
        request.get_headers()['Accept-Language'] = String.format("{0},{1};q=0.5", this.acceptLanguage, this.acceptLanguage.substr(0, this.acceptLanguage.indexOf("-")));

        request.set_url(Rf.WebRequest.createRequestUrl(this.requestUrl, params));

        request.set_body(null);
        request.add_completed(onComplete.$delegate(this));

        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
                {
                    result = response.get_responseData();
                }
                catch (ex) { }

                if ((statusCode < 200) || (statusCode >= 300))
                {
                    this.onFailed();
                }
                else
                {
                    this.onCompleted(result);
                }
            }
            else
            {
                this.onFailed();
            }
        }
    }
};

Rf.WebRequest.createRequestUrl = function(url, params)
{
    var result = url;

    var following = false;

    for (key in params)
    {
        if (typeof (params[key]) == "function")
            continue;

        if (following)
            result += "&";
        else
        {
            result += "?";
            following = true;
        }

        result += key + "=" + params[key];
    }

    return result;
}

Rf.WebRequest.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.WebRequest.requestTimeout = 30000;

Rf.WebRequest.registerClass("Rf.WebRequest");

if (!Rf.__noGlobals)
{
    var WebRequest = Rf.WebRequest;
    WebRequest.registerClass("WebRequest");
}

// ------------------------------------------------------------------------------------



// ------------------------------------------------------------------------------------
// 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.UI.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------
// 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), HTMLElement.prototype);
    }
}

Rf.DomUtility.applyDomInheritance = function(element, baseObject)
{
    if (element != null && baseObject != null)
    {
        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;

    if (document.all)
        Rf.DomUtility.applyDomInheritance(result, HTMLElement.prototype);

    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;

    if (!root.childNodes)
        return null;

    for (var n = 0; n < root.childNodes.length; n++)
    {
        if (Rf.DomUtility.elementHasAttribute(root.childNodes[n], attributeName, attributeValue, exact))
            return root.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;
}

if (document.all && !$isDefined("HTMLElement"))
{
    HTMLElement = function() { };
    HTMLElement.prototype = {};
}

var $byId = function(elementId)
{
    if (!elementId)
        return null;

    var result;
    
    if (typeof (elementId) == "string")
        result = $get(elementId);
    else
        result = elementId;

    if (document.all)
        Rf.DomUtility.applyDomInheritance(result, HTMLElement.prototype);

    return result;
}
HTMLElement.prototype.$byId = function(elementId) { return $byId(elementId, this); }

var $byClass = function(elementClassName, scope)
{
    if (!elementClassName)
        return null;

    var result;

    if (typeof (elementClassName) == "string")
        result = Rf.DomUtility.getElementByClassName(elementClassName, scope);
    else
        result = elementClassName;

    if (document.all)
        Rf.DomUtility.applyDomInheritance(result, HTMLElement.prototype);

    return result;
}
HTMLElement.prototype.$byClass = function(elementClassName) { return $byClass(elementClassName, this); }


var $byAttribute = function(attributeName, attributeValue, scope)
{
    if (!attributeName || !attributeValue)
        return null;

    var result;
    
    if (typeof (attributeName) == "string")
        result = Rf.DomUtility.getElementByAttribute(attributeName, attributeValue, true, scope);
    else
        result = attributeName;

    if (document.all)
        Rf.DomUtility.applyDomInheritance(result, HTMLElement.prototype);
        
    return result;
}
HTMLElement.prototype.$byAttribute = function(attributeName, attributeValue) { return $byAttribute(elementClassName, attributeValue, this); }


var $byTagName = function(elementTagName, scope)
{
    if (!elementTagName)
        return null;

    var result;

    if (!scope)
        scope = document;

    result = scope.getElementsByTagName(elementTagName);

    if (document.all)
    {
        for ( var n=0; n<result.length; n++ )
            Rf.DomUtility.applyDomInheritance(result[n], HTMLElement.prototype);
    }

    return result;
}
HTMLElement.prototype.$byTagName = function(elementTagName) { return $byTagName(elementTagName, this); }

var $byName = function(elementName, scope)
{
    return $byAttribute("name", elementName, scope);
}
HTMLElement.prototype.$byName = function(elementName) { return $byName(elementName, this); }

var $clone = function(element)
{
    if (typeof (element.innerHTML) != "undefined")
        return  Rf.DomUtility.cloneElement(element);
    else
        return element.clone();
}

HTMLElement.prototype.$clone = function()
{
    return $clone(this);
}

var $createElement = function(tagName)
{
    if (!tagName)
        throw "Element tag name not provided.";

    return document.createElement(tagName);
}
HTMLElement.prototype.$createChild = function(tagName) { return this.appendChild($createElement(tagName)); }







// ------------------------------------------------------------------------------------
// 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);
}

window.evalOrCall = function(func) {
    if (func == null)
        return;

    if (this != window)
        window.evalOrCall.apply(window, arguments);

    var args = [];

    for (var n = 1; n < arguments.length; n++)
        args.push(arguments[n]);

    if (typeof (func) == "string")
        eval(func);
    else
        func.apply(null, args);
}

// ------------------------------------------------------------------------------------









// ------------------------------------------------------------------------------------
// 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.select = function(selectElement, value)
{
    selectElement = $byId(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.FormUtility.push = function(form, src)
{
    form = $byId(form);

    for (var n = 0; n < form.length; n++)
    {
        var item = form[n];

        if (!item.name || !src[item.name])
            continue;

        if (item.type == "text" || item.type == "password" ||
            item.type == "textarea" || item.tagName == "textarea")
        {
            item.value = src[item.name];
        }
        else if (item.type == "checkbox")
        {
            item.checked = (src[item.name] && true);
        }
        else if (item.type == "radio")
        {
            if (item.value == src[item.name])
                item.checked = true;
        }
        else if (item.tagName == "select")
        {
            for (var m = 0; m < item.options.length; m++)
            {
                var option = item.options[m];

                if (option.value == src[item.name])
                {
                    item.selectedIndex = m;
                    break;
                }
            }
        }
    }
}

Rf.FormUtility.pull = function(form, dst)
{
    if (!dst)
        dst = {};

    form = $byId(form);

    for (var n = 0; n < form.length; n++)
    {
        var item = form[n];

        if (item.type == "text" || item.type == "password" ||
            item.type == "textarea" || item.tagName == "textarea")
        {
            dst[item.name] = item.value;
        }
        else if (item.type == "checkbox")
        {
            dst[item.name] = item.checked;
        }
        else if (item.type == "radio")
        {
            if (item.checked)
                dst[item.name] = item.value;
        }
        else if (item.tagName == "select" && item.selectedIndex >= 0)
        {
            dst[item.name] = item.options[item.selectedIndex].value;
        }
    }

    return dst;
}

if (!Rf.__noGlobals)
{
    var FormUtility = Rf.FormUtility;
    Type.registerNamespace("FormUtility");
}

// ------------------------------------------------------------------------------------

















// ------------------------------------------------------------------------------------
// 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();
    }
}


if (!Rf.__noGlobals)
{
    var OnLoad = Rf.OnLoad;
}

// ------------------------------------------------------------------------------------




// ------------------------------------------------------------------------------------
// 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;
}

if (!Rf.__noGlobals)
{
    var OnInit = Rf.OnInit;
}

// ------------------------------------------------------------------------------------






// ------------------------------------------------------------------------------------
// Rf.UI.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;
}

if (!Rf.__noGlobals)
{
    Screen = Rf.Screen;
}
// ------------------------------------------------------------------------------------



// ------------------------------------------------------------------------------------
// 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.WebRequest.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.useHttpGet)
        {
            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.servicesUrl = "http://cantoso.org/WebServices/";
Rf.WebMethod.servicesUrlSuffix = ".asmx";
Rf.WebMethod.requestTimeout = 3000;

Rf.WebMethod.registerClass("Rf.WebMethod");

if (!Rf.__noGlobals)
{
    var WebMethod = Rf.WebMethod;
    WebMethod.registerClass("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/WebResource.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

// ------------------------------------------------------------------------------------
// Rf.WebResource
// ------------------------------------------------------------------------------------

Rf.WebResource = function(resourceName, resourcePath, onLoadCallback)
{
    this.resourceName = resourceName;
    this.resourcePath = resourcePath;

    this.requestUrl = Rf.WebResource.resourcesUrl;

    this.isLoaded = false;
    this.isLoading = false;

    this.content = null;

    this.onLoad = onLoadCallback ? onLoadCallback : function() { };
}

Rf.WebResource.prototype =
{
    load: function()
    {
        this.isLoading = true;
        var request = new Rf.WebRequest(this.requestUrl + this.resourcePath);
        request.onCompleted = this.onLoadCallback.$delegate(this);
        request.invoke("resourceName", this.resourceName);
    },

    onLoadCallback: function(result)
    {
        this.isLoaded = true;
        this.content = result;
        this.isLoading = false;
        
        if (typeof (this.onLoad) == "string")
            eval(this.onLoad);
        else
            this.onLoad(result);
    }
};

Rf.WebResource.resourcesUrl = "http://cantoso.org/Resources/";

Rf.WebResource.resoucesElement = null;
Rf.WebResource.resouces = {};

Rf.WebResource.initialize = function()
{
    if (Rf.WebResource.resoucesElement != null)
        return;

    var bodyElement = $byTagName("body")[0];

    Rf.WebResource.resoucesElement = document.createElement("div");
    $markupResourceBag = Rf.WebResource.resoucesElement;

    // Deprecated:
    // bodyElement.appendChild(Rf.WebResource.resoucesElement);
}

var $markupResourceBag = Rf.WebResource.resoucesElement;

var $markupResource = function(element)
{
    var result = Rf.WebResource.resoucesElement.$byId(element);

    if (!result)
        result = Rf.WebResource.resoucesElement.$byClass(element);

    return result;
}

Rf.WebResource.loadScript = $loadScript = function(resourceName, onLoad, scriptType)
{
    if (!scriptType)
        scriptType = "Script";
        
    var uniqueName = "__script_" + resourceName;

    var oldRes = Rf.WebResource.resouces[uniqueName];

    if (oldRes)
    {
        if (oldRes.isLoaded)
        {
            evalOrCall(onLoad, oldRes.content);
        }
        else
        {
            var oldFunc = oldRes.onLoad;
            oldRes.onLoad = function(content)
            {
                evalOrCall(oldFunc, content);
                evalOrCall(onLoad, content);
            };
        }

        return oldRes;
    }

    if (Rf.WebResource.resoucesElement == null)
        Rf.WebResource.initialize();

    var onLoadCallback = function(content)
    {
        Rf.WebResource.registerScript(resourceName, content);

        evalOrCall(onLoad, content);
    }

    var res = new Rf.WebResource(resourceName, scriptType, onLoadCallback.$delegate(this));
    res.load();

    Rf.WebResource.resouces[uniqueName] = res;

    return res;
}

Rf.WebResource.loadDynamicScript = $loadDynamicScript = function(resourceName, onLoad)
{
    return $loadScript(resourceName, onLoad, "DynamicScript");
}

Rf.WebResource.loadMarkup = $loadMarkup = function(resourceName, onLoad)
{
    var uniqueName = "__markup_" + resourceName;

    var oldRes = Rf.WebResource.resouces[uniqueName];

    if (oldRes)
    {
        if (oldRes.isLoaded)
        {
            evalOrCall(onLoad, oldRes.content);
        }
        else
        {
            var oldFunc = oldRes.onLoad;
            oldRes.onLoad = function(content)
            {
                evalOrCall(oldFunc, content);
                evalOrCall(onLoad, content);
            };
        }

        return oldRes;
    }

    if (Rf.WebResource.resoucesElement == null)
        Rf.WebResource.initialize();

    var onLoadCallback = function(content)
    {
        Rf.WebResource.registerMarkup(resourceName, content);

        evalOrCall(onLoad, content);
    }

    var res = new Rf.WebResource(resourceName, "Markup", onLoadCallback.$delegate(this));
    res.load();

    Rf.WebResource.resouces[uniqueName] = res;

    return res;
}

Rf.WebResource.load = $loadResource = function(resourceName, onLoad)
{
    var res = new Rf.WebCombinedResource(resourceName, onLoad);
    res.load();
    
    return res;
}

//if (Rf.__debug)
//{
//    Rf.WebResource.registerScript = function(resourceName, content)
//    {
//        var uniqueName = "__script_" + resourceName;

//        var el = document.createElement("script");
//        el.attributes["resourceName"] = resourceName;
//        el.type = "text/javascript";
//        el.src =
//            Rf.WebResource.resouces[uniqueName].requestUrl +
//            Rf.WebResource.resouces[uniqueName].resourcePath + "?resourceName=" +
//            resourceName;
//            
//        Rf.WebResource.resoucesElement.appendChild(el);
//    }
//}
//else
//{
    Rf.WebResource.registerScript = function(resourceName, content)
    {
        //    var el = document.createElement("script");
        //    el.resourceName = resourceName;
        //    el.type = "text/javascript";
        //    el.innerHTML = content.replace(/^\/\/\/.*$/gmi, "");

        //    Rf.WebResource.resoucesElement.appendChild(el);

        window.evalOrCall(content);
    }
//}

Rf.WebResource.registerMarkup = function(resourceName, content)
{
    var el = document.createElement("div");
    el.resourceName = resourceName;
    el.innerHTML = content;

    Rf.WebResource.resoucesElement.appendChild(el);
}



Rf.OnInit.register(Rf.WebResource.initialize);


Rf.WebResource.registerClass("Rf.WebResource");

if (!Rf.__noGlobals)
{
    var WebResource = Rf.WebResource;
    WebResource.registerClass("WebResource");
}

// ------------------------------------------------------------------------------------











// ------------------------------------------------------------------------------------
// Rf.WebCombinedResource
// ------------------------------------------------------------------------------------

Rf.WebCombinedResource = function(resourceName, onLoad)
{
    this.resourceName = resourceName;

    this.scriptResource = null;
    this.markupResource = null;

    this.isLoaded = false;

    this.onLoad = onLoad ? onLoad : function() { };
    this.onScriptLoad = function() { };
    this.onMarkupLoad = function() { };
}

Rf.WebCombinedResource.prototype =
{
    load: function()
    {
        this.isLoaded = false;

        this.scriptResource = Rf.WebResource.loadScript(this.resourceName, this.onScriptLoadCallback.$delegate(this));
        this.markupResource = Rf.WebResource.loadMarkup(this.resourceName, this.onMarkupLoadCallback.$delegate(this));
    },

    onScriptLoadCallback: function(content)
    {
        evalOrCall(this.onScriptLoad);

        if (!this.isLoaded && this.markupResource && this.markupResource.isLoaded)
            this.onLoadCallback();
    },

    onMarkupLoadCallback: function(content)
    {
        evalOrCall(this.onMarkupLoad);

        if (!this.isLoaded && this.scriptResource && this.scriptResource.isLoaded)
            this.onLoadCallback();
    },

    onLoadCallback: function()
    {
        this.isLoaded = true;

        evalOrCall(this.onLoad);
    }
};

Rf.WebCombinedResource.registerClass("Rf.WebCombinedResource");

if (!Rf.__noGlobals)
{
    var WebCombinedResource = Rf.WebCombinedResource;
    WebCombinedResource.registerClass("WebCombinedResource");
}

// ------------------------------------------------------------------------------------


// ------------------------------------------------------------------------------------
// Rf/Controls/Control.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// Control
// ------------------------------------------------------------------------------------

Rf.UI.UIElement = function()
{
    if (Rf.OnInit.reached)
        this.initialize();
    else
        Rf.OnInit.register(this.initialize.$delegate(this));
}

Rf.UI.UIElement.prototype =
{
    initialize: function()
    {
    }
}

Rf.UI.UIElement.registerClass("Rf.UI.UIElement");

if (!Rf.__noGlobals)
{
    var UIElement = Rf.UI.UIElement;
    UIElement.registerClass("UIElement");
}

// ------------------------------------------------------------------------------------






// ------------------------------------------------------------------------------------
// Rf/Controls/BoxPanel.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// BoxPanel
// ------------------------------------------------------------------------------------

Rf.UI.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.UI.BoxPanel.boxElementID;

    this.holderElementClassName = Rf.UI.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.UI.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.UI.BoxPanel.boxElementID = "Rf.UI.BoxPanel";
Rf.UI.BoxPanel.boxElementHolderClass = "Rf.UI.BoxPanelHolder";

Rf.UI.BoxPanel.registerClass("Rf.UI.BoxPanel");

// ------------------------------------------------------------------------------------











// ------------------------------------------------------------------------------------
// Rf/Controls/Button.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// Generic button class
// ------------------------------------------------------------------------------------

Rf.UI.Button = function(buttonElement, applyStyles)
{
    this.applyStyles = applyStyles == null ? true : applyStyles;

    this.disabledClassName = "disabled";
    this.buttonClassName = "button";
    this.hiddenClassName = "hidden";

    this.buttonElement = buttonElement;

    this.visible = true;
    this.enabled = true;

    this.onClick = function() { };

    Rf.UI.Button.initializeBase(this, [buttonElement]);
}

Rf.UI.Button.prototype =
{
    initialize: function()
    {
        Rf.UI.Button.callBaseMethod(this, "initialize");

        this.buttonElement = $byId(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);

        $addHandler(this.buttonElement, "click", this.onClickCallback.$delegate(this));

        if (this.buttonElement.onclick)
            this.onClick = this.buttonElement.onclick;

        if (this.buttonElement.className)
            this.buttonClassName += " " + this.buttonElement.className;

        this.updateButtonElementState();
    },

    setEnabled: function(value)
    {
        this.enabled = value;
        this.updateButtonElementState();
    },

    setVisible: function(value)
    {
        this.visible = value;
        this.updateButtonElementState();
    },

    updateButtonElementState: function()
    {
        if (!this.applyStyles)
            return;
            
        var className = this.buttonClassName;

        if (!this.enabled)
            className += " " + this.disabledClassName;

        if (!this.visible)
            className += " " + this.hiddenClassName;

        this.buttonElement.className = className;
    },

    onClickCallback: function(evt)
    {
        evt.preventDefault();

        if (this.enabled && this.visible)
            this.onClick();

        return false;
    }
};

Rf.UI.Button.registerClass("Rf.UI.Button", Rf.UI.UIElement);

if (!Rf.__noGlobals)
{
    var Button = Rf.UI.Button;
    Button.registerClass("Button", UIElement);
}

// ------------------------------------------------------------------------------------









// ------------------------------------------------------------------------------------
// Rf/Controls/ClickEditor.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// ClickEditor
// ------------------------------------------------------------------------------------

Rf.UI.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.UI.ClickEditor.hoverClassName;
    this.inputClassName = Rf.UI.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.UI.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.UI.ClickEditor.hoverClassName = "clickEditorHover";
Rf.UI.ClickEditor.inputClassName = "clickEditorInput";

Rf.UI.ClickEditor.registerClass("Rf.UI.ClickEditor");

// ------------------------------------------------------------------------------------







// ------------------------------------------------------------------------------------
// Rf/Controls/DropDown.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// Stylable dropdown class
// ------------------------------------------------------------------------------------

Rf.UI.DropDown = function(originElement)
{
    this.controlClassName = "dropDown";
    this.disabledClassName = "disabled";
    this.hiddenClassName = "hidden";
    this.focusClassName = "focus";
    this.droppedClassName = "dropped";

    this.keyCodeDown = 12;
    this.keyCodeUp = 12;
    this.keyCodeReturn = 12;
    this.keyCodeEscape = 12;

    this.originElementClassName = "replaced";

    this.originElement = originElement;
    this.controlElement = null;
    this.selectorElement = null;
    this.optionsElement = null;

    this.hasFocus = false;
    this.visible = true;
    this.enabled = true;
    this.dropped = false;

    this.onClick = function() { };
    this.onFocus = function() { };
    this.onBlur = function() { };
    this.onKeyDown = function() { }; // TODO: implement this
    this.onChange = function() { }; // TODO: implement delayed text change event

    Rf.UI.DropDown.initializeBase(this, [originElement]);
}

Rf.UI.DropDown.prototype =
{
    initialize: function()
    {
        Rf.UI.DropDown.callBaseMethod(this, "initialize");

        // result:
        // <div>
        //      <span onclick="setOptionsVisible(true);">Current option</span>
        //      <ul onClick="setOptionsVisible(false);" onMouseOut="setFocusIndex(-1);">
        //          <li onclick="showOptionAt(0);setSelectedIndex(0);" onmouseover="setFocusIndex(0);">Option 1</li>
        //          <li onclick="showOptionAt(1);setSelectedIndex(1);" onmouseover="setFocusIndex(1);">Option 1</li>
        //      </ul>
        // </div>
        // 1. Create the select element with onClick event handled
        // 2. Iterate through the original items
        // 3. For each create a <li> element with an onClick event handled
        //

        this.originElement = $byId(this.originElement);

        if (!this.originElement)
            throw "Invalid origin element.";

        this.initializeControlElement();

        $addHandler(this.controlElement, "click", this.onClickCallback.$delegate(this));
        $addHandler(this.selectorElement, "mousedown", this.onSelectorClickCallback.$delegate(this));
        $addHandler(this.originElement, "focus", this.onFocusCallback.$delegate(this));
        $addHandler(this.originElement, "blur", this.onBlurCallback.$delegate(this));
        $addHandler(this.originElement, "change", this.onChangeCallback.$delegate(this));
        $addHandler(this.originElement, "keyup", this.onKeyUpCallback.$delegate(this));
    },

    initializeControlElement: function()
    {
        if (this.originElement.className)
            this.controlClassName += " " + this.originElement.className;

        // Create empty elements
        this.controlElement = this.originElement.parentNode.appendChild($createElement("div"));
        this.selectorElement = this.controlElement.appendChild($createElement("span"));
        this.optionsElement = this.controlElement.appendChild($createElement("ul"));

        this.controlElement.className = this.controlClassName;

        if (this.originElement.attributes['style'])
            this.controlElement.attributes.setNamedItem(this.originElement.attributes.style.cloneNode(false));

        // Create items
        for (var i = 0; i < this.originElement.length; i++)
        {
            var originalItem = this.originElement.options[i];
            var item = this.optionsElement.appendChild($createElement("li"));
            item.optionIndex = i;

            item.innerHTML = originalItem.text;
            $addHandler(item, "mousedown", function(evt)
            {
                this.dropped = false;
                this.setSelectedIndex(evt.target.optionIndex);
                this.updateElementState();
                evt.preventDefault();
            } .$delegate(this));
        }

        this.updateSelector();

        this.originElement.className = this.originElementClassName;
    },

    updateSelector: function()
    {
        this.selectorElement.innerHTML =
            this.originElement.options[this.originElement.selectedIndex].text;
    },

    setSelectedIndex: function(index)
    {
        this.originElement.selectedIndex = index;

        this.updateSelector();
    },

    setEnabled: function(value)
    {
        this.enabled = value;
        this.updateElementState();
    },

    setVisible: function(value)
    {
        this.visible = value;
        this.updateElementState();
    },

    updateElementState: function()
    {
        var className = this.controlClassName;

        if (!this.visible)
            className += " " + this.hiddenClassName;

        if (!this.enabled)
            className += " " + this.disabledClassName;

        if (this.dropped)
            className += " " + this.droppedClassName;

        if (this.hasFocus)
            className += " " + this.focusClassName;

        this.controlElement.className = className;
    },

    onKeyUpCallback: function(evt)
    {
        if (evt.keyCode == this.keyCodeReturn || evt.keyCode == this.keyCodeEscape)
        {
            this.dropped = false;
            this.updateElementState();
        }

        this.updateSelector();
    },

    onSelectorClickCallback: function(evt)
    {
        evt.preventDefault(); // don't blur the origin element
        this.originElement.focus();

        this.dropped = !this.dropped;
        this.updateElementState();
    },

    onClickCallback: function(evt)
    {
    },

    onFocusCallback: function(evt)
    {
        this.hasFocus = true;

        this.updateElementState();
    },

    onBlurCallback: function(evt)
    {
        this.hasFocus = false;
        this.dropped = false;

        this.updateElementState();
    },

    onChangeCallback: function(evt)
    {
        this.updateSelector();

        this.dropped = false;
        this.updateElementState();
    }
};

Rf.UI.DropDown.registerClass("Rf.UI.DropDown", Rf.UI.UIElement);

if (!Rf.__noGlobals)
{
    var DropDown = Rf.UI.DropDown;
    DropDown.registerClass("DropDown", UIElement);
}

// ------------------------------------------------------------------------------------









// ------------------------------------------------------------------------------------
// Rf/Controls/ImagePopup.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// ImagePopup
// ------------------------------------------------------------------------------------

Rf.UI.ImagePopup = function() { };

Rf.UI.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.UI.Popup(contentElement);
    var globalLoading = new Rf.UI.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.UI.ImagePopup.registerClass("Rf.UI.ImagePopup");

// ------------------------------------------------------------------------------------






// ------------------------------------------------------------------------------------
// Rf/Controls/Input.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// Generic input class
// ------------------------------------------------------------------------------------

Rf.UI.Input = function(inputElement, labelValue)
{
    this.inputClassName = "input";
    this.disabledClassName = "disabled";
    this.hiddenClassName = "hidden";
    this.focusClassName = "focus";

    this.labelValue = labelValue ? labelValue : "";

    this.inputElement = inputElement;
    this.baseClassName = "";

    this.hasFocus = false;
    this.visible = true;
    this.enabled = true;

    this.handleTabs = false;
    this.tabsText = "\t";
    this.tabsCharCode = 9;

    this.onClick = function() { };
    this.onFocus = function() { };
    this.onBlur = function() { };
    this.onKeyDown = function() { }; // TODO: implement this
    this.onChange = function() { }; // TODO: implement delayed text change event

    Rf.UI.Input.initializeBase(this, [inputElement, labelValue]);
}

Rf.UI.Input.prototype =
{
    initialize: function()
    {
        Rf.UI.Input.callBaseMethod(this, "initialize");
        
        this.inputElement = $byId(this.inputElement);

        if (!this.inputElement)
            throw "Invalid input element.";

        this.enabled = !Rf.DomUtility.elementHasAttribute("className", this.disabledClassName, false, this.inputElement);
        this.visible = !Rf.DomUtility.elementHasAttribute("className", this.hiddenClassName, false, this.inputElement);

        $addHandler(this.inputElement, "click", this.onClickCallback.$delegate(this));
        $addHandler(this.inputElement, "focus", this.onFocusCallback.$delegate(this));
        $addHandler(this.inputElement, "blur", this.onBlurCallback.$delegate(this));
        $addHandler(this.inputElement, "keydown", this.onKeyDownCallback.$delegate(this));

        if (this.inputElement.className)
            this.inputClassName = this.inputElement.className;

        this.onBlurCallback();
    },

    setEnabled: function(value)
    {
        this.enabled = value;
        this.updateElementState();
    },

    setVisible: function(value)
    {
        this.visible = value;
        this.updateElementState();
    },

    updateElementState: function()
    {
        var className = this.inputClassName;

        if (!this.enabled)
            className += " " + this.disabledClassName;

        if (!this.visible)
            className += " " + this.hiddenClassName;

        if (this.hasFocus)
            className += " " + this.focusClassName;

        this.inputElement.className = className;
    },

    onKeyDownCallback: function(evt)
    {
        if (this.handleTabs && evt.keyCode == this.tabsCharCode)
        {
            evt.preventDefault();

            Rf.DomUtility.insertAtCursor(this.inputElement, this.tabsText);
        }
    },

    onClickCallback: function(evt)
    {
        evt.preventDefault();

        if (this.enabled && this.visible)
            this.onClick();

        return false;
    },

    onFocusCallback: function(evt)
    {
        this.hasFocus = true;
        this.updateElementState();

        if (this.inputElement.value == this.labelValue)
            this.inputElement.value = "";

        this.onFocus(evt);
    },

    onBlurCallback: function(evt)
    {
        this.hasFocus = false;
        this.updateElementState();

        if (this.inputElement.value.length == 0)
            this.inputElement.value = this.labelValue;

        this.onBlur(evt);
    }
};

Rf.UI.Input.registerClass("Rf.UI.Input", Rf.UI.UIElement);

if (!Rf.__noGlobals)
{
    var Input = Rf.UI.Input;
    Input.registerClass("Input", UIElement);
}

// ------------------------------------------------------------------------------------









// ------------------------------------------------------------------------------------
// Rf/Controls/LoadingControl.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// LoadingControl
// ------------------------------------------------------------------------------------

Rf.UI.LoadingControl = function(hostElement, originElement)
{
    this.hostElement = hostElement;
    this.originElement = originElement;
    this.mainElement = null;

    Rf.UI.LoadingControl.initializeBase(this, [hostElement, originElement]);
}

Rf.UI.LoadingControl.prototype =
{
    initialize: function()
    {
        Rf.UI.LoadingControl.callBaseMethod(this, "initialize");

        if (!this.originElement)
            this.originElement = Rf.UI.LoadingControl.getOriginElement();
        else
            this.originElement = $markupResource(this.originElement);

        this.hostElement = $markupResource(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.UI.LoadingControl.originElement = "tplLoadingControl";

Rf.UI.LoadingControl.getOriginElement = function()
{
    if (typeof (Rf.UI.LoadingControl.originElement) == "string" )
        Rf.UI.LoadingControl.originElement = $markupResource(Rf.UI.LoadingControl.originElement);

    return Rf.UI.LoadingControl.originElement;
}

Rf.UI.LoadingControl.registerClass("Rf.UI.LoadingControl", Rf.UI.UIElement);

if (!Rf.__noGlobals)
{
    var LoadingControl = Rf.UI.LoadingControl;
    LoadingControl.registerClass("LoadingControl", UIElement);
}

// ------------------------------------------------------------------------------------





// ------------------------------------------------------------------------------------
// GlobalLoading singleton
// ------------------------------------------------------------------------------------

Rf.UI.GlobalLoading = function()
{
    if (Rf.UI.GlobalLoading.instance != null)
        return Rf.UI.GlobalLoading.instance;

    this.popup = null;
    this.LoadingControl = null;

    Rf.UI.GlobalLoading.initializeBase(this);

    Rf.UI.GlobalLoading.instance = this;
}

Rf.UI.GlobalLoading.instance = null;

Rf.UI.GlobalLoading.prototype =
{
    initialize: function()
    {
        Rf.UI.GlobalLoading.callBaseMethod(this, "initialize");

        this.popup = new Rf.UI.Popup("tplGlobalLoading");
        this.loadingControl = new Rf.UI.LoadingControl(this.popup.contentElement);
        this.loadingControl.start();
    },

    start: function()
    {
        this.popup.show();
    },

    stop: function()
    {
        this.popup.close();
    }
};

Rf.UI.GlobalLoading.registerClass("Rf.UI.GlobalLoading", Rf.UI.UIElement);

if (!Rf.__noGlobals)
{
    var GlobalLoading = Rf.UI.GlobalLoading;
    GlobalLoading.registerClass("GlobalLoading", UIElement);
}

// ------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------
// Rf/Controls/TopMenu.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");




// ------------------------------------------------------------------------------------
// MenuBar supersingleton
// ------------------------------------------------------------------------------------

Rf.UI.MenuBar = function()
{
    if (Rf.UI.MenuBar.instance != null)
        return Rf.UI.MenuBar.instance;

    this.barElement = null;
    this.subItemsElement = null;

    this.subItems = {};

    Rf.UI.MenuBar.initializeBase(this);

    Rf.UI.MenuBar.instance = this;
}

Rf.UI.MenuBar.prototype =
{
    initialize: function()
    {
        this.barElement =
            document.createElement(Rf.UI.MenuBar.barElementTagName);
        this.barElement.className =
            Rf.UI.MenuBar.barElementClassName;

        this.subItemsElement = document.createElement("ul");
        this.barElement.appendChild(this.subItemsElement);

        document.body.insertBefore(this.barElement, document.body.firstChild);
    },

    addItem: function(name, label, onClick)
    {
        this.subItems[name] =
            new Rf.UI.MenuItem(this.subItemsElement, name, label, onClick);
    }
};

Rf.UI.MenuBar.instance = null;
Rf.UI.MenuBar.barElementTagName = "div";
Rf.UI.MenuBar.barElementClassName = "menuBar";

Rf.UI.MenuBar.registerClass("Rf.UI.MenuBar", Rf.UI.UIElement);

if (!Rf.__noGlobals)
{
    var MenuBar = Rf.UI.MenuBar;
    MenuBar.registerClass("MenuBar", UIElement);
}

// ------------------------------------------------------------------------------------






// ------------------------------------------------------------------------------------
// MenuItem
// ------------------------------------------------------------------------------------

Rf.UI.MenuItem = function(hostElement, name, label, onClick)
{
    this.name = name;
    this.label = label;

    this.hostElement = hostElement;

    this.containerElement = null;
    this.itemElement = null;
    this.subItemsElement = null;

    this.subItems = {};

    this.onClick = onClick ? onClick : function() { };

    Rf.UI.MenuItem.initializeBase(this);
}

Rf.UI.MenuItem.prototype =
{
    initialize: function()
    {
        Rf.UI.MenuItem.callBaseMethod(this, "initialize");

        this.containerElement = document.createElement("li");

        this.itemElement = document.createElement("a");
        this.itemElement.href = "#";
        this.itemElement.innerHTML = this.label;
        $addHandler(this.itemElement, "click", function(evt){evt.preventDefault();} );
        $addHandler(this.itemElement, "click", this.onClickCallback.$delegate(this));

        this.subItemsElement = document.createElement("ul");

        this.containerElement.appendChild(this.itemElement);
        this.containerElement.appendChild(this.subItemsElement);

        this.hostElement.appendChild(this.containerElement);
    },
    
    onClickCallback: function()
    {
        this.onClick();
    },

    addSubItem: function(name, label, onClick)
    {
        this.subItems[name] =
            new Rf.UI.MenuItem(this.subItemsElement, name, label, onClick);
    }
};


Rf.UI.MenuItem.registerClass("Rf.UI.MenuItem", Rf.UI.UIElement);

if (!Rf.__noGlobals)
{
    var MenuItem = Rf.UI.MenuItem;
    MenuItem.registerClass("MenuItem", UIElement);
}

// ------------------------------------------------------------------------------------





// ------------------------------------------------------------------------------------
// Rf/Controls/MessageBox.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// MessageBox
// ------------------------------------------------------------------------------------

Rf.UI.MessageBox = function() { };

Rf.UI.MessageBox.message = function(text, title, btnOk_callback)
{
    if (title && typeof (title) == "function")
    {
        btnOk_callback = title;
        title = null;
    }

    Rf.UI.MessageBox.showDialog("tplMessageBox_message", text, title, btnOk_callback);
}

Rf.UI.MessageBox.success = function(text, title, btnOk_callback)
{
    if (title && typeof (title) == "function")
    {
        btnOk_callback = title;
        title = null;
    }

    Rf.UI.MessageBox.showDialog("tplMessageBox_success", text, title, btnOk_callback);
}

Rf.UI.MessageBox.error = function(text, title, btnOk_callback)
{
    if (title && typeof (title) == "function")
    {
        btnOk_callback = title;
        title = null;
    }

    Rf.UI.MessageBox.showDialog("tplMessageBox_error", text, title, btnOk_callback);
}

Rf.UI.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.UI.MessageBox.showDialog("tplMessageBox_question", text, title, btnYes_callback, btnNo_callback);    
}


Rf.UI.MessageBox.showDialog = function(dialogClassName, text, title, btnOk_callback, btnCancel_callback)
{
    var popup = new Rf.UI.Popup(dialogClassName);

    var textElement = popup.contentElement.$byClass("ctlText");
    textElement.innerHTML = text;

    if (title)
    {
        var titleElement = popup.contentElement.$byClass("ctlTitle");
        titleElement.innerHTML = title;
    }

    var buttonOkElement = popup.contentElement.$byClass("btnOk");
    var buttonCancelElement = popup.contentElement.$byClass("btnCancel");


    if (buttonOkElement)
    {
        $addHandler(buttonOkElement, "click", function(evt) { evt.preventDefault(); });
        $addHandler(buttonOkElement, "click", popup.destroy.$delegate(popup));

        if (btnOk_callback)
            $addHandler(buttonOkElement, "click", btnOk_callback);
    }
    if (buttonCancelElement)
    {
        $addHandler(buttonCancelElement, "click", function(evt) { evt.preventDefault(); });
        $addHandler(buttonCancelElement, "click", popup.destroy.$delegate(popup));

        if (btnCancel_callback)
            $addHandler(buttonCancelElement, "click", btnCancel_callback);
    }

    popup.show();
}


Rf.UI.MessageBox.registerClass("Rf.UI.MessageBox");

if (!Rf.__noGlobals)
{
    var MessageBox = Rf.UI.MessageBox;
    MessageBox.registerClass("MessageBox");
}

// ------------------------------------------------------------------------------------










// --------------------------------------------------------------------------------
// Rf/Controls/MultiEditor.js
// --------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// MultiEditor
// ------------------------------------------------------------------------------------

Rf.UI.MultiEditor = function(hostElementID, addFormTemplateID, editFormTemplateID)
{
    this.hostElementID = hostElementID;
    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;

    Rf.UI.MultiEditor.initializeBase(this);
}

Rf.UI.MultiEditor.prototype =
{
    initialize: function()
    {
        this.hostElement = $markupResource(this.hostElementID);

        if (!this.hostElement)
            throw "Invalid host element.";

        this.hostElement.multiEditor = this;

        this.loadingControl = new LoadingControl(this.hostElement);
    },

    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;
    },

    loadList: function()
    {
        if (!this.isModified) // nothing new
            return;

        var wmLoadList = new Rf.WebMethod(this.webService, this.webMethod_LoadList);

        wmLoadList.onCompleted = this.loadList_onSuccess.$delegate(this);
        wmLoadList.onFailed = this.loadList_onError.$delegate(this);

        if (!this.onListLoading())
            return;

        this.loadingControl.start();
        this.loadTemplateData();
        this.isLoading = true;

        wmLoadList.invoke(this.webMethodArguments_LoadList);
    },

    reload: function()
    {
        this.reset();
        this.loadList();
    },

    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); } .$delegate(this);

            wmGet.onFailed = this.loadTemplateData_onMethodFailed.$delegate(this);

            this.templateDataSourcesWorking++;

            if (sourceDef.arguments)
                wmGet.invoke(sourceDef.arguments);
            else
                wmGet.invoke();
        }
    },

    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();
        }
    },

    loadTemplateData_onMethodFailed: function()
    {
        this.templateDataSourcesWorking--;
        this.templateDataSourcesFailed++;

        if (this.templateDataSourcesWorking <= 0 && !this.isLoading)
        {
            this.loadingControl.stop();
        }
    },

    loadList_onSuccess: function(data)
    {
        if (this.templateDataSourcesWorking > 0)
        {
            //Rf.UI.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;
        Rf.Template.fill(this.hostElement, this.templateData);

        this.isModified = false;
        this.onListLoaded();
    },

    loadList_onError: function()
    {
        this.isLoading = false;

        if (this.templateDataSourcesWorking <= 0)
            this.loadingControl.stop();

        if (!this.onListLoadError())
            return;

        MessageBox.error("Could not load element list."); // TODO: localize this somehow
    },

    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.$byTagName("form")[0];

        if (!this.currentForm)
            throw "Invalid template.";

        var btnSave = new Rf.UI.Button(this.currentForm.$byClass("btnSave"));
        btnSave.onClick = this.submitAddForm.$delegate(this);

        var btnCancel = new Rf.UI.Button(this.currentForm.$byClass("btnCancel"));
        btnCancel.onClick = this.closeForm.$delegate(this);

        this.isAdding = true;

        if (this.currentForm.$byTagName("input")[0])
            this.currentForm.$byTagName("input")[0].focus();
    },

    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;
    },

    submitAddForm: function()
    {
        if (!this.currentControlElement || !this.currentForm)
            return;

        if (!this.onItemAdding())
            return;

        this.addItem();
    },

    addItem: function()
    {
        var wmAdd = new Rf.WebMethod(this.webService, this.webMethod_Add);

        wmAdd.onCompleted = this.addItem_onCompleted.$delegate(this);
        wmAdd.onFailed = this.addItem_onFailed.$delegate(this);

        this.loadingControl.start();
        wmAdd.invoke(this.webMethodArguments_Add);
    },

    addItem_onCompleted: function(result)
    {
        this.closeForm();
        this.loadingControl.stop();
        this.isModified = true;

        if (!this.onItemAdded(result))
            return;

        this.reset();
        this.loadList();
    },

    addItem_onFailed: function()
    {
        this.loadingControl.stop();

        if (!this.onItemAddError())
            return;

        MessageBox.error("Could not add element."); // TODO: localize this somehow
    },

    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.$delegate(this);
        wmDelete.onFailed = this.deleteItem_onFailed.$delegate(this);

        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); } .$delegate(this),
            function() { });
    },

    deleteItem_onCompleted: function(result)
    {
        this.loadingControl.stop();
        this.currentDataItem = null;
        this.isModified = true;

        if (!this.onItemDeleted(result))
            return;

        this.reset();
        this.loadList();
    },

    deleteItem_onFailed: function()
    {
        this.loadingControl.stop();

        if (!this.onItemDeleteError())
            return;

        MessageBox.error("Could not delete element."); // TODO: localize this somehow
    },

    openEditForm: function(controlElement, index)
    {
        if (this.isEditing || this.isAdding)
            return;

        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.$byTagName("form")[0];

        var btnSave = new Rf.UI.Button(this.currentForm.$byClass("btnSave"));
        btnSave.onClick = this.submitEditForm.$delegate(this);

        var btnCancel = new Rf.UI.Button(this.currentForm.$byClass("btnCancel"));
        btnCancel.onClick = this.closeForm.$delegate(this);

        this.isEditing = true;

        if (this.currentForm.$byTagName("input")[0])
            this.currentForm.$byTagName("input")[0].focus();
    },

    submitEditForm: function()
    {
        if (!this.currentControlElement || !this.currentForm)
            return;

        if (!this.onItemUpdating())
            return;

        this.updateItem();
    },

    updateItem: function()
    {
        var wmUpdate = new Rf.WebMethod(this.webService, this.webMethod_Update);
        wmUpdate.onCompleted = this.updateItem_onCompleted.$delegate(this);
        wmUpdate.onFailed = this.updateItem_onFailed.$delegate(this);

        this.loadingControl.start();
        wmUpdate.invoke(this.webMethodArguments_Update);
    },

    updateItem_onCompleted: function(result)
    {
        this.closeForm();
        this.loadingControl.stop();
        this.currentDataItem = null;
        this.isModified = true;

        if (!this.onItemUpdated(result))
            return;

        this.reset();
        this.loadList();
    },

    updateItem_onFailed: function()
    {
        this.loadingControl.stop();

        if (!this.onItemUpdateError())
            return;

        MessageBox.error("Could not update element."); // TODO: localize this somehow
    }
};

Rf.UI.MultiEditor.getCurrent = function(controlElement)
{
    if (controlElement.multiEditor)
        return controlElement.multiEditor;
    else if (controlElement.parentNode)
        return Rf.UI.MultiEditor.getCurrent(controlElement.parentNode);
    else
        return null;
}

Rf.UI.MultiEditor.registerClass("Rf.UI.MultiEditor",Rf.UI.UIElement);

if (!Rf.__noGlobals)
{
    var MultiEditor = Rf.UI.MultiEditor;
    MultiEditor.registerClass("MultiEditor", UIElement);
}

// --------------------------------------------------------------------------------






// ------------------------------------------------------------------------------------
// Rf/Controls/Pager.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// Pager
// ------------------------------------------------------------------------------------

Rf.UI.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.UI.Button(_this.btnForward);
            _this.btnForward.onClick = _this.btnForward_click;
        }

        if (_this.btnBack)
        {
            _this.btnBack = new Rf.UI.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.UI.Pager.registerClass("Rf.UI.Pager");

// ------------------------------------------------------------------------------------









// ------------------------------------------------------------------------------------
// Rf/Controls/Popup.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// Popup
// ------------------------------------------------------------------------------------

Rf.UI.Popup = function(content, boxElement, onClose)
{
    this.contentElement = content;
    this.boxElementOrigin = boxElement;

    this.backgroundElement = null;
    this.boxElement = null;
    this.holderElement = null;

    this.index = -1;
    this.isActive = false;

    this.onClose = onClose ? onClose : function() { };

    Rf.UI.Popup.initializeBase(this, [content, boxElement]);
}

Rf.UI.Popup.prototype =
{
    initialize: function()
    {
        Rf.UI.Popup.callBaseMethod(this, "initialize");

        Rf.UI.Popup.prepareElements();

        this.boxElementOrigin = $markupResource(this.boxElementOrigin);
        
        if (!this.boxElementOrigin)
            this.boxElementOrigin = $markupResource(Rf.UI.Popup.boxElement); 

        this.contentElement = $markupResource(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 > Rf.Screen.getViewportHeight() ?
            document.documentElement.scrollHeight :
            Rf.Screen.getViewportHeight()) + "px";
        this.backgroundElement.style["width"] = "100%";
        this.backgroundElement.style["background"] = Rf.UI.Popup.backgroundColor;
        this.backgroundElement.style["filter"] = "alpha(opacity=" + Rf.UI.Popup.backgroundAlpha * 100 + ")";
        this.backgroundElement.style["opacity"] = "" + Rf.UI.Popup.backgroundAlpha;
        this.backgroundElement.style.zIndex = Rf.UI.Popup.initialIndex;


        // create the box elelment
        this.boxElement = $clone(this.boxElementOrigin);

        this.boxElement.style["position"] = "absolute";
        this.boxElement.style["top"] = "0px";
        this.boxElement.style["left"] = "-9998px";
        this.boxElement.style["display"] = "block";

        var contentHolder = this.boxElement.$byClass("ctlContent");

        // replace the holder element with content element
        this.boxElement.replaceChild(this.contentElement, contentHolder);

        // populate the elements
        Rf.UI.Popup.containerElement.appendChild(this.backgroundElement);
        Rf.UI.Popup.containerElement.appendChild(this.boxElement);
    },

    show: function(skipPositionUpdate)
    {
        if (this.isActive)
            this.close();

        this.backgroundElement.style["display"] = "block";

        Rf.UI.Popup.itemStack.push(this);

        Rf.UI.Popup.updateContainerVisibility();

        this.updateIndex(Rf.UI.Popup.itemStack.length - 1);

        this.updatePosition();

        Rf.UI.Popup.updateTopItem();

        this.isActive = true;

        this.boxElement.style["visibility"] = "visible";
    },

    updateIndex: function(newIndex)
    {
        this.index = newIndex;

        this.backgroundElement.style.zIndex = (Rf.UI.Popup.initialIndex + this.index * 2);
        this.boxElement.style.zIndex = (Rf.UI.Popup.initialIndex + this.index * 2 + 1);
    },

    setContents: function(content)
    {
        //if (content.parentNode)
        //content.parentNode.removeChild(content);

        this.contentElement = $clone(content);
        this.contentElement.style["display"] = "block";

        if (this.isActive)
            this.updatePosition();
    },


    updatePosition: function()
    {
        this.backgroundElement.style["height"] =
            (document.documentElement.scrollHeight > Rf.Screen.getViewportHeight() ?
            document.documentElement.scrollHeight :
            Rf.Screen.getViewportHeight()) + "px";

        this.boxElement.style["width"] = this.contentElement.offsetWidth + "px";
        //boxElement.style["height"] = this.contentElement.offsetHeight + "px";

        var top = (5 * this.index + Rf.Screen.getScrollY() + Rf.Screen.getViewportHeight() / 2 - this.contentElement.offsetHeight / 2);

        this.boxElement.style["top"] = (top > 0 ? top : 0) + "px";

        this.boxElement.style["left"] = 5 * this.index +
            (document.body.offsetWidth / 2 - this.boxElement.offsetWidth / 2) + "px";
    },

    close: function()
    {
        Rf.UI.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.UI.Popup.updateContainerVisibility();
        Rf.UI.Popup.updateItemIndexes();
        Rf.UI.Popup.updateTopItem();

        this.isActive = false;

        this.onClose();
    },

    destroy: function()
    {
        if (this.isActive)
            this.close();

        Rf.UI.Popup.containerElement.removeChild(this.boxElement);
        Rf.UI.Popup.containerElement.removeChild(this.backgroundElement);
    }
}


Rf.UI.Popup.backgroundColor = "#aaa";
Rf.UI.Popup.backgroundAlpha = 0.6;
Rf.UI.Popup.initialIndex = 200;

Rf.UI.Popup.containerElement = null;
Rf.UI.Popup.boxElement = null;

Rf.UI.Popup.itemStack = [];
Rf.UI.Popup.top = null;

Rf.UI.Popup.prepareElements = function()
{
    if (Rf.UI.Popup.containerElement != null ||
         Rf.UI.Popup.boxElement != null)
        return;

    Rf.UI.Popup.containerElement = document.createElement("div");
    Rf.UI.Popup.containerElement.className = "popupContainer";
    $byTagName("body")[0].appendChild(Rf.UI.Popup.containerElement);

    Rf.UI.Popup.boxElement = $markupResource("tplPopup");

    var viewportHeight = Rf.Screen.getViewportHeight();
    var height = document.getHeight();

    if (viewportHeight > height)
        height = viewportHeight;

    Rf.UI.Popup.containerElement.style["height"] = height + "px";
}

Rf.UI.Popup.updateContainerVisibility = function()
{
    Rf.UI.Popup.containerElement.style["display"] =
        Rf.UI.Popup.itemStack.length > 0 ? "block" : "none";

    var viewportHeight = Rf.Screen.getViewportHeight();
    var height = document.getHeight();

    if (viewportHeight > height)
        height = viewportHeight;

    Rf.UI.Popup.containerElement.style["height"] = height + "px";
}

Rf.UI.Popup.updateItemIndexes = function()
{
    for (var n = 0; n < Rf.UI.Popup.itemStack.length; n++)
        Rf.UI.Popup.itemStack[n].updateIndex(n);
}

Rf.UI.Popup.updateTopItem = function()
{
    if (Rf.UI.Popup.itemStack.length > 0)
    {
        Rf.UI.Popup.top = Rf.UI.Popup.itemStack[Rf.UI.Popup.itemStack.length - 1];
    }
    else
        Rf.UI.Popup.top = null;
}

Rf.UI.Popup.registerClass("Rf.UI.Popup",Rf.UI.UIElement);

if (!Rf.__noGlobals)
{
    var Popup = Rf.UI.Popup;
    Popup.registerClass("Popup", UIElement);
}

// ------------------------------------------------------------------------------------






// ------------------------------------------------------------------------------------
// Rf/Controls/TabControl.js
// ------------------------------------------------------------------------------------

if (!$isDefined("Rf"))
    Type.registerNamespace("Rf");

if (!$isDefined("Rf.UI"))
    Type.registerNamespace("Rf.UI");

// ------------------------------------------------------------------------------------
// Rf.UI.TabPanel
// ------------------------------------------------------------------------------------

Rf.UI.TabPanel = function(hostElement)
{
    this.hostElement = hostElement;

    this.elements = [];
    _activeIndex = -1;

    Rf.UI.TabPanel.initializeBase(this, [hostElement]);
}

Rf.UI.TabPanel.prototype =
{
    initialize: function()
    {
        Rf.UI.TabPanel.callBaseMethod(this, "initialize");

        this.hostElement = $byId(this.hostElement);

        var buttons = Rf.DomUtility.getElementsByAttribute("className", "tabButton", false, this.hostElement);
        var panels = Rf.DomUtility.getElementsByAttribute("className", "tabPanel", false, this.hostElement);

        for (var n = 0; n < buttons.length; n++)
        {
            var tabElement = new Rf.UI.TabPanelElement(buttons[n], panels[n], this);
            this.elements.push(tabElement);
        }

        if (this.elements.length > 0)
            this.setActiveIndex(0);
    },

    reset: function()
    {
        for (var n = 0; n < this.elements.length; n++)
            this.elements[n].active = false;
    },

    getActiveIndex: function()
    {
        return _activeIndex;
    },

    setActiveIndex: function(index, postDown)
    {
        if (!this.elements[index] ||
            !this.elements[index].isEnabled ||
            this.elements[index].isActive)
        {
            return;
        }

        _activeIndex = index;
        this.update();

        if (this.elements[index].isEnabled && this.elements[index].isActive)
            this.elements[index].onActivate();        
    },

    update: function()
    {
        for (var n = 0; n < this.elements.length; n++)
        {
            var tabElement = this.elements[n];
            tabElement.isActive = _activeIndex == n;
            tabElement.update();
        }
    }
};

Rf.UI.TabPanel.registerClass("Rf.UI.TabPanel", UIElement);

if (!Rf.__noGlobals)
{
    var TabPanel = Rf.UI.TabPanel;
    TabPanel.registerClass("TabPanel", UIElement);
}
// ------------------------------------------------------------------------------------







// ------------------------------------------------------------------------------------
// Rf.UI.TabPanelElement
// ------------------------------------------------------------------------------------

Rf.UI.TabPanelElement = function(tabElement, contentElement, tabControl)
{
    this.tabControl = tabControl;

    this.tabElement = tabElement;
    this.contentElement = contentElement

    this.index = tabControl.elements.length;

    this.isActive = false;
    this.isEnabled = true;
    this.isVisible = true;

    this.onActivate = function() { };

    Rf.UI.TabPanelElement.initializeBase(this, [tabElement, contentElement, tabControl]);
}

Rf.UI.TabPanelElement.prototype =
{
    initialize: function()
    {
        Rf.UI.TabPanelElement.callBaseMethod(this, "initialize");

        this.contentElement = $byId(this.contentElement);
        this.tabElement = $byId(this.tabElement);

        $addHandler(this.tabElement, "click", this.activate.$delegate(this));
    },

    activate: function(evt)
    {
        if (evt)
            evt.preventDefault();

        if (!this.isEnabled || this.isActive)
            return;

        this.tabControl.setActiveIndex(this.index);
    },

    update: function()
    {
        if (!this.isVisible)
        {
            if (this.contentElement)
                this.contentElement.style["display"] = "none";

            this.tabElement.style["display"] = "none";
        }
        else if (this.isActive)
        {
            if (this.contentElement)
                this.contentElement.style["display"] = "block";

            this.tabElement.className = Rf.UI.TabPanelElement.tabActiveClassName;
        }
        else
        {
            if (this.contentElement)
                this.contentElement.style["display"] = "none";

            this.tabElement.className = this.isEnabled ?
                    Rf.UI.TabPanelElement.tabInactiveClassName : Rf.UI.TabPanelElement.tabDisabledClassName;
        }
    }
}

Rf.UI.TabPanelElement.tabActiveClassName = "tabButton active";
Rf.UI.TabPanelElement.tabInactiveClassName = "tabButton";
Rf.UI.TabPanelElement.tabDisabledClassName = "tabButton disabled";

Rf.UI.TabPanelElement.registerClass("Rf.UI.TabPanelElement", Rf.UI.UIElement);

if (!Rf.__noGlobals)
{
    var TabPanelElement = Rf.UI.TabPanelElement;
    TabPanelElement.registerClass("TabPanelElement", UIElement);
}
// ------------------------------------------------------------------------------------





