
isc.defineClass("OPINIATOR_CategoryCache", isc.Class);
OPINIATOR_CategoryCache.addClassProperties({
    _cache: {},

    clear: function ()
        { OPINIATOR_CategoryCache._cache = new Object(); }
    });

OPINIATOR_CategoryCache.addProperties({
    // Absract methods
    categoryLoaded: function ( category ) {},
    showBusy: function ( busy ) {},

    init: function ()
        { this.Super("init", arguments); },

    /**
     * Loads a category
     */
    loadCategory: function ( category )
        {
        if ( isc.isA.Number(category) )
            {
            // See if we have the category in cache if not loaded it
            var catid = category;
            category = OPINIATOR_CategoryCache._cache[catid];
            if ( !isc.isAn.Object(category) )
                {
                this._loadingid = catid;
                this.showBusy(true, OPINIATOR.BUSY_DELAY);
                WebClientSvc.getCategory(catid, this.callback("_catloaded"), this.callback("error"));
                return;
                }
            }

        this.showBusy(false);

        //  Keep the category around
        OPINIATOR_CategoryCache._cache[category.id] = category; 
        this._category = category; 
        this.categoryLoaded(category);
        },

    _catloaded: function ( category )
        {
        // Handles multiple quick selects by the user causing categories to be
        // loaded while other categorie requests are pending
        if ( category.id == this._loadingid )
            {
            category.questions = OPINIATOR.toArray(category.questions); 
            // Call load again this time with a real object
            this.loadCategory(category);
            }
        },

    callback: function (methodName)
        { return {target:this, methodName:methodName}; }
    });

/**
 * @class MobileTextEditor 
 *  
 * UI Element to edit a Mobile Text Item.  The Text item may be 
 * either an SMS text item or a Mobi Text item. The item will be 
 * modified in place. The modified text will modify either the 
 * question or the override if an override was not null. 
 */
isc.defineClass("OPINIATOR_MobileTextEditor", isc.DynamicForm);
OPINIATOR_MobileTextEditor.addProperties({

    // Constructor Properties
    /**
     * The parentEditor for enabling the save button
     */
    parentEditor:null,

    /**
     * The question to which the textProperty will be applied
     */
    question: null,

    /**
     *  Property within the question or the override that holds the
     *  text value. Currently either "mobiText" or "smsText"
     */
    textProperty: null,

    /**
     * If specified then the override checkbox will be enabled and 
     * values will be placed into this override object as opposed to 
     * modifying the question object. 
     */
    override: null,

    /**
     *  Maximum length the text can be
     */
    maxTextLength: null,

    /**
     *  Title of the Editor 
     */
    title: null,

    // Superclass Properties
    minColWidth:10,
    cellPadding:2,
    numCols:2,
    fixedColWidths:false,
    cellBorder:0,
    showResizeBar:false,
    layoutAlign:"left",
    items:[
        {
        name:"header",
        type:"header",
        defaultValue:"",
        align:"center",
        colSpan:2
        },
        {
        name:"override",
        type:"checkbox",
        title:"Override Text",
        hieght:25,
        showTitle:false,
        startRow:true,
        endRow:false,
        tabIndex:1,
        align:"left"
        },
        {
        name:"text",
        type:"textArea",
        textBoxStyle:"mtextItem",
        tabIndex:2,
        showTitle:false,
        startRow:true,
        width:"*",
        rowSpan:2,
        colSpan:2,
        align:"left",
        width:"*",
        _constructor:"OPINIATOR_TextAreaItem"
        },
        {
        name:"spacer",
        type:"textArea",
        startRow:true,
        endRow:false,
        _constructor:"SpacerItem"
        },
        {
        name:"tlen",
        type:"text",
        startRow:false,
        endRow:true,
        showTitle:false,
        defaultValue:"0/0",
        textBoxStyle:"mobilenTextItem",
        align:"left",
        hieght:25,
        textAlign:"right",
        _constructor:"StaticTextItem"
        }
        ],

    initWidget: function ()
        {
        this.Super("initWidget", arguments);

        var overrideItem = this.getItem("override");
        var headerItem = this.getItem("header");
        var text_item = this.getItem("text");
        var tlen_item = this.getItem("tlen");

        headerItem.setValue(this.title);

        if ( this.override === null  )
            {
            overrideItem.hide();
            this._setText(this.question[this.textProperty]);
            }
        else
            {
            overrideItem.show();
            if ( isc.isA.String(this.override[this.textProperty]) )
                {
                overrideItem.setValue(true);
                text_item.enable();
                tlen_item.show();
                this._setText(this.override[this.textProperty]);
                }
            else
                {
                overrideItem.setValue(false);
                text_item.disable();
                tlen_item.hide();
                this._setText(this.question[this.textProperty]);
                }
            }

        },

    destroy: function ()
        {
        this.parentEditor = null;
        this.question = null;
        this.override = null;
        this.textProperty = null;
        this.title = null;
        this.Super("destroy", arguments);
        },

    _setText: function ( text )
        {
        var text_item = this.getItem("text");
        var tlen_item = this.getItem("tlen");

        if ( isc.isA.String(text) )
            {
            text_item.setValue(text);
            if ( new Number(text.length) > new Number(this.maxTextLength) )
                { tlen_item.textBoxStyle = "mobilenTextItemMaxed"; }
            else
                { tlen_item.textBoxStyle = "mobilenTextItem"; }
            tlen_item.updateState();
            tlen_item.setValue("" + text.length + "/" + this.maxTextLength);
            }
        else
            {
            text_item.setValue("");
            tlen_item.setValue("0/"+ this.maxTextLength);
            tlen_item.textBoxStyle = "mobilenTextItem";
            tlen_item.updateState();
            }
        },

    setText: function ( newtext )
        {
        var text_item = this.getItem("text");
        this.itemChange(text_item, newtext, text_item.getValue());
        },

    getText: function ( text )
        { return this.getItem("text").getValue(); },

    _overrideChanged : function(overriding, defaultText)
        {
        var text_item = this.getItem("text");
        var tlen_item = this.getItem("tlen");

        if ( overriding )
            {
            text_item.enable();
            tlen_item.show();
            text_item.form.focusInItem(text_item);
            }
        else
            {
            text_item.disable();
            tlen_item.hide();
            text_item.setValue(defaultText);
            delete this.override[this.textProperty];
            text_item.form.focusInItem(text_item.form.getItem("override"));
            }
        },

    itemChange: function (item, newValue, oldValue)
        {
        var override;
        var iname = item.getFieldName();
        switch ( iname )
            {
            case "override":
                this._overrideChanged(newValue, this.question[this.textProperty]);
                this.parentEditor.enableSave();
                break;

            case "text":
                var test = newValue.length > (this.maxTextLength - 0);

                if ( this.override !== null )
                    { this.override[this.textProperty] = newValue; }
                else
                    { this.question[this.textProperty] = newValue; }

                this._setText(newValue);
                this.parentEditor.enableSave();
                break;

            default:
                break;
            }
        return true;
        }

    });


/**
 * @class QuestionEditor 
 *  
 * UI Element to Edit both a MobiText Item and SMS TextItem. The 
 * text will be modified in either the question or an override 
 * if an overrides array was specified
 */
isc.defineClass("OPINIATOR_QuestionEditor", isc.DynamicForm);
OPINIATOR_QuestionEditor.addProperties({

    // Constructor Properties
    parentEditor: null,

    // Busy Indicator
    showBusy: OPINIATOR_ShowBusy,
    destroyBusy: OPINIATOR_DestroyBusy,

    // Private Properties
    _overrides: null,
    _cache: null,

    // Superclass Properties
    numCols:2,
    colWidths: ["50%", "50%"],
    styleName:"defaultCanvas",
    minColWidth:10,
    cellPadding:2,
    cellBorder:0,
    layoutAlign:"left",
    sectionVisibilityMode: "mutex",


    initWidget: function ()
        { this.Super("initWidget", arguments); },

    destroy: function ()
        {
        // Delete a cache if it exists
        if ( isc.isA.Object(this._cache) )
            {
            delete this._cache.target;
            delete this._cache;
            }

        delete this.parentEditor;
        delete this._overrides;
        this.destroyBusy();
        this.Super("destroy", arguments);
        },

    edit: function ( category, overrides )
        {
        // Only use overrides if editing with overrides
        this._overrides = isc.isAn.Array(overrides) ? overrides : null;

        //  If the category passed is actually its id then load it from a cache
        //  The cache may load it from the server
        if ( isc.isA.Number(category) )
            {
            var catid = category;
            this._getCache().loadCategory(catid);
            return;
            }

        this._edit(category);
        },

    _getCache: function ()
        {
        if ( !isc.isA.Object(this._cache) )
            {
            this._cache = OPINIATOR_CategoryCache.create({
                target:this,

                categoryLoaded: function( category )
                    { this.target._edit(category); },

                error: function( code, msg )
                    { this.target.error(code, msg); },

                showBusy: function( busy )
                    {
                    if ( busy )
                        {
                        this.target.disable();
                        this.target.showBusy(true, OPINIATOR.BUSY_DELAY);
                        }
                    else
                        {
                        this.target.enable();
                        this.target.showBusy(false);
                        }
                    }
                });
            }
        return this._cache;
        },

    /**
     *  Create the form once the category is loaded
     */
    _edit: function ( category )
        {
        var questions = category.questions;

        var items = [];
        items.add({type:"rowSpacer", height:18});
        var tabIndex = 1;
        var pcount = this._promptCount(questions);
        var len = questions.getLength();
		
        if (category.type === "WELCOME" )
            { len = 0; }
		
        // Expand the first section but none of the others
        var expandsect = true;

        for ( var i = 0; i < len; i++ )
            {
            var q = questions[i];
            var override = this._getOverride(q, category);

            //  Create a section for each question in the category.  If there's only one question then
            //  don't use sections.
            var sectionItem = null;

            sectionItem = {
                type:"section",
                showTitle:false,
                defaultValue: (pcount > 1) ? q.title : "Message Text",
                sectionExpanded:expandsect,
                canCollapse: true,
                itemIds:[],
                tabIndex:tabIndex
                };
            items.add(sectionItem);
            tabIndex++;

            // Expand the first section but none of the others
            expandsect = false;
            var editor;
            if ( category.type !== "WELCOME" )
                {
                editor = {
                    name:q.title + "-mobi",
                    startRow:true,
                    endRow:false,
                    showTitle:false,
                    type:"canvas",
                    canvas: OPINIATOR_MobileTextEditor.create({
                            parentEditor:this.parentEditor,
                            title:"Mobi Text", 
                            textProperty:"mobiText", 
                            question:q, 
                            override:override, 
                            maxTextLength:512}),
                    tabIndex:tabIndex
                    };
                tabIndex++;
                items.add(editor);
                if ( sectionItem !== null  )
                    { sectionItem.itemIds.add(editor.name); }
                }			
				
            var smseditor = OPINIATOR_MobileTextEditor.create ({
                    parentEditor:this.parentEditor,
                    title:"SMS Text", 
                    textProperty:"smsText", 
                    question:q, 
                    override:override, 
                    maxTextLength:q.maxSMSLength
                    });

            editor = {
                name:q.title + "-sms",
                startRow:false,
                endRow:true,
                showTitle:false,
                type:"canvas",
                canvas: smseditor,
                tabIndex:tabIndex
                };
            tabIndex++;
            items.add(editor);
			
			var voiceeditor = OPINIATOR_MobileTextEditor.create ({
                    parentEditor:this.parentEditor,
                    title:"Voice Text", 
                    textProperty:"voiceText", 
                    question:q, 
                    override:override, 
                    maxTextLength:512
                    });

            editor = {
                name:q.title + "-voice",
                startRow:false,
                endRow:true,
                showTitle:false,
                type:"canvas",
                canvas: voiceeditor,
                tabIndex:tabIndex
                };
            tabIndex++;
            items.add(editor);
			
            if ( sectionItem !== null  )
                { sectionItem.itemIds.add(editor.name); }

            if ( (override === null) )
                {
                switch ( q.responseType ) 
                    {
                    case "NUMERICRANGE":
                        {
                        editor = {
                            name:q.title + "-values",
                            startRow:true,
                            endRow:true,
                            showTitle:false,
                            colSpan:2,
                            height:130,
                            type:"canvas",
                            canvas: OPINIATOR_NumericResponseEditor.create({
                                parentEditor:this.parentEditor,
                                question:q,
                                disableRange:category.type == "NETPROMOTER"
                                }),
                            tabIndex:tabIndex
                            };
                        tabIndex++;
                        items.add(editor);
                        if ( sectionItem !== null  )
                            { sectionItem.itemIds.add(editor.name); }
                        }
                        break;

                    case "CHOICE":
                        {
                        editor = {
                            name:q.title + "-values",
                            startRow:true,
                            endRow:true,
                            showTitle:false,
                            colSpan:2,
                            height:130,
                            type:"canvas",
                            canvas: OPINIATOR_ChoiceResponseEditor.create({
                                parentEditor:this.parentEditor,
                                smsEditor:smseditor,
                                question:q,
                                updateSMSText: function ( newtext )
                                    {
                                    var text = this.smsEditor.getText();
                                    text.trim();
                                    this.smsEditor.setText(text.replace(/\(.*\)$/, newtext));
                                    }
                                }),
                            tabIndex:tabIndex
                            };
                        tabIndex++;
                        items.add(editor);
                        if ( sectionItem !== null  )
                            { sectionItem.itemIds.add(editor.name); }
                        }
                        break;

                    default:
                        break;
                    }
                }
            }
		if (!isCategoryTab && (category.type == "PERFORMANCE" || category.type == "NUMERIC" || category.type == "NETPROMOTER")) {
			sectionItem = {
				type: "section",
				showTitle: false,
				defaultValue: "Alert",
				sectionExpanded: false,
				canCollapse: true,
				itemIds: [],
				tabIndex: tabIndex
			};
			
			editor = {
				name: "alert",
				type: "canvas",
				startRow: true,
				endRow: false,
				showTitle: false,
				canvas: OPINIATOR_AlertResponseEditor.create({
					parentEditor: this.parentEditor,
					_category: category,
					_survey: selectedSurvey,
					_alerts: null
				})
			};
			items.add(sectionItem);
			items.add(editor);
			if (sectionItem != null) {
				sectionItem.itemIds.add(editor.name);
			}
		}
        this.setItems(items);
        },

    verifyQuestions: function ( category ) 
        {
        var questions = category.questions;

        for ( var i = 0; i < questions.getLength(); i++ )
            {
            var q = questions[i];

            switch ( q.responseType )
                {
                case "CHOICE":
                    {
                    if ( q.valueTextMap.getLength() < 2 )
                        {
                        OPINIATOR.warn("Multiple Choice Questions must have at least two choices.");
                        return false;
                        }
                    }
                    break;

                default:
                    break;
                }

            if ( category.type !== "WELCOME" )
                {
                // Verify the length of the SMS Message and the Mobi Message
                if ( q.smsText.length > q.maxSMSLength )
                    {
                    OPINIATOR.warn("SMS Text is too long.");
                    return false;
                    }
                }

            if ( q.mobiText.length > 512 )
                {
                OPINIATOR.warn("Mobi Text is too long.");
                return false;
                }
            }

        return true;
        },


    _promptCount: function ( questions )
        {
        var count = new Number(0);
        for ( var i = 0; i < questions.getLength(); i++ )
            {
            if ( questions[i].responseType != "IGNORE"  )
                { count++; }
            }
        return count;
        },

    /**
     *  Gets the override for a question is the question exists 
     */
    _getOverride: function ( question, category )
        {
        var override = null;
        if ( isc.isAn.Array(this._overrides) )
            {
            var i = this._overrides.findIndex("qid", question.id);
            if ( i < 0 )
                { 
                override = {qid: question.id, catid: category.id}; 
                this._overrides.add(override); 
                }
            else
                { override = this._overrides[i]; }
            }
        return override;
        },


    error: function (code, msg)
        {
        this.showBusy(false);
        switch ( msg )
            {
            case "DeletedState":
                OPINIATOR.warn("This category has been deleted by another user.");
                break;

            default:
                OPINIATOR.warn(msg);
                break;
            }
        },

    callback: function (methodName)
        { return {target:this, methodName:methodName}; }

    });

isc.defineClass("OPINIATOR_CategoryGeneralForm", isc.DynamicForm);
OPINIATOR_CategoryGeneralForm.addProperties({
    // Constructor Properties 
    parentEditor: null,

    // Superclass Properties
    showBusy:OPINIATOR_ShowBusy,
    destroyBusy:OPINIATOR_DestroyBusy,

    // Superclass Properties
    width:"100%",
    height:"100%",
    minColWidth:10,
    cellPadding:2,
    numCols:2,
    fixedColWidths:false,
    titleWidths:80,
    cellBorder:0,
    showResizeBar:false,
    layoutAlign:"left",
    itemHoverDelay:3000,
    selectOnFocus:true,
    items:[
        {type:"rowSpacer", height:18},
        //  Category Name
        {
        name:"name",
        type:"text",
        tabIndex:1,
        title:"Category",
        titleAlign:"left",
        align:"left",
        wrapTitle:false,
        width:250,
        height:25,
        _constructor:"OPINIATOR_TextItem"
        },
        //  Category Type
        {
        name:"type",
        title:"Type",
        titleAlign:"left",
        align:"left",
        tabIndex:2,
        startRow:true,
        wrapTitle:false,
        type:"enum",
        valueMap: { 
            "PERFORMANCE": "Performance", 
            "NUMERIC": "Numeric",
            "CHOICE": "Multiple Choice", 
            "TEXT": "Text"			
            }, 
        width:130,
        height:25
        }
        ],


    initWidget: function ()
        { this.Super("initWidget", arguments); },

    destroy: function ()
        {
        delete this._category;
        delete this._parentEditor;
        this.destroyBusy();
        this.Super("destroy", arguments);
        },

    edit: function ( category )
        {
        this._category = category;
        this.setValue("name", category.title);
        if ( !isc.isA.Number(category.id) )
            {
            switch ( category.type )
                {
                case "PERFORMANCE":
                case "TEXT":
                case "NUMERIC":
                case "CHOICE":				
                case "BOOLEAN":
                    this._showType(category.type, false);
                    break;
                default:
                    this._showType(category.type, true);
                    break;
                }
            }
        else
            { this._showType(category.type, true); }
        },

    _showType: function (type, isStatic)
        {
        var type_item = this.getItem("type");

        if ( isStatic )
            {
            var text = "unknown";
            switch ( type )
                {
                case "PERFORMANCE":
                    text = "Performance";
                    break;
                case "NUMERIC":
                    text = "Numeric";
                    break;
                case "TEXT":
                    text = "Text";
                    break;
                case "BOOLEAN":
                    text = "Boolean";
                    break;
                case "CHOICE":
                    text = "Choice";
                    break;
                case "WELCOME":
                    text = "Welcome";
                    break;
                case "THANKYOU":
                    text = "Thank You";
                    break;
                case "NETPROMOTER":
                    text = "Net Promoter";
                    break;
                case "ZIPCODE":
                    text = "Zipcode";
                    break;

                default:
                    break;
                }
            type_item.disable();
            type_item.setValue(text);
            }
        else
            {
            type_item.enable();
            type_item.setValue(type);
            }
        },

    itemChange: function (item, newValue, oldValue)
        {
        if ( oldValue != newValue  )
            {
            this.parentEditor.enableSave();
            switch ( item.getFieldName() )
                {
                case "name":
                    this._category.title = newValue;
                    break;

                case "type":
                    this.parentEditor.delayCall("changeNewCategory", [this._category.title, newValue]);
                    break;

                default:
                    break;
                }
            }
        }
    });

// ----------------
isc.defineClass("OPINIATOR_CategoryEditor", OPINIATOR_BusyVLayout);
OPINIATOR_CategoryEditor.addProperties({

    // Constructor Properties

    /**
     * The selector that contains the key node to this category for 
     * refresh purposes 
     */
    selector: null,
    
    /**
     * Toolstrip to add save and cancel buttons
     */
    toolstrip: null,

    // Private Properties

    // The save button in the toolstrip
    _saveButton: null,

    // The cancel button in the toolstrip
    _cancelButton: null,

    // The Category we are editing
    _category: null,

    initWidget: function ()
        {
        this._saveButton = OPINIATOR_Button.create({
            title:"Save",
            visibility: "hidden",
            target:this,
            layoutAlign:"center",
            icon: "icons/16/save.png",
            click: function ()
                { this.target.save(); return true;}
            });

        this._cancelButton = OPINIATOR_Button.create({
            title:"Cancel",
            layoutAlign:"center",
            visibility: "hidden",
            icon: "icons/16/cancel.png",
            target:this,
            click: function ()
                { this.target.cancel(true); return true;}
            });
            
        this.toolstrip.addMember(this._cancelButton);
        this.toolstrip.addMember(this._saveButton);
        delete this.toolstrip;

        this._generalEditor = OPINIATOR_CategoryGeneralForm.create({height:60, parentEditor:this});
        this._generalEditor.hide();

        this.members = [this._generalEditor];

        this.Super("initWidget", arguments);
        },

    destroy: function ()
        {
        delete this.selector;
        delete this._saveButton;
        delete this._cancelButton;
        delete this._generalEdtior;
        this.Super("destroy", arguments);
        },

    enableSave: function ()
        {
        this._saveButton.show();
        this._cancelButton.show();
        },

    disableSave: function ()
        {
        this._saveButton.hide();
        this._cancelButton.hide();
        },

    _cleanupCategory: function ( category )
        {
        },

    _verifyCategory: function ( category )
        {
        if ( isc.isA.Object(this._questionEditor) )
            { return this._questionEditor.verifyQuestions(category); }
        return true;
        },

    cancel: function ( reedit )
        {
        this.disableSave();
        if ( reedit )
            { 
            if ( isc.isA.Number(this._category.id) )
                { this.edit(this._category.id); }
            else
                { this.clearEditor(); }
            }
        },

    save: function ( callback )
        {
        if ( isc.isAn.Object(callback) )
            { this._callbackOnSave = callback; }
        else
            { delete this._callbackOnSave; }

        this._cleanupCategory(this._category);

        if ( this._verifyCategory(this._category) )
            {
            this.showBusy(true, OPINIATOR.BUSY_DELAY);
            WebClientSvc.saveCategory(this._category, this.callback("_saveDone"), this.callback("error"));
            }
        },

        
    _saveDone: function ( category )
        {
        this.showBusy(false);
        this.selector.refreshCategory(category);
        if ( isc.isAn.Object(this._callbackOnSave) )
            { Class.fireCallback(this._callbackOnSave); }
        else
            { 
            this._category = category;
            this.disableSave();
            this._updateEditors(category); 
            }
        },

    /**
     * Edits the given category.  If the category is passed in as a 
     * number its assumed to be the category id and the record will 
     * be retrieved from the surver. 
     * 
     * @author ktyra (3/27/2009)
     */
    edit: function ( category )
        {
        if ( isc.isA.Number(category) )
            {
            this.showBusy(true, OPINIATOR.BUSY_DELAY);
            var catid = category;
            WebClientSvc.getCategory(catid, this.callback("edit"), this.callback("error"));
            }
        else
            {
            // Update the category row from a potential reload.  Note that this might be a new
            // category and in that case we don't add it to the list until its saved.  We know its
            // new or not from the category.id
            this._category = category;
            if ( isc.isA.Number(category.id) )
                {
                this.selector.refreshCategory(category);
                this.disableSave();
                }
            else
                { this.enableSave(); }
            // Ensure that the all the category's lists are indeed lists
            this._updateEditors(category);
            this.showBusy(false);
            }
        },

    clearEditor : function ()
        {
        this._generalEditor.hide();
        if ( isc.isA.Object(this._questionEditor) )
            {
            this.removeMember(this._questionEditor);
            this._questionEditor.destroy();
            }
        },

    _updateEditors : function (category)
        {
        category.questions = OPINIATOR.toArray(category.questions);
        this._generalEditor.show();
        this._generalEditor.edit(category);

        if ( isc.isA.Object(this._questionEditor) )
            {
            this.removeMember(this._questionEditor);
            this._questionEditor.destroy();
            }

        // Build a new question editor
        this._questionEditor = OPINIATOR_QuestionEditor.create({height:"*", parentEditor:this});
        this.addMember(this._questionEditor);
        this._questionEditor.edit(category);
        },

    wasModified: function ()
        { return this._saveButton.isVisible(); },

    changeNewCategory: function ( title, type )
        { 
        this.showBusy(true, OPINIATOR.BUSY_DELAY);
        WebClientSvc.newCategory(title, type, this.callback("_changeNewCategory"), this.callback("error") ); 
        },

    _changeNewCategory: function ( category )
        { 
        this.showBusy(false);
        this.edit(category);
        },

    error: function (code, msg)
        {
        this.showBusy(false);
        switch ( msg )
            {
            case "StaleState":
                OPINIATOR.warn("Changes were made to the category by another user while you were editing.\nYour changes were lost! Please re-edit the category.");
                break;

            case "DeletedState":
                OPINIATOR.warn("This category has been deleted by another user.");
                this.selector.refresh();
                this.hide();
                break;

            default:
                OPINIATOR.warn(msg);
                break;
            }
        },

    callback: function (methodName)
        { return {target:this, methodName:methodName}; }

    });

