property
- Extending the funtionality of DT_RowId and DT_RowClass, this commit
adds DT_RowData which utalises jQuery's `$().data()` method to set
HTML5 data-* attributes, which can be useful for additional meta data.
- This is some what complimentary to using objects as the data source
where you could just use row().data() to get the data, but this is
effectively an orthogonal way of getting the data and might be useful
for existing Javascript libraries.
- It should be noted that the data-sort and data-filter work I'll be
doing for v1.10 shortly will not interact with this method, that will
be DOM sourced data only, while this is Ajax / Javascript based only.
However, if you do want to use data from this source for filtering /
sorting, its easy to do with `data` - `data: 'DT_RowData.sort'` for
example.
- This fixes issue #45.
- Had split the row details out into its own file a little while back,
since it is 100% self contained now, but hadn't committed the file!
Here is it now.
errors
- A lot of posts in the forum are questions such as "what does the
invalid JSON response" error mean, or "how to fix the unknown
requested parameter error". To address these, rather than having them
answered individually in the forum, I'm going to write a series of
technical notes for DataTables (getting started, how to use columns
etc) and as part of those, each error that DataTables can fire off
will have a technical note explaining in deatil what the error means.
- Example:
DataTables warning: table id=example - Invalid JSON response. For
more information about this error, please see
http://datatables.net/tn/1
- This commit puts the required logic in place. The technical notes
don't exist yet, but they will soon. They will be:
1 - Invalid JSON response
2 - Non-table node initialisation ({this.nodeName})
3 - Cannot reinitialise DataTable
4 - Requested unknown parameter {param} for row {idx}
5 - Unknown paging action: {action}
6 - Possible column misalignment
- The table cannot fit into the current element which
will cause column
- This also has the advantage that the errors in the DataTables code can
be a little smaller. Around 500 bytes saved.
- This fixes issue #173
non-array element
- If found to be something other than an array, it will treat it as if
it were an array with a single element in it, of the value given.
- With the new API that is being introduced in v1.10, the old API
(fnUpdate, fnAddData etc) is being deprecated and retired. It is now a
shim layer calling through the new API, rather than duplicating the
logic of the calls, but is still provided for backwards compatiblity.
- It is _strongly_ recommended that you start to use the new API from
this point in - very certainly for new projects.
- The api() method, is not deprecated, it is new in 1.10 and provides a
way to get access to a DataTables API instance from the jQuery host
object, if the table is initlaised with `dataTable()` (rather than
`DataTable()` which does give you the API instance. It has a single
option which is used by the old API's shim layer to allow it to use
the iApiIndex option to get the context to be used.
- There were two functions called _fnGetRowData, which were conflicting
- The $().map doesn't execute with the scope of the element, need to
pass the element through to the get data function correctly.
- The row()/rows() methods have index methods, so it makes sense that
the column(s) and cell(s) methods also have index methods to get the
raw information out of the table. Rather than shying away from the
indexes in 1.10, as has been done with the pervious versions of
DataTables, 1.10 will embrase them as first class citizens.
- New methods:
- columns().index()
- column().index()
- cells().index()
- cell().index()
- It is possible at the moment to use rows().data() to get the data for
the table, you can use rows().data( { order: 'index' } ); to get the
data in index order - I suspect a reasonably common use when working
with the data set (at least, I use it that way!) and its a but clumsy
to write that way, particularly compared to the old fnGetData method.
So the new data() method is a short cut for `rows().data( { order:
'index' } ).flatten()` to get the data set for the host table(s).
- For consistency and completeness, the cell() and cells() methods now
accept their own cell selector option (rather than just rows and
columns) which is a jQuery selector, or no selector at all for all
cells. Additionally it allows an options object to be passed in, to
allow configuraiton of the order of data etc.
- The cells() method now has these calling options:
- cells() - all cells
- cells( opts ) - option configuration
- cells( selector ) - cell selector
- cells( selector, opts ) - cell selector + options
- cells( rowSelector, columnSelector ) - row + column selector
- cells( rowSelector, columnSelector, opts ) - row + column selector +
opttions
- The cell() method as the same signature.
with newly added rows
- Looking at fnAddData, and about to replace it, I realised that
fnAddData returned the indexes of the newly added row while the new
methods didn't. It makes sense for row.add() to return a row()
extended object with the newly added rows so row().node() etc can be
used. Also the indexes are in the inst, so that information is also
available. Likewise is done for its plural counterpart.
- Did consider creating an `augment` static method for the API, and
might yet do this, but this is the only place to use it at the moment.
Possibly it might be useful for plug-ins, but before adding, lets see
how the new API is used.
with plurality
- There are four groupings of plural / singular methods in the new API:
table(s), row(s), column(s) and cell(s). We need to provide similar
methods for each, often leading to code duplication. To help reduce
this code duplication I've created a new `registerPlural` method which
allows both the singular and plural to be derived from a single
function automatically. The plural form is given and wrapped up by a
container function which extracts a singular return.
- Note that not all singular methods can use this approach, for example
row().data() provides extra functionality over rows().data() in that
it can be used as a setter as well as getter.
- To round off the API, this commit adds a column() method, for working
with a single column, as with row/rows, cell/cells and table/tables.
- New methods:
- column() - Column selector
- column().data() - Get column data
- column().header() - Get the column header cell
- column().visible( set ) - Get / set the column visiblity
- column().order( dir ) - Order the table by this column
- Note that I haven't implemented column().search() yet as I'm sure
there must be a better way of dealing with the singular functions...
Need to look at the four groups a bit more before this (and then the
API :-) ) is finalised
- The columns().data() method was flattening the returned array. While
possibly okay on its own, that doesn't match the behaviour of how
rows().data() works, where each row is an entry in the array, rather
than the array being flattened. As such I've changed columns().data()
to work work in the say way, for each column you select, you get an
entry in the api instance - an array with the data for the that
column.
- To allow for hte fact that some may want to work with the flattened
data, I've added a `flatten()` method to the instance base, which is
basically a shortcut call to `reduce`.
- Now that we have the cells() / cell() methods, with the ability to
select based on column and row, and the ability to get the whole row
or column cells, the TD get methods on row / rows / columns were
redundant and I think should be removed for berevity. It could also
get confusing with the chaining since there are nested and top level
methods with the same name.
- Removed:
- rows().cells()
- row().cells()
- columns().cells()
- New API methods:
- cell().invalidate() - Invalidate a single cell
- cells().invalidate() - Invalidate multiple cells
- Note that the invalidation is actually row based, rather than cell
based - i.e. the whole row is invalidated. This may change in future
versions of DataTables, but I'm concerned that it would add a lot of
code for little enhancement.
- New API methods:
- cells( rowSelector, columnSelector, opts ) - Cell selector
- cells( ... ).nodes() - Get the nodes for the selected cells
- cells( ... ).data() - Get the data for the selected cells
- cell( rowSelector, columnSelector, opts ) - Single cell selector
- cell( ... ).node() - Get the cell node
- cell( ... ).data() - Get the cell data
- There was a bug in `_selector_first` whereby it wasn't correctly
reducing the set - was gatting away with it before, because it was
reducing to a single element array, which has a toString() method
which allowed it to appear to work for integers.
- New API methods:
- table() - select a single table
- table().node() - get the table node for the table
- To be honest, these methods are not likely to be used particuarly
often, so I think they are fairly low priority, but they could provide
useful, and it is a public way to get the table node.
- New API methods:
- rows().invalidate() - Invalidate the matched rows
- row().invalidate() - Invalidate the matched row
- row().data( set ) - Set the data to use for the matched row
- This involves building upon the invalidation work done in the last few
commits and creating an invalidation function. This new function will
mark the cached data as invalid for re-reading by the sort and
filtering methods (this will need to be abstracted into modules in
1.11, but there is no infrastructure for that yet - that's what 1.11
is all about). Additionally the invalidation method will update either
the data held by DataTables (read from the DOM), or update the DOM if
the data source was not the DOM. A flag allows an override to state
the direction, although I think that generally speaking you might not
want to use the override (you might nuke parts of your data source
object if you read from the dom for example).
- Like sorting, for the new API we need to be able to invalidate data
held for filtering in a fairly simple manner (it could be done before,
but it was messy, see fnUpdate - you need to call the methods in the
parent function, rather than just invalidating). This commit adds that
ability to DataTables.
- Performance improvements:
- The big one is that filtering data is only obtained and formatted
when invalidated, rather than every full filter now.
- Regular expressions for newline and HTML matching are variables,
rather than redefined on every call.
- DIV for reading text version of an HTML formatted string is a
variable, rather than being recreated on every call.
- Type based formatters have been moved into the extension API ('string'
and 'html'). They can be overridden there if wanted. Allows
simplication of the call for the formatter.
- Fixes issue #158 as part of the refactoring.
- Smaller by 22 bytes (compressed)... Likely once invalidation is fully
implemented that will be swallowed up...
- Refactoring _fnSortingClasses to be more efficient in how it operates
and to compress better. This is done by looping first over the
elements to have their classes removed, and then looping over only
those to have them added. Previous all columns were operated upon.
Also using _pluck and that fact that all cells fromt he tbody are
stored makes the code much smaller, more readable and compressable.
Only 0.5KiB saved in the refactor, but every little helps...
- Restored column sorting classes functionality that had been disabled
earlier in the 1.10 development sequence.
- Think this code was in DataTables 1.0 and has been relatively
untouched! A refactor allows it to be more readable and smaller when
compressed (about 450 bytes saved)
- invalidation is going to play an important part in the new API, with
the ability to invalid the cached data for sorting, filtering, display
etc so we need to be able tos upport this in the core.
- In fairness the sorting didn't actually need invalidation because it
would always get data on every sort, which is bad for performance -
proper invalidation and caching will resolve this. Which is what has
been implemented here.
- I had expected (hoped) to be able to save a bit of space in the
refactor, but only aorund 100 bytes (compressed) saved, which will
probably be lost when the invalidation is fully implemented in the
API. Still, better performance, tidier code, and no extra space...
Fix: Sorting classes now show multi column sorting when a column is
defined to sort over multiple columns (sortData). Previously it would
only show the first column.
- Two new methods for the new API to allow new data (rows) to be added
to the table.
- row.add() - Add a single row to the table. object, array, jQuery
object or TR node can be passed in.
- rows.add() - Add one or more rows to the table from a source array.
An array or jQuery object must be passed in, containing objects,
arrays, or TR nodes (or any combination thereof).
- Should be noted that this is iterated over all tables in the current
API context, so care should be taken when adding a node to multiple
tables, since it will be moved between them. Equally, when adding
data, the original object reference is retained, so changing it in one
table will change it in all!
- These two methods effectively replace fnAddData from the old API.
fnAddData had a few issues with distingusihing a multiple row add and
a single row add, since arrays could be used for both (indeed, it
simply couldn't cope with something like using a single integer as
reference for a data object, which can now be done in 1.10). The two
new methods sidestep this problem by providing one method for multiple
row add, and another for single row add - the developer needs to know
that the plural has meaning here!
Only call once each to check to see sort ascending / sort descending is is active. (And only check for the descending class if we didn't find the ascending class)
Should also lead to smaller minified code.
- Addition of a destroy method for the new API, effectively replacing
fnDestroy from the old API.
- The functionality is identical to fnDestroy, but it has been
refactored to make better use of jQuery and allow for better
compression (should be 1/4 - 1/2 KiB saved)
- $ - perform a jQuery selector on the nodes in the table (matching the
$ method from the old API).
- clear - clear the table completely (replaces fnClearTable).
- settings - get an array of the settings objects for the tables used in
the API instance.
- on - jQuery event listener proxy. Use for table specific events
('draw', 'xhr' etc).
- one - jQuery event listener proxy (single event).
- off - jQuery event unlistener proxy.
- Showing and hiding details about a row in a child row is very useful
and proven to be a popular part of DataTables. This commit provides
that ability in the new API and extends it. It also fully modularises
the child rows aspects, so it could be removed from the core without
effecting any other aspects (it may be moved into a seperate file in
future).
- This will effectively replace fnOpen, fnClose and fnIsOpen
- Added methods:
- row( selector, opts ).child()
- row( selector, opts ).child( str, class )
- row( selector, opts ).child( str, class ).show()
- row( selector, opts ).child( str, class ).hide()
- row( selector, opts ).child.show()
- row( selector, opts ).child.hide()
- row( selector, opts ).child.isShown()
- Note that unlike the old API you need to specify the data first, and
then use the show() method to show the child row. This allows the
details rows to be configured before they are actually shown.
- Additionally multiple child rows can be attached to a parent (pass
`str` (from above) as an array to use this feature. API plug-ins could
use this ability to show fully nested tables.
- Not just a string can be passed in now, but also a TR node which will
actually be used (rather than put into a nested row), any other type
of node (which will be inserted into a wrapper row/cell) or a jQuery
object.
- The rows() method allows operations on multiple rows with a single
call, this new singualr option, `row()` performs operations on a
single row, allowing fine grain control and easy access to certain
aspects. For example. `rows().data()` will return an array of data
objects, even if there is only one row as a result of the selector,
while `row().data()` will return the data object directly.
- Impletemented thus far:
- row()
- row().node()
- row().cells()
- row().data() - get only as of yet
- row().index()
- row().remove()
- Previously it was the domain of the filtering caller to update the
global filtering input element (fnFilter or the keypress handler
specifically), but in keeping with the drive towards modularity, it
should be the control itself that updates when needed.
- This is done by listening for the `filter` event from the table and
updating the display as needed. It is a touch less efficent since the
same value might be written as what is already there, but it reduces
code size and complexity.
- Ability to filter the table through the new API.
- This effectively replaces the fnFilter method of the old API.
- Note that one capability which has been removed from the old API is the
ability to not show the new filter on the filtering input elements. I
can't see any use for that feature to be honest, so it has been
dropped. The filtering inputs always show the global filter state now.
- Additionally, note that we've been forced to call this `search` here
rather than `filter` since there is a `filter` method for the API
collection instance. This might be revisted before release.