3.2.0

Table DataModel for JS Array

'js_table_model.html'

I tried to make something similar to XML data model for JS Array

Working fine, but needs more improvements, suggestions are welcome...

<html>
<head>
  <title>ActiveWidgets Grid :: Examples</title>

  <!-- ActiveWidgets stylesheet and scripts -->
  <link href="../../runtime/styles/xp/grid.css" rel="stylesheet" type="text/css" ></link>
  <script src="../../runtime/lib/grid.js"></script>

  <!-- grid format -->
  <style>
.active-controls-grid {height: 200px; width: 680px; font: menu;}
.active-scroll-bars {overflow-y: scroll;}
.active-column-0 {width:  80px;}
.active-column-1 {width: 200px;}
.active-column-2 {text-align: right;}
.active-column-3 {text-align: right;}
.active-column-4 {text-align: right;}

.active-grid-column {border-right: 1px solid threedlightshadow;}
.active-grid-row {border-bottom: 1px solid threedlightshadow;}
  </style>

  <!-- grid data -->
  <script>
var myData5 = [
  ["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"]
];

var myData10 = [
  ["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"]
];

var myData20 = [
  ["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"
];

// ****************************************************************
//     JavaScript DataModel.
// ****************************************************************

if (!window.My) My=[];
if (!My.JS) My.JS=[];

My.JS.Table = Active.System.Model.subclass();
My.JS.Table.create = function(){

  var obj = this.prototype;
  obj._items = [];
  obj._formats = [];
  obj._ready = true;

  obj.setItems = function(data) {
    this._items = data;
    this.setReady(true);
    if (this.$owner) {
      //var sindex = this.$owner.getSortProperty("index");
      //var sorder = this.$owner.getSortProperty("direction");
      this.$owner.setRowProperty("value", function(i){return i});
      this.$owner.setRowProperty("order", function(i){return i});
      this.$owner.setRowProperty("count", this.getCount());
      this.$owner.setSortProperty("index", -1);
      this.$owner.setSortProperty("direction", "none");
      //if(sindex != -1) {
      //  this.$owner.sort(sindex, sorder);
      //}
      this.$owner.refresh();
    }
  };

  obj.setFormat = function(format, index){
    this._formats = this._formats.concat();
    this._formats[index] = format;
  };

  obj.getCount = function(){
    if (!this._items) {return 0}
    return this._items.length;
  };

  obj.getIndex = function(i){
    return i;
  };

  obj.getText = function(i, j){
    var data = this.getData(i, j);
    var format = this._formats[j];
    return format ? format.dataToText(data) : data;
  };

  obj.getImage = function(){
    return "none";
  };

  obj.getLink = function(){
    return "";
  };

  obj.getValue = function(i, j){
    var data = this.getData(i, j);
    var format = this._formats[j];
    if (format) {
      return format.dataToValue(data);
    }
    var value = Number(data.replace(/[ ,%\$]/gi, "").replace(/\((.*)\)/, "-$1"));
    return isNaN(value) ? data.toLowerCase() + " " : value;
  };

  obj.getData = function(i, j){
    return this._items[i][j] ? this._items[i][j] : "";
  };

  obj.isReady = function(){
    return this._ready;
  };

  obj.setReady = function(ready){
    this._ready = ready;
  };
};

My.JS.Table.create();

  </script>
</head>
<body>
  <script>

  //  create ActiveWidgets Grid javascript object
  var obj = new Active.Controls.Grid;

  //  provide column labels
  obj.setColumnProperty("texts", myColumns);

  obj.setDataModel(new My.JS.Table);

  //  set headers width/height
  obj.setRowHeaderWidth("28px");
  obj.setColumnHeaderHeight("20px");

  //  set click action handler
  obj.setAction("click", function(src){window.status = src.getItemProperty("text")});

  //  write grid html to the page
  document.write(obj);
  
  </script>
  
  <input type="button" onclick="show0()" value="Show 0"/>
  <input type="button" onclick="show5()" value="Show 5"/>
  <input type="button" onclick="show10()" value="Show 10"/>
  <input type="button" onclick="show20()" value="Show 20"/>
  
  <script>
  function show0() {  
    obj.getDataModel().setItems([]);;
  }
  function show5() {  
    obj.getDataModel().setItems(myData5);;
  }
  function show10() { 
    obj.getDataModel().setItems(myData10);;
  }
  function show20() { 
    obj.getDataModel().setItems(myData20);;
  }
  
  </script>

</body>
</html>
Sudhaker Raj
September 24,
Forgot to mention the force behind it.

Set the array – you are done. No need to specify ‘row/count’ or ‘data/count’.

obj.getDataModel().setItems(myData5);


Add/delete/modify the JS array and set it again ;-) No more sorting bug or complex operations…

Cheers,
Sudhaker Raj
September 24,
Alex, I was expecting some comment from you over this.
Sudhaker Raj
September 27,
First of all - this is exactly how data models are supposed to work. The default data model might be too simplistic or limited, so you build a better one and plug it in instead of the default.

Should the default model behave exactly like this? Maybe, but initially I did not think that js array is a very good way of storing the data. In my previous experience I used array of (complex) objects much more often. Thats why I was focusing more on having functions to supply the correct data.

Also different people mean different things when passing the new data into the existing grid. For some this is exactly the same data, just with updated values, so you'd rather keep row order (or run sort procedure before refresh). For others it is completely different data, so you have to reset columns as well. What do you think?

For a generic model I would implement similar procedures for values, images and links. Maybe calling them setTexts, setValues, setImages, setLinks instead of just setItems. Maybe these procedures should also work with a single row of data and row index to update one row only.

You can use also this syntax: grid.setDataProperty("texts", []) or with your current implementation grid.setDataProperty("items", []).
Alex (ActiveWidgets)
September 27,

Yeah, you are right :-) This JS model will be too specific to be generic and what you did already is very flexible.

I ended up doing this for 2 major reasons

1. Sorting bug (if you change data after sorting, it crashes)
2. In direct support of format object.

For item 1. I had this fix

Active.Controls.Grid.prototype.setAction("dataChanged", function() {
  var newCount = this.getDataProperty("count");
  // clear internal row state
  var rowValues = [];
  for(var i=0; i < newCount; ++i) { rowValues.push(i); }
  this.setRowProperty("values", rowValues);
  this.setSortProperty("index", null);
  // clear selection - if required
  this.setSelectionProperty("index", -1);
  this.setSelectionProperty("values", []);
  // clear any nodata or loading status
  if(newCount > 0) {
    this.setStatusProperty("code","");
  } else {
    this.setStatusProperty("code","nodata");
  }
  this.refresh();
});


Make grid like this

obj.gridData = [];
obj.getDataText = function(i, j){return this.gridData[i][j]};
obj.setDataText = function(value, i, j){this.gridData[i][j] = value};


And all I need to call after data changed

obj.gridData = newData;
obj.setDataProperty("count", obj.gridData.length);
obj.action("dataChanged");


The new JS Array model was giving me easy way to get the same with just 1 line and it also supports format.
---

Perhaps, I'll switch back to default model to keep myself closer to your future release.

Sudhaker Raj
September 28,

Alex, please have a look at http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/table/AbstractTableModel.html (if not already).

I liked isCellEditable() and other fire* methods and will be great if something similar is implemented in AW Grid also.

isCellEditable can make cells editable specifically. Right now, only whole column can be made editable.

Thanks,
Sudhaker Raj
September 28,

Java script array is fastest / easiest way to generate dynamic data is using loops in any programming language.

Alex, can we expect your ideal javascript table model from you ASAP?


Sudhaker Raj
November 24,
It is possible to use the paging patch with this data model?
How should it be implemented?
Giovanni
December 10,
Another question is about Date formatting with this table model.
Im trying this:

var date = new Active.Formats.Date;
    date.setTextFormat("dd/mm/yyyy");
    date.setDataFormat("ISO8061");

    var table = new My.JS.Table;
    table.setFormat(wApp_1_Date,4);

    var obj = new Active.Controls.Grid;
    obj.setDataModel(wApp_1_Table);


and im getting a bunch of #ERR on the column that I tried to format.

What could be wrong?
Thanks.
Giovanni
December 10,

This topic is archived.

See also:


Back to support forum