
    // ChangeEvent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ChangeEvent = Class.create();
    ChangeEvent.prototype =
    {
        iType : -1,
        oTarget : null,

        initialize : function(p_oEvent, p_iType)
        {
            this.oTarget = p_oEvent.getTarget();
            this.iType = p_iType;
        },

        getType : function()
        {
            return this.iType;
        },

        getTarget : function()
        {
            return this.oTarget;
        },

        toString : function()
        {
            return "ChangeEvent[type=\"" + this.iType + "\"]";
        }
    };

    ChangeEvent.Type = new Object();
    ChangeEvent.Type.CHANGED = 0;



    // CheckBoxGroup ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    CheckBoxGroup = Class.create();
    CheckBoxGroup.prototype =
    {
        oPattern : null,
        oGlobalCheckBox : null,
        aCheckBoxes : null,
        aListeners : null,

        initialize : function(p_oPattern)
        {
            this.oPattern = p_oPattern || /^checkBox\[([0-9]+)\]$/;
            this.oGlobalCheckBox = null;
            this.aCheckBoxes = null;
            this.aListeners = [];

            Mouse.addListener(
            {
                onMouseClicked : function(p_oEvent)
                {
                    oCheckBox = p_oEvent.getTarget();
                    if(oCheckBox.id.match(this.oPattern))
                    {
                        var iIndex;
                        iId = parseInt(RegExp.$1);

                        // Was the box is checked?
                        if(oCheckBox.checked)
                        {
//document.body.appendChild(document.createTextNode("+[" + iId + "]"));
                            // Is the box the global one?
                            if(oCheckBox == this.getGlobalCheckBox())
                            {
                                for(iIndex = 0; iIndex < this.getCheckBoxes().length; ++iIndex)
                                {
                                    oCheckBox = this.getCheckBoxes()[iIndex];
                                    oCheckBox.checked = true;
                                }
                            }
                            else
                            {
                                var bAllChecked = true;
                                iIndex = 0;
                                while(bAllChecked && iIndex < this.getCheckBoxes().length)
                                {
                                    bAllChecked &= this.getCheckBoxes()[iIndex].checked;
                                    ++iIndex;
                                }

                                if(bAllChecked)
                                {
                                    this.getGlobalCheckBox().checked = true;
                                }
                            }
                        }
                        else
                        {
//document.body.appendChild(document.createTextNode("-[" + iId + "]"));
                            if(oCheckBox == this.getGlobalCheckBox())
                            {
                                for(iIndex = 0; iIndex < this.getCheckBoxes().length; ++iIndex)
                                {
                                    oCheckBox = this.getCheckBoxes()[iIndex];
                                    oCheckBox.checked = false;
                                }
                            }
                            else
                            {
                                this.getGlobalCheckBox().checked = false;
                            }
                        }

                        this.dispatch(new ChangeEvent(p_oEvent, ChangeEvent.Type.CHANGED));
                    }
                }.bind(this)
            });
        },

        getSelection : function()
        {
            var r_aSelection = [];

            var iIndex;
            for(iIndex = 0; iIndex < this.getCheckBoxes().length; ++iIndex)
            {
                oCheckBox = this.getCheckBoxes()[iIndex];
                if(oCheckBox.checked && oCheckBox != this.getGlobalCheckBox())
                {
                    r_aSelection.push(oCheckBox);
                }
            }

            return r_aSelection;
        },

        getPattern : function()
        {
            return this.oPattern;
        },

        getCheckBoxes : function(p_bBrowse)
        {
            if(!this.aCheckBoxes || p_bBrowse)
            {
                this.browse();
            }

            return this.aCheckBoxes;
        },

        getGlobalCheckBox : function(p_bBrowse)
        {
            if(!this.oGlobalCheckBox || p_bBrowse)
            {
                this.browse();
            }

            return this.oGlobalCheckBox;
        },

        browse : function()
        {
            this.aCheckBoxes = [];

            var aFields = document.getElementsByTagName("input");
            var iIndex;
            for(iIndex = 0; iIndex < aFields.length; ++iIndex)
            {
                oField = aFields[iIndex];
                if(oField.type == "checkbox" && oField.id && oField.id.match(this.oPattern))
                {
                    if(RegExp.$1 == 0)
                    {
                        this.oGlobalCheckBox = oField;
                    }
                    else
                    {
                        this.aCheckBoxes.push(oField);
                    }
                }
            }
        },

        addListener : function(p_oListener)
        {
            this.aListeners.push(p_oListener);
        },

        dispatch : function(p_oEvent)
        {
            var iIndex;
            switch(p_oEvent.getType())
            {
                case ChangeEvent.Type.CHANGED:
                {
                    for(iIndex = 0; iIndex < this.aListeners.length; ++iIndex)
                    {
                        if(this.aListeners[iIndex]["onChanged"])
                        {
                            this.aListeners[iIndex].onChanged(p_oEvent);
                        }
                    }
                    break;
                }
            }
        }
    };

