3.2.0

Any workaround for the removed setEditorTemplate() without having to use the default AW.Templates.ImageText functionality?

Hi Alex, Greetings,

I always loved the setEditorTemplate() method and I understood from the following posts that it is considered redundant and not supported anymore in the current and future versions:

Post by Alex (ActiveWidgets)[Please comment] Cell editing, changing API (2.0):
/javascript.forum.9201.21/please-comment-cell-editing-changing.html

Post by Rob Francis, Beta4 breaks my setEditorTemplate code - Please help:
/javascript.forum.10775.1/beta4-breaks-my-seteditortemplate-code.html


I was wondering how the functionality can be duplicated without the original setEditoTremplate method in place.

Is there any workaround for the removed setEditoTremplate() without having to go for the contentEditable functionality that is available in the AW.Templates.ImageText class? I would love to see a cell (that is currently being edited) displaying an HTML Textbox and an image (or, lets say, one my template customizations) and display back text once cell editing has been complete.

1. I would never want to staticly use obj.setCellTemplate() because it would display all of the cells in a particular column allowing user modification at all times. I would want to enable/disable this template only when the current cell is in editable mode (ideally the missing setEditorTemplate() was doing this job). I'm thinking of the events 'cellEditStarting' and 'cellEditEnded' -- but what is the best code to write in here?

2. By stepping into the code, I understood that AW.Templates.ImageText is the class that forms the base source for t.startEdit() -- all others Templates (including Input and Combo) inherit from this base class and reuse this browser based contentEditable functionality, if my understanding is correct. It would be a real pain (and might be misleading for me) if I go inherit this class and duplicate the startEditIE and startEditGecko private methods to apply an editor template like behaviour.


Please, Alex and other experts, suggest me a better solution to this problem -- If such a case was already encountered and resolved, please apologize for this duplicate post (I tried my best searching the forums), and kindly share the link.

So far in all the PoC i have done, this is the only show stopper that has kept me from going for the commercial version. I greatly appreciate your advice and the time spent with this.

Thanks
Neo (TrioteX)
May 21,
OK, I came up with a patch myself -- took me three full hours but in the end it is a good progress:

This is a generic code, so you can use it for any template you like, Combo, custom template etc.

The idea is to create a Doublet -- yes, it would be a pair of templates, viz., the view template and the edit template. When the cell is in edit mode the edit template is displayed and when the cell comes out of edit mode the view template is restored.

I have to create this concept called Doublet, just because the grid exposes limited customization to the cell template -- that is, either to display the cell template all the time or restricts the user to go with in-line editing with just one default template (the base class for all these is AW.Templates.ImageText).

OK, now to the solution. Create a grid just like you usually do. And instead of passing a static Combo template to the setCellTemplate method, pass it through Doublet Pairing


var doublet = AW.Templates.Doublet.Pair( 
                        obj.getCellTemplate(1), 
                        new AW.Templates.Combo 
                  ); 
    obj.setCellTemplate( doublet, 1);


Here is a sample code:

This code has the following features:
- Allow inline editing of the grid.
- Allow a column to have a different template instead of the default one (Combo used for second column)
- Allow Combo to appear for the currently selected cell only.
- Commit and Discard changes to the combo or a cell using Enter and Esc keys
- Navigate through the cells/rows using Tab keys


Known Issue:
- Double click on other cell when the popup is being shown (or the combo is being edited) doesn't move the focus to the other cell. This could be a minor problem with Combo to be fixed (I haven't checked the code, and its so late here :( ). If someone has pointers or fixed this little thing alone, please post.

Hope this helps!

<SCRIPT>


AW.Templates.Doublet={};
AW.Templates.Doublet.Pair=function(viewTemplate, editTemplate){
    viewTemplate.editTemplate = editTemplate;
    editTemplate.viewTemplate = viewTemplate;
    return viewTemplate;
};

AW.Grid.Controllers.Cell.DoubletsPatch=function(){
    var controller = this;
    if (!controller.editCurrentCell ||
        controller.editCurrentCell!==controller.onKeyPress){return}
    // backup original functionality
    controller._orig_startEdit = controller.editCurrentCell;
    controller.doubletStartEdit = function( event ) {

     	var c=this.getCurrentColumn();
        var r=this.getCurrentRow();
        if(!this.getCellEditable(c,r)){return}
        var t=this.getCellTemplate(c,r);
        if (!t || this.$edit){return}
        if ( t.editTemplate ) {

            var self = t;
            var item=self.getAttribute("aw");
            var originalText=self.getControlProperty("text");
            var text=originalText;

            function raiseEvent(name){
                var text1=self.getControlProperty("text");
                var fullname=AW.camelCase("on",item,name);
                var result=self.raiseEvent(fullname,text,self.$0,self.$1,self.$2);
                var text2=self.getControlProperty("text");
                if(text2!=text1){updateText(text2)}
                return result
            }
            if(raiseEvent("editStarting")){self=null;return}

            eT = t.editTemplate;
            eT._et_startEdit = eT.startEdit;
            eT.startEdit = t.startEdit;
            this.setCellTemplate(eT,c,r);
            t=this.getCellTemplate(c,r);
            t.refresh();

            t.onCellEditStarting=function(){
                //No-Op
            };
            t.onCellEditStarted=function(){
                raiseEvent("editStarted");
            };
            t.onCellEditEnded=function(){
            	var vT = this.viewTemplate;
                this.startEdit = this._et_startEdit;
                this.$owner.setCellTemplate(vT,c,r);
                var t=this.$owner.getCellTemplate(c,r);
                t.refresh();
                raiseEvent("editEnded");
                self = t = vT = null;
            };
        }
     	if(t.startEdit && !this.$edit){
     		this.$editCol=c;
            this.$editRow=r;
            if(event && event.type=="keypress"){
                if(event.keyCode !=27){
                    t.startEdit(String.fromCharCode(event.keyCode || event.charCode))
                }
            }else{
                t.startEdit()
            }
            AW.setReturnValue(event,false)
        }

    };
    // Assign new functionality
    controller.onMouseDown = controller.editCurrentCell = controller.onKeyPress = controller.doubletStartEdit;
};
AW.Grid.Controllers.Cell.DoubletsPatch();







        var myData = [
            ["MSFT","Microsoft Corporation", "314,571.156", "32,187.000", "55000"],
            ["ORCL", "Oracle Corporation", "62,615.266", "9,519.000", "40650"],
            ["SAP", "SAP AG (ADR)", "40,986.328", "8,296.420", "28961"],
            ["CA", "Computer Associates Inter", "15,606.335", "3,164.000", "16000"],
            ["ERTS", "Electronic Arts Inc.", "14,490.895", "2,503.727", "4000"],
            ["SFTBF", "Softbank Corp. (ADR)", "14,485.840", ".000", "6865"],
            ["VRTS", "Veritas Software Corp.", "14,444.272", "1,578.658", "5647"],
            ["SYMC", "Symantec Corporation", "9,932.483", "1,482.029", "4300"],
            ["INFY", "Infosys Technologies Ltd.", "9,763.851", "830.748", "15400"],
            ["INTU", "Intuit Inc.", "9,702.477", "1,650.743", "6700"],
            ["ADBE", "Adobe Systems Incorporate", "9,533.050", "1,230.817", "3341"],
            ["PSFT", "PeopleSoft, Inc.", "8,246.467", "1,941.167", "8180"],
            ["SEBL", "Siebel Systems, Inc.", "5,434.649", "1,417.952", "5909"],
            ["BEAS", "BEA Systems, Inc.", "5,111.813", "965.694", "3063"],
            ["SNPS", "Synopsys, Inc.", "4,482.535", "1,169.786", "4254"],
            ["CHKP", "Check Point Software Tech", "4,396.853", "424.769", "1203"],
            ["MERQ", "Mercury Interactive Corp.", "4,325.488", "444.063", "1822"],
            ["DOX", "Amdocs Limited", "4,288.017", "1,427.088", "9400"],
            ["CTXS", "Citrix Systems, Inc.", "3,946.485", "554.222", "1670"],
            ["KNM", "Konami Corporation (ADR)", "3,710.784", ".000", "4313"]
        ];

        var myColumns = [
            "Ticker", "Company Name", "Market Cap.", "$ Sales", "Employees"
        ];



    var obj = new AW.Grid.Extended;


    //	provide cells and headers text
    obj.setCellText(myData);
    obj.setHeaderText(myColumns);
    
    // save grid data for future use
    obj.gridData = myData;

    //	set number of rows/columns
    obj.setRowCount(myData.length);
    obj.setColumnCount(myColumns.length);

    obj.setSelectionMode("single-cell");

    //	enable row selectors
    obj.setSelectorVisible(true);
    obj.setSelectorText(function(i){return this.getRowPosition(i)+1});

    //	set headers width/height
    obj.setSelectorWidth(30);
    obj.setHeaderHeight(20);

    //	allow editing
    obj.setCellEditable(true);

    //	disable virtual rendering
    obj.setVirtualMode(false);



    // change the first column to a doublet

    var itemText1 = ["Francis Ford Coppola","Quentin Tarantino","Sam Mendes","Alfred Hitchcock"];
    var itemValues1 = [1,2,3,4];

    var list1 = new AW.UI.List;
    list1.setItemText(itemText1);
    list1.setItemValue(itemValues1);
    list1.setItemCount(itemText1.length);

    obj.setPopupTemplate(list1, 1);




    var doublet = AW.Templates.Doublet.Pair(
                        obj.getCellTemplate(1),
                        new AW.Templates.Combo
                  );
    obj.setCellTemplate( doublet, 1);



    // ... Other customizations follow



    /* SET CONTROL KEYS */
    obj.setController("MyTabKeys", {
        onKeyTab: "mySelectNextCell",
        onKeyEnter: "mySelectNextCell",
        onKeyShiftTab: "mySelectPreviousCell"
    });

    /* onKeyTab */
    obj.mySelectNextCell = function(event) {
        //alert( event.keyCode );
        var c = new Number(this.getCurrentColumn()) + 1;
        var r = new Number(this.getCurrentRow());
        if (c >= this.getColumnCount()) {
            c = 0;
            r++;
        }
        try {
            // move focus out, triggers end of edit
            this.getContent("focus").element().focus();
        }
        catch(err) {
            // ignore focus errors
        }
        if (r < this.getRowCount()) {
            this.mySelectCell(c, r);
        } else {
            this.gridData.push([]);
            this.addRow();
            this.mySelectCell(0, r);
        }
        //
        AW.setReturnValue(event, false);
        event = null;
    }

    /* onKeyShiftTab */
    obj.mySelectPreviousCell = function(event) {
        var c = new Number(this.getCurrentColumn()) - 1;
        var r = new Number(this.getCurrentRow());
        if (c < 0) {
            c = this.getColumnCount() - 1;
            r--;
        }
        try {
            // move focus out, triggers end of edit
            this.getContent("focus").element().focus();
        }
        catch(err) {
            // ignore focus errors
        }
        if (r > -1) {
            this.mySelectCell(c, r);
            AW.setReturnValue(event, false);
        }
        event = null;
    }

    /* Custom Select Cell function */
    obj.mySelectCell = function(c, r){

        if (c != this.getCurrentColumn()){
            this.setCurrentColumn(c);
        }

        if (r != this.getCurrentRow()){
            this.setCurrentRow(r);
        }

        var cc = this.getSelectedColumns();
        if (cc.length != 1 || cc[0] != c){
            this.setSelectedColumns([c]);
        }

        var rr = this.getSelectedRows();
        if (rr.length != 1 || rr[0] != r){
            this.setSelectedRows([r]);
        }
    }

/*
    // override original selection controllers //
    obj.setController("selection", {
        selectPreviousCell: mySelectNextCell,
        selectNextCell: mySelectPreviousCell
    });
*/

    /**
     * auto edit on cell selection (if cell supports edit)
     */
    obj.onCellSelectedChanged = function(selected, col, row) {
       if (selected) {
            this.setTimeout(function(){
                this.raiseEvent("editCurrentCell", {}, col, row);
            });
        }
    }

    obj.onCellClicked = function(event, col, row) {
       if (obj.getCellSelected(col, row)) {
            this.setTimeout(function(){
                this.raiseEvent("editCurrentCell", {}, col, row);
            });
        }
    }


    document.write(obj);



    </SCRIPT>

Neo (TrioteX)
May 21,
w00t, the known issue was resolved. It was because of the event bubble cancelation by the viewTemplate that is being refreshed after cell edit mode has ended. I used the classic technique: setTimeout(fn,10) and it now works great!

Old:
t.onCellEditEnded=function(){ 
                var vT = this.viewTemplate; 
                this.startEdit = this._et_startEdit; 
                this.$owner.setCellTemplate(vT,c,r); 
                var t=this.$owner.getCellTemplate(c,r); 
                t.refresh(); 
                raiseEvent("editEnded"); 
                self = t = vT = null; 
            };


New lines:
t.onCellEditEnded=function(){
                var eT = this;
       			    var vT = this.viewTemplate;
                var grid = this.$owner;
                grid.setCellTemplate(vT,c,r);
                setTimeout(function(){
                    grid.getCellTemplate(c,r).refresh();
                    grid = self = eT = vT = t = null;
                }, 10);
                raiseEvent("editEnded");
            };

Neo (TrioteX)
May 22,
And here is the complete patch-doublet.js file:

AW.Templates.Doublet={};
AW.Templates.Doublet.Pair=function(viewTemplate, editTemplate){
    viewTemplate.editTemplate = editTemplate;
    editTemplate.viewTemplate = viewTemplate;
    return viewTemplate;
};

AW.Grid.Controllers.Cell.DoubletsPatch=function(){
    var controller = this;
    if (!controller.editCurrentCell ||
        controller.editCurrentCell!==controller.onKeyPress){return}
    // backup original functionality
    controller._orig_startEdit = controller.editCurrentCell;
    controller.doubletStartEdit = function( event ) {

     	var c=this.getCurrentColumn();
        var r=this.getCurrentRow();
        if(!this.getCellEditable(c,r)){return}
        var t=this.getCellTemplate(c,r);
        if (!t || this.$edit){return}
        if ( t.editTemplate &&
                            (!event || event.type!="keypress" || event.keyCode!=27)
            ) {

            var self = t;
            var item=self.getAttribute("aw");
            var originalText=self.getControlProperty("text");
            var text=originalText;

            function raiseEvent(name){
                var text1=self.getControlProperty("text");
                var fullname=AW.camelCase("on",item,name);
                var result=self.raiseEvent(fullname,text,self.$0,self.$1,self.$2);
                var text2=self.getControlProperty("text");
                if(text2!=text1){updateText(text2)}
                return result
            }
            if(raiseEvent("editStarting")){self=null;return}

            eT = t.editTemplate;
            this.setCellTemplate(eT,c,r);
            t=this.getCellTemplate(c,r);
            t.refresh();

            t.onCellEditStarting=function(){
                //No-Op
            };
            t.onCellEditStarted=function(){
                raiseEvent("editStarted");
            };
            t.onCellEditEnded=function(){
                var eT = this;
                var vT = this.viewTemplate;
                var grid = this.$owner;
                grid.setCellTemplate(vT,c,r);
                setTimeout(function(){
                    grid.getCellTemplate(c,r).refresh();
                    grid = self = eT = vT = t = null;
                }, 10);
                raiseEvent("editEnded");
            };
        };

     	if(t.startEdit && !this.$edit){
     		this.$editCol=c;
            this.$editRow=r;
            if(event && event.type=="keypress"){
                if(event.keyCode !=27){
                    t.startEdit(String.fromCharCode(event.keyCode || event.charCode))
                }
            }else{
                t.startEdit()
            }
            AW.setReturnValue(event,false)
        }

    };
    // Assign new functionality
    controller.onMouseDown = controller.editCurrentCell = controller.onKeyPress = controller.doubletStartEdit;
};
AW.Grid.Controllers.Cell.DoubletsPatch();


HTH
Neo (TrioteX)
May 22,

This topic is archived.

See also:


Back to support forum