Login Register

Events

As we alluded to in the last few pages, selection and cell editing is pointless without some kind of background processing. So how do you hook code into these places? Through Dojo's event model, of course!

Editing Changes

If you're using a writable dojo.data datastore, you simply hook your procedures into the dojo.data Notification API. Suppose in our running example, we make the Description field editable:

cells: [[
    {name: 'Namespace', field:0, width:"30em"}, 
    {name: 'Description', field:3, width:"30em",
        editor: dojox.grid.editors.Dijit }
  ]
],

Then, we place the hook into dojo.data.Notification's onSet extension point:

<div dojoType="dojo.data.ItemFileWriteStore"
        jsId="jsonStore" url="dijits.txt">

    <script type="dojo/connect" event="onSet" args="item,attr,oldVal,newVal">
       console.debug("About to change "+attr+" from "+oldVal+" to "+newVal);
       // Save the record with dojo.xhrPost or your favorite remote method
    </script>
</div>

Here is the entire source code. Note how we place the layout initialization code in a dojo/method block inside the Grid tag. That's due to the editor class dojox.grid.editors.Dijit in the view definition. When you're using CDN, the dojox.grid.editors package is not available directly after the dojo.require., so we can't place the initialization code after it (as we did in our previous examples). By using a dojo/method, we can place this code close to its use (the Grid tag) and it's guaranteed to run after all dojo.require'd modules have loaded. You can also use dojo.addOnLoad to accomplish this.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title>Test dojox.Grid Editing</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
    <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dojox/grid/_grid/tundraGrid.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
        body {
            font-size: 0.9em;
            font-family: Geneva, Arial, Helvetica, sans-serif;
        }
        .heading {
            font-weight: bold;
            padding-bottom: 0.25em;
        }
               
        #grid {
            border: 1px solid #333;
            width: 40em;
            height: 30em;
        }
    </style>
    <script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
            djConfig="isDebug:false, parseOnLoad: true">
</script>
    <script type="text/javascript">
        dojo.require("dojo.data.ItemFileWriteStore");
        dojo.require("dojox.grid.Grid");
        dojo.require("dojox.grid._data.model");
        dojo.require("dojox.grid.editors");
        dojo.require("dojo.parser");
   
</script>
</head>
<body class="tundra">
<div class="heading">Grid Events</div>
    <div dojoType="dojo.data.ItemFileWriteStore"
        jsId="jsonStore" url="dijits.txt">

        <script type="dojo/connect" event="onSet" args="item,attr,oldVal,newVal">
            console.debug("About to change "+attr+" from "+oldVal+" to "+newVal);
        </script>
    </div>
    <div dojoType="dojox.grid.data.DojoData" jsId="model"
        rowsPerPage="20" store="jsonStore" query="{ namespace: '*' }"
        clientSort="true">

    </div>
    <div id="grid" elasticView="2" dojoType="dojox.Grid" model="model"
        jsId="thisGrid">

        <script type="dojo/method">
            var view1 = {
                cells: [[
                    {name: 'Namespace', field:0, width:"30em"},
                    {name: 'Description', field:3, width:"30em"}
                  ],
                  [
                    {name: 'Summary', field:2, colspan:2,
                     editor: dojox.grid.editors.Dijit }
                  ]
                ]
            };
            var rowbar = {
               type: 'dojox.GridRowView', width: '20px'
            };
            var fixedColumn = {
                 noscroll: true,
                 cells: [[ {name: 'Class', field:1} ]]
            };
           
            // When you initialize inside the dojo/method script, you must set the
            // structure manually.
            var layout = [ rowbar, fixedColumn, view1 ];
            thisGrid.setStructure(layout);
        </script>
       </div>
</body>
</html>

You can read more on the dojo.data Notification API in Part 3 of the book, but here are the basics for your Grid needs:

  • onSet: function(/* item */ item, /* attribute-name-string */ attribute, /* object | array */ oldValue, /* object | array */ newValue ) - called after any cell is edited and saved.
  • onNew: function(/* item */ newItem,) - called after a row is added to the grid.
  • onDelete: function(/* item */ deletedItem) - called after a row is deleted

Low-Level Events

For more granular event processing, you can hook into Grid events. Each event calls the function you provide, passing back the event object. If e is the event, the interesting stuff is in:

  • e.rowIndex: the row number
  • e.cell.index: the column (cell) number. Taken with e.rowIndex, effectively gives you coordinates of a cell event.
  • e.keyCode: keystroke value, only applicable to keydown event.
Entity click/double click mouse over/out right click
Data Cell onCellClick
onCellDblClick
onCellMouseOver
onCellMouseOut
onCellContextMenu
Hdr Cell onHeaderCellClick
onHeaderCellDblClick
onHeaderCellMouseOver
onHeaderCellMouseOut
onHeaderCellContextMenu
Data Row onRowClick
onRowDblClick
onRowMouseOver
onRowMouseOut
onRowContextMenu
Hdr Row onHeaderClick
onHeaderDblClick
onHeaderMouseOver
onHeaderMouseOut
onHeaderContextMenu

onRowDblClick in IE6 with window.open misbehavior

Setting an onRowDblClick handler with a window.open command works fine in FF/Ubuntu.

But in IE6 the new window fails to get focus (sometimes blinks into focus momentarily) and will not retain focus when alt-tabbed to from the parent window.

Invoking the same handler from a button works fine.

grid = new dojox.Grid({
        "id": "grid",
        "model": model,
        "structure": layout,
        "autoWidth" : true,
        "onRowDblClick" : editCheck,
        "defaultHeight": 8
        },dojo.byId("list"));

...

function editCheck(evt) {

    var row=evt.rowIndex;
    
    var rowID=grid.model.getDatum(row,IDfieldNum);
    editwin=window.open('retCheckEdit.pl?id='+ rowID,'_blank','width=800,height=394,resizable=no,toolbar=no,location=no,directories=no,status=no,menubar=no,copyhistory=no,left=30,top=128,screenX=30,screenY=128');

    return true;
}

* code edited to be more clear -1st version was for button or event

How can the new window get focus in IE6?

Thanks In Advance,

George

IE6 and clicks

IE frequently has trouble doing stuff at click-time. My usual solution is to set an idle-time timeout like so:

function editCheck(evt) {
  var row = evt.rowIndex;
  var rowID = grid.model.getDatum(row,IDfieldNum);
  setTimeout(function(){ window.open(...); }, 1);
  return true;
}

Cheers,
Scott