﻿if (typeof (_fileVersions) == 'undefined')
    eval('var _fileVersions = new Array()');
_fileVersions.push('ActionGroupHandling 6.6.0.0');

_actionGroupHandler = new ActionGroupHandler();
_actionGroupReceiverHandler = new ActionGroupReceiverHandler();

// Action type enums
var ActionType = new Object();
ActionType.Zero = 'Zero';
ActionType.ZeroOrOne = 'ZeroOrOne';
ActionType.One = 'One';
ActionType.OneOrMore = 'OneOrMore';
ActionType.Many = 'Many';

//=============================================================
// Helper functions
//=============================================================
function InitializeActionGroupHandler()
{
	_actionGroupHandler.Initialize();
}

function RefreshActionGroupItems(rootElement)
{
    var inputElements = rootElement.getElementsByTagName('input');
    var refreshedGroups = new Object();

    for (var index = 0; index < inputElements.length; index++)
    {
        var inputElement = inputElements[index];
        var actionGroupName = GetActionGroupName(inputElement);

        if (actionGroupName)
        {
            if (!refreshedGroups[actionGroupName])
            {
                ClearActionGroup(actionGroupName);
                refreshedGroups[actionGroupName] = true;
            }
        
            AddActionGroupItem(actionGroupName, new ActionGroupItem(inputElement.id));
        }
    }

    InitializeActionGroupHandler();
}

function AddActionGroupItem(actionGroupName, actionGroupItem)
{
    var actionGroup = _actionGroupHandler.ActionGroups[actionGroupName];

    if (actionGroup == null)
    {
        actionGroup = new ActionGroup(actionGroupName);

        _actionGroupHandler.AddActionGroup(actionGroup);
    }

    actionGroup.AddActionGroupItem(actionGroupItem);
}

function GetActionGroupName(element)
{
    return _actionGroupHandler.GetActionGroupName(element);
}

function ClearActionGroup(actionGroupName)
{
    var actionGroup = _actionGroupHandler.ActionGroups[actionGroupName];

    // Ignore the action group if it's missing (actiongroups without items are not created at startup, by design)
    if (actionGroup != null)
    {
        actionGroup.ActionGroupItems = new Array();
        actionGroup.SelectedItemCount = 0;
    }
}

//=============================================================
// ActionGroupHandler
//=============================================================
function ActionGroupHandler()
{
    this.ActionGroups = new Object();
}

ActionGroupHandler.prototype.Initialize = function ()
{
	this.Notify();
}

// Notifies action group receivers about the status of action groups.
// actionGroupName - optional. If omitted, all action group receivers are notified.
ActionGroupHandler.prototype.Notify = function (notifiedActionGroupName)
{
	// Refresh the state of the action groups whos receivers will be notified.
	for (var actionGroupName in this.ActionGroups)
	{
		this.ActionGroups[actionGroupName].RecalculateItems();

		if (notifiedActionGroupName != null && actionGroupName == notifiedActionGroupName)
		{
			break;
		}
	}

	_actionGroupReceiverHandler.NotifyReceivers(notifiedActionGroupName);
}

ActionGroupHandler.prototype.AddActionGroup = function(actionGroup)
{
    this.ActionGroups[actionGroup.ActionGroupName] = actionGroup;
}

ActionGroupHandler.prototype.GetActionGroupName = function(element)
{
	var actionGroupName = null;
	var parentNode = (element != null) ? element.parentNode : null;
	var actionGroupAttribute = parentNode.getAttribute("ActionGroup");

	if (actionGroupAttribute != null && actionGroupAttribute.length > 0)
	{
		actionGroupName = actionGroupAttribute;
	}

	return actionGroupName;
}

ActionGroupHandler.prototype.HandleEvents = function (e)
{
	var evt = window.event || e;
	var srcElement = evt.target || evt.srcElement;

	if (srcElement.tagName.toLowerCase() == 'input' && srcElement.type.toLowerCase() == 'checkbox')
	{
		var actionGroupName = this.GetActionGroupName(srcElement);

		if (actionGroupName != null)
		{
			var actionGroup = this.ActionGroups[actionGroupName];
			var receiverGroupName = "receiver" + actionGroupName;

			if (actionGroup == null)
			{
				throw "Actiongroup missing: " + actionGroupName;
			}

			actionGroup.RecalculateItems();
			_actionGroupReceiverHandler.ChangeState(receiverGroupName, actionGroup);
		}
	}

	return true;
}

ActionGroupHandler.prototype.ResetGroup = function(groupName)
{
    var receiverGroupName = "receiver" + groupName;
    _actionGroupReceiverHandler.ChangeState(receiverGroupName, null);
}

ActionGroupHandler.prototype.GetSelectedItemCount = function(groupName)
{
    var actionGroup = this.ActionGroups[groupName];
    var selectedItemCount = 0;

    if (actionGroup)
    {
        actionGroup.RecalculateItems();
        selectedItemCount = actionGroup.SelectedItemCount;
    }

    return selectedItemCount;
}

ActionGroupHandler.prototype.GetSelectedValues = function(groupName)
{
    var actionGroup = this.ActionGroups[groupName];
    var selectedValues = new Array();

    if (actionGroup)
    {
        selectedValues = actionGroup.GetSelectedValues();
    }

    return selectedValues;
}

ActionGroupHandler.prototype.ForEachSelectedItem = function(groupName, callbackFunction)
{
    var actionGroup = this.ActionGroups[groupName];

    if (actionGroup)
    {
        actionGroup.ForEachSelectedItem(callbackFunction);
    }
}

ActionGroupHandler.prototype.ClearSelected = function(ignoredActionGroup)
{
    for (actionGroupName in _actionGroupHandler.ActionGroups)
    {
        if (actionGroupName != ignoredActionGroup)
        {
            var actionGroup = _actionGroupHandler.ActionGroups[actionGroupName];

            actionGroup.ClearSelected();
        }
    }
}

//=============================================================
// ActionGroup
//=============================================================
function ActionGroup(actionGroupName)
{
    this.ActionGroupName = actionGroupName;
    this.ActionGroupItems = new Array();
    this.SelectedItemCount = 0;
}

ActionGroup.prototype.AddActionGroupArray = function (actionGroupItems)
{
    // the clearing of the array passed is needed because 
    // ScriptManager.RegisterArrayDeclaration arrays are not cleared in update panel postbacks.
    this.ActionGroupItems = actionGroupItems.slice();
    actionGroupItems.splice(0, actionGroupItems.length);
}

ActionGroup.prototype.AddActionGroupItem = function(actionGroupItem)
{
    this.ActionGroupItems.push(actionGroupItem);
}

ActionGroup.prototype.RecalculateItems = function()
{
    var selectedItemCount = 0;

    for (var index = this.ActionGroupItems.length - 1; index >= 0; index--)
    {
        var element = $get(this.ActionGroupItems[index].ControlID);

        if (element != null && element.checked)
        {
            selectedItemCount++;
        }

        // Optimization: no need to count beyond two selected items, since there are no actiontypes for more.
        if (selectedItemCount > 1)
        {
            break;
        }
    }

    this.SelectedItemCount = selectedItemCount;
}

ActionGroup.prototype.ClearSelected = function()
{
    for (var index = this.ActionGroupItems.length - 1; index >= 0; index--)
    {
        var element = $get(this.ActionGroupItems[index].ControlID);

        if (element != null && element.checked)
        {
            element.click();
        }
    }
}

ActionGroup.prototype.GetSelectedValues = function ()
{
    var selectedValues = new Array();

    for (var index = this.ActionGroupItems.length - 1; index >= 0; index--)
    {
        var element = $get(this.ActionGroupItems[index].ControlID);

        if (element != null && element.checked)
        {
            var parent = element.parentNode;
            
            if (parent != null && parent.getAttribute('boxValue'))
            {
                selectedValues.push(parent.getAttribute('boxValue'));
            }
            else
            {
                selectedValues.push(element.value);
            }
        }
    }

    return selectedValues;
}

ActionGroup.prototype.ForEachSelectedItem = function(callbackFunction)
{
    var continueWithNext = true;

    for (var index = this.ActionGroupItems.length - 1; index >= 0; index--)
    {
        var element = $get(this.ActionGroupItems[index].ControlID);

        if (element != null && element.checked)
        {
            var parent = element.parentNode;

            if (parent != null && parent.getAttribute('boxValue'))
            {
                continueWithNext = callbackFunction(parent);
            }
            else
            {
                continueWithNext = callbackFunction(element);
            }
        }

        if (!continueWithNext)
        {
            break;
        }
    }
}

//=============================================================
// ActionGroupItem
//=============================================================
function ActionGroupItem(controlID)
{
    this.ControlID = controlID;
}

//=============================================================
// ActionGroupReceiverHandler
//=============================================================
function ActionGroupReceiverHandler()
{
    this.ActionGroupReceiverGroups = new Object();
    this.CustomActionGroupReceivers = new Object();
}

ActionGroupReceiverHandler.prototype.AddCustomReceiverFunction = function(actionGroupName, func)
{
    var receiverGroupName = "receiver" + actionGroupName;

    if (this.CustomActionGroupReceivers[receiverGroupName] == null)
    {
        actionGroupReceiver = new Array();
        this.CustomActionGroupReceivers[receiverGroupName] = actionGroupReceiver;
    }

    this.CustomActionGroupReceivers[receiverGroupName].push(func);
}

ActionGroupReceiverHandler.prototype.AddReceivers = function (actionGroupName, actionGroupReceiverGroup)
{
	this.ActionGroupReceiverGroups[actionGroupName] = actionGroupReceiverGroup;
}

// Notify the receivers of the state of an action group. 
// If the action group is omitted, all receivers of all action groups are notified.
ActionGroupReceiverHandler.prototype.NotifyReceivers = function (actionGroupName)
{
	var notifiedReceiverGroupName = (actionGroupName != null) ? "receiver" + actionGroupName : null;

	for (var receiverGroupName in _actionGroupReceiverHandler.ActionGroupReceiverGroups)
	{
		var receiverGroup = _actionGroupReceiverHandler.ActionGroupReceiverGroups[receiverGroupName];
		var actionGroup = _actionGroupHandler.ActionGroups[receiverGroup.ActionGroupName];

		if (notifiedReceiverGroupName == null)
		{
			_actionGroupReceiverHandler.ChangeState(receiverGroupName, actionGroup);
		}
		else if (receiverGroupName == notifiedReceiverGroupName)
		{
			_actionGroupReceiverHandler.ChangeState(receiverGroupName, actionGroup);
			break;
		}
	}
}

ActionGroupReceiverHandler.prototype.ChangeState = function (receiverGroupName, actionGroup)
{
	var thisObj = this;

	function DelayedChangeState(receiverGroupName, actionGroup)
	{
		var actionGroupReceiverGroup = thisObj.ActionGroupReceiverGroups[receiverGroupName];
		var selectedItemCount = 0;
		var selectedActionGroupName = null;

		if (actionGroup != null)
		{
			selectedItemCount = actionGroup.SelectedItemCount;
			selectedActionGroupName = actionGroup.ActionGroupName;
		}

		if (actionGroupReceiverGroup != null)
		{
			var length = actionGroupReceiverGroup.ActionGroupReceiverItems.length;

			for (var index = 0; index < length; index++)
			{
				actionGroupReceiverGroup.ActionGroupReceiverItems[index].ChangeEnabled(selectedItemCount);
			}
		}

		var customActionGroupReceiver = thisObj.CustomActionGroupReceivers[receiverGroupName];

		if (customActionGroupReceiver != null && selectedActionGroupName != null)
		{
			for (var index = 0; index < customActionGroupReceiver.length; index++)
			{
				var func = customActionGroupReceiver[index];

				func(selectedActionGroupName, selectedItemCount);
			}
		}
	}

	// Every action group item will trigger a change state. Instead of calling each action group receiver for every
	// state change, wait till all state changes have been executed and then call the receivers with the latest state.
	if (!this.DelayedChangeStateHandlers)
	{
		this.DelayedChangeStateHandlers = new Object();
	}

	var handlerName = receiverGroupName + "-" + (actionGroup != null ? actionGroup.ActionGroupName : "");

	if (!this.DelayedChangeStateHandlers[handlerName])
	{
		this.DelayedChangeStateHandlers[handlerName] = true;

		setTimeout(function ()
		{
			DelayedChangeState(receiverGroupName, actionGroup);
			thisObj.DelayedChangeStateHandlers[handlerName] = false;
		}, 0);
	}
}

//=============================================================
// ActionGroupReceiverGroup
//=============================================================
function ActionGroupReceiverGroup(actionGroupName)
{
    this.ActionGroupName = actionGroupName;
    this.ActionGroupReceiverItems;
}

ActionGroupReceiverGroup.prototype.AddActionGroupReceiverGroupItems = function (actionGroupReceiverGroupArray)
{
    // the clearing of the array passed is needed because 
    // ScriptManager.RegisterArrayDeclaration arrays are not cleared in update panel postbacks.
    this.ActionGroupReceiverItems = actionGroupReceiverGroupArray.slice();
    actionGroupReceiverGroupArray.splice(0, actionGroupReceiverGroupArray.length);
}

//=============================================================
// ActionGroupReceiverItem
//=============================================================
function ActionGroupReceiverItem(actionGroupName, controlId, actionType, itemToggleCallbackFunction)
{
    this.ControlId = controlId;
    this.ActionGroupName = actionGroupName;
    this.Action = actionType;
    this.ItemToggleCallbackFunction = itemToggleCallbackFunction;
}

ActionGroupReceiverItem.prototype.ChangeEnabled = function (selectedItemCount)
{
	var disabled = true;

	if (selectedItemCount == 0 &&
		(this.Action == ActionType.Zero ||
		 this.Action == ActionType.ZeroOrOne))
	{
		disabled = false;
	}
	else if (selectedItemCount == 1 &&
			 (this.Action == ActionType.ZeroOrOne ||
			  this.Action == ActionType.One ||
			  this.Action == ActionType.OneOrMore))
	{
		disabled = false;
	}
	else if (selectedItemCount > 1 &&
			(this.Action == ActionType.OneOrMore ||
			 this.Action == ActionType.Many))
	{
		disabled = false;
	}

	if (this.ItemToggleCallbackFunction != null)
	{
		this.ItemToggleCallbackFunction(this.ControlId, disabled);
	}
	else
	{
		var control = $get(this.ControlId);

		if (control)
		{
			control.disabled = disabled;
		}
	}
}

//=============================================================
// Action group event initialization
//=============================================================

if (typeof (Sys) != 'undefined')
{
    var handleEventsDelegate = function (e) { _actionGroupHandler.HandleEvents(e); }
    $addHandler(document, 'click', handleEventsDelegate);
    Sys.Application.add_load(InitializeActionGroupHandler);
    
    // Notify the ScriptManager that this script file has finished loading.
    Sys.Application.notifyScriptLoaded();
}
