GridWidget
Version 27, changed by guest 01/29/2006.
Show version history
Proposed Classes/Concepts
- UI Widgets -- Different types of UI widgets may want to get data from a DataProvider and display it in different ways. Here are some types of widgets that might all be bound to the same data source:
- DataGrid -- A grid widget (any sort of editable table, like a spreadsheet)
- charts -- bar charts, pie charts, scatter plots, Gantt charts, etc. (all drawing on data provided by a "Data Provider")
- other widget bindings -- e.g. binding Data Provider columns to a ComboBox or List widget
- single-object widget -- displays all the fields of a single DataObject?
- Data Model
- DataSet? or RecordSet? -- A DataSet? holds a collection of DataObject? objects. The DataSet? object might have methods like:
- getColumns() or getFields()
- getRows() or getObjects()
- getRowCount()
- addRow()
- deleteRow() vs. removeRow() ?
- addColumn() ?
- removeColumn() ?
- getColumnCount()
- sort(dataColumn, ascendingVsDescending) or sort(field, ascendingVsDescending)
- DataObject? or DataItem? or DataRecord? -- A single DataObject? object represents a single record in a data store, like a record in a RDBMS. The DataObject? might have methods like:
- setValue(field) -- "field" could be a DataColumn?, or a string with the name of the field/DataColumn?
- getValue(field)
- compare(otherDataObject) -- used for sorting a table (maybe returns -1, 0, or +1)
- compare(otherDataObject, field) -- used for sorting a table (maybe returns -1, 0, or +1)
- validate() or isValid()
- delete()
- DataColumn? -- A DataColumn? represents a column header shared by the DataObjects? in a DataSet?. A DataColumn? is like a "field", or "attribute", or "property". The DataColumn? object might have methods like:
- getName() or getCaption()
- getDescription()
- getType()
- toString() -- should return the same thing as getName(), so that a simple DataGrid implementation can ignore the DataColumn? object entirely
- getFormula() or getDerivationRule() -- used by spreadsheet-type apps (example: "= width * height")
- getTextFormatting() -- for example: alignment (left, center, right), or $x.xx, or "0.4" vs "40%"
- DataType? -- A DataType? objects represents a type of value. Examples of DataTypes? might be "varchar", "Text", "Number", "int", "Date", "URL", "e-mail address", etc. The DataType? object might have methods like:
- compare(firstValue, secondValue) -- used for sorting a table
- getName()
- convert(value, otherDataType)
- validate(value) or isValid(value)
- DataValue? or DataCell? -- Having an explicit DataValue? class may be going too far. Maybe it's enough to just represent literal values as JavaScript Date objects and JavaScript literals like strings and numbers. However, without an explicit DataValue? class it's hard to solve some problems, so it might be worth having one available. A simple DataGrid implementation could just ignore it, while fancier implementations could take advantage of it. A DataValue? object might have methods like:
- toString() -- returns a simple string literal representation of the value
- getValue() -- returns a string literal, or a JavaScript number, or a JavaScript Date, etc.
- getType() -- returns a DataType? object
- getFormula() or getDerivationRule() -- used by spreadsheet-type apps (example: "= width * height")
- getTextFormatting() -- for example: alignment (left, center, right), or $x.xx, or "0.4" vs "40%"
- Data Providers
- A DataProvider (or DataSource?) is an object that knows how to get data from some sort of data store, like an RDBMS, and transform the data into a common Dojo data model that different UI widgets can be bound to. You can create a DataProvider object and set it up to get data from some data store, and then when you ask the DataProvider for data, it returns results in the form of Data Model objects, like DataObjects?, DataColumns?, DataTypes?, etc.
- A DataProvider might talk to a remote data store (like an RDBMS) via SOAP or RPC or whatever, or a DataProvider might talk to a local data store (held in memory, or stored on the local hard drive using dojo.storage).
- A DataProvider might talk to a highly structure data store (like an RDBMS), or a semi-structured data store (like Google Base, or the Ning Content Store, or the JotSpot? page/property store)
- Examples of DataProviders? might include: JSONDataProvider, HtmlTableProvider, XmlDataIslandProvider, SOAPProvider
- A DataProvider object might have methods like:
- fetch() or get() or find() or getQueryResultSet()
- save() or update()
- delete(dataObject)
- beginTransaction()
- endTransaction()
- RPC layer
Design Issues
- Caching
- "I would think that the caching would need to be handled at a layer above the rpc call, but I'm sure we could debate that portion. I expected the
caching to occur at the dataobject level....which would be best at knowing how it can cache things in a way that makes sense to it (as would other
higher level things build on rpc)" -- Dustin Machi - "I agree" -- Alex Russell
- Merging vs. separating the ideas of DataProvider and DataSet?
- "We're talking about two separate things here, a data provider and some sort of data set representation. I would seriously prefer that these remain separated, with said providers returning said data set as the primary functionality of the provider." -- Tom Trenka
- "I think that I agree with this :) Though I would think that aside from initially getting the data they need to be able to provide minimal set of operations with that (in a way thats standardized across provider types)." -- Dustin Machi
- Merging vs. separating the ideas of DataObject? and DataSet?
- "I think there's a big difference between a DataObject and an actual DataSet, so we should probably keep it in mind" -- Tom Trenka
- "I would personally go about this by creating objects that can do everything with their particular row of data, where the DataSet is a collection of those objects (multiple rows) that knows how to work with multiple objects to present them in a useful way. For example, an object can have a comparator method that compares itself or some part of itself against another instance of a the same object and know whether it is greater or less than that object. A 'sort' on the dataset would essentially be running an algorithm that exploits the objects ability to compare itself to other objects, without itself knowing how to deal with that. The same holds true with objects knowing how to edit, update, and validate its data. It would seem to me to be best to define that at the object (row) level and then let the grid just deal with things that are related to a collection." -- Dustin Machi
- 2-dimensional data sets vs. N-dimensional sets
- "I think we should probably start by modeling on a standard, 2 dimensional set" -- Tom Trenka
- Speed
- We "should think about performance considerations when dealing with these; it's nice to make them elegant, but not at the risk of not being able to create large tables with good performance. Sometimes it's hard to have both elegance and performance in JavaScript, especially for extremely large datasets and creation of things like large tables." -- Brad Neuberg
- "I also share Brad's concern with whatever the final API, performance be an important part of the design." -- Michael Tildahl
- Automatic data-driven generation of UI
- "I can see that if we have dataobjects we can have datasets(grids) of those objects and we can also automatically generate entire forms and view of those individual objects in an automated fashion. And while I understand that not everyone necessarily wants things automatically generated for them...I see we could use that as a method of compression of source code. Instead of writing the code to design these forms and views, the object definition is all that is passed. This then generates these views and the only code that is required is to customize the view on top of that. All that said, I don't know whether the savings in code transport is <, >,== the amount of processing time it takes to "uncompress" (build the objects and forms) than the time it takes to transfer the extra code. It should at least be less error prone." -- Dustin Machi
- Structured data vs. semi-structured data
- "My concern with basing the data provider API on things like ADO.NET or JDBC is that we need to be more flexible than the relational model provides. Things like spreadsheets can have different types on a per cell basis." -- Michael Tildahl
- "This is the strength of the delegation/prototype model. We can define the main metadata on the column objects (if there is such a thing), but let a cell override the methods so that it's specific to itself." -- Tom Trenka
- "I'm not suggesting that we try to pull a full-on relational model; I'm just suggesting that since most data of this sort is tabular, that we might look to pre-existing models. I've no problem creating a data set structure based on object database systems, for instance...just throwing out ideas." -- Tom Trenka
- "In my mind something better to base the data provider API on is the Java Swing TableModel interface.
http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/table/TableModel.html It gives a clean separation but doesn't limit you to the relation model." -- Michael Tildahl
- Metadata
- "Metadata in another important issue. I'm thinking that metadata would either just be added dynamically to the data object as an application needs it or stored in the dom and not using the data object at all." -- Michael Tildahl
- "Storing it in the DOM is very possibly less efficient than designing a set of objects to handle the task (it depends on how you'd store it in the DOM), but that's still a possibility." -- Tom Trenka
- Multi-valued cells
- The other issue for the data object is that it needs to take into account that cells can have more than one value.
- "I still don't agree with this one, because you're assuming that the only use for the data set is to serve as the foundation of a spreadsheet. I would hate to try to figure out how to chart a cell with more than one value, for instance." -- Tom Trenka
- Calculated values vs. raw values
- "However, if you're thinking about calcuated values as opposed to properties, there's nothing wrong with defining a set of methods such as "getValue" that you can override on a case-by-case basis...in fact, that would probably be the best solution to this anyways, given JS's flexibility with the delegation model." -- Tom Trenka
Links
- Overview
- Alternative approaches
- Microsoft's ADO and ADO.NET
- Java's JDBC
- Data Model
- Grid Widgets
- Data Provider
- Binding UI to Data
- Rendering
- Inspiration
Grid Widget: Proposed Features Fly-by
- Paging (large datasets)
- Formatting values
- Text
- Number, Currency
- Date, Time
- Percentage, Fraction
- Scientific
- URL
- etc... this should be user-extensible obviously (IP address, Zip code, SSN)
- Formatting cells
- bold, italic, underline
- text color
- bgcolor
- alignment: left, center, right
- hyperlinks
- Edit standard (textual) cell values
- plaintext edit
- richtext edit
- overflow handling (Excel-like or not)
- Edit non-textual cell values
- dropdowns w/ constrained values
- checkboxes, radio buttons, buttons
- custom form dialog that pops out of the cell
- images
- icon next to text value
- entire cell is filled with an image
- Multi-valued cells
- columns can have some cells with single values, like the date "2005-11-24"
- columns can have some cells that can have multiple values, like "2005-11-24, 2006-03-19"
- Loosely-typed columns (like in Excel)
- different cells in a column can have different types of values (e.g. mostly dates, but with some URLs)
- Row headers
- lock row headers, chrome-only
- lock row headers including some data columns
- Modify/remove row header labels (numbers, by default)
- context menu for row-specific actions
- Column headers
- toggleable (has named col headers, or not)
- lock column headers (so rows scroll but headers remain visible)
- rename
- context menu for col-specific actions
- collapse columns
- Spanning a column heading over two columns of data
- Row Actions
- dnd reorder rows
- format all cells in row
- Column Actions
- dnd reorder cols
- format all cells in col
- resize column widths
- Expandable/drilldown rows
- Selection
- cell
- row
- col
- select all
- shift/ctrl click multi-select manager
- "rubber-band" (drag-select arbitrary rectangular range)
- Fill
- Positioning
- Auto adjust grid size to window
- User can manually adjust grid size
- User can drag grid around
- Keyboard navigation
- mimics Excel/OpenOffice navigation
- Keyboard shortcuts
- mimics Excel/OpenOffice shortcuts, where that doesn't interfere w/ common browser shortcuts
- Cell alignment
- auto-fit to contents
- wrap text
- User preferences
- per-grid
- per-user
- e.g., select which columns are displayed
- Undo
- client-side vs server-side
- Copy/Paste
- Live update
- User permissions
- actions can be made enabled, disabled-visible, disabled-invisible
- actions can be grouped, and those groups can be toggled
- entire grid can be made read-only
- Sort
- client-side vs server-side
- single-sort: asc/desc resortable by clicking column headers (sortable via server or client )
- multi-col sorting
- maintain discrete row order
- sorting set containing mixed datatypes
- sorting w/ int'l chars
- indicate current sort order
- Group
- Search
- free-text, allow wildcard
- optionally constrain search to one column or group of columns
- Filter
- Autofilter (like in Excel)
- Formulas
- lightweight clientside impl
- a "Totals row" is one cheesy initial step
- API for "hardcore" serverside impl
- Conditional row highlighting
- Import
- Export
- Status indicator (loading/saving)
- Focus management
- warn if navigating away and edits not saved
- remove 'pseudo-focus' cell (for keyboard navigation) if document/browser doesn't have focus
- Look 'n feel customization
- e.g. alternating row colors
- implementer can set width and height of headers
- tooltip labels on headers, rows, etc
- "horizon" title bar before the header row
- grid footer area
- "Divider row" within table
- Alternate renderings of data (not regular grid)
- Error handling
- Internationalization/localization
- string/image externalization
- bi-directional text
Use Cases
- The openrecord.org project would like to use the Grid widget, but unfortunately openrecord needs cells that can have multiple values, so if the Grid widget doesn't support that then the openrecord project might need to create a custom version of the Grid widget (maybe a subclass?)
People
- Alex Russell -- Dojo
- Brian Skinner -- Dojo OpenRecord project -- needs a grid widget with support for semi-structured data
- Dustin Machi
- Jesse Kuhnert -- has some grid code already: dtacos.grid.TableDataProvider
- Michael Tildahl (JotSpot) -- working on the next version of the table widget for Jot
- Tim Mansfield (JotSpot) -- made current version of the table widget for Jot
- Tom Trenka -- Dojo / f(m)
- Andy Cavatorta -- written some data grids, looking to help out
- Rogers Reilly -- contributed code from the s-rod example above (in "Links ... Grid Widgets"), also looking to help
Hide quick tip X
Quick Tip: Link to Other Wiki Pages
Use the Link function to link to an existing wiki page, a new wiki page, a document, or a URL.
| |
File |
By |
Size |
Attached |
Ver. |
|