- okay, now the grid "white flash" is gone: cells are not deleted (DOM removeChild for cells and/or rows) but instead flagged as "dirty"; then when render() comes around, it updates all the "dirty" content via `updateCell()` (which now gets a *lot* more use than before, so we're definitely exercising quite different areas of slickgrid with this new approach).
- okay, now the grid "white flash" is gone: cells are not deleted (DOM removeChild for cells and/or rows) but instead flagged as "dirty"; then when render() comes around, it updates all the "dirty" content via `updateCell()` (which now gets a *lot* more use than before, so we're definitely exercising quite different areas of slickgrid with this new approach).

- the above is still accompanied by cell/row removal when the cells/rows get *outside* the "rendered area" (which is the visible area plus a bit of buffer in all directions); do note that `cleanupRows()` now is the only one who does some real DOM node removal and it's *only* invoked inside `render()` hence DOM nodes for cells and rows stay around while you scroll very fast (you can see this with the current long delay setting happening: move around and the 'activeCell' gets updated every time and all the 'old' activeCells will still be available while scrolling, even while no render() got executed *yet*. This at least cleans up the render/invalidation/update process a bit, so that is gets to be manageable again (see next item though).

- slickgrid risk area: I'm not sure the row/colspanning cells are handled correctly at all times and I must say that the `invalidateRows()` code which addresses the special concerns for those only got worse in terms of complexity. I'll have to test and simplify that chunk if I can, because it was and still is raising the hairs on my head ;-)

- migrated the internal spans cache from array indexed to object for legibility: now colspan is not index `[3]` but `.colspan`, for example (I'm talking about the `{ row, cell, rowspan, colspan }` arrays turned objects here).

- I'm not at all happy with the way ow/colspanning was & is handled, but right now I can't come up with a faster / more efficient approach to these. Imagine having `rowspan=*` columns in a 1 million row grid and working 'at the bottom of it': the current implementation scans all the way back to row=0 to find rowspan overlaps with the active (visible) area. :-(

- added code to the activateCellInternal() function so that we pick up focus and shift it to the slickgrid focusSisnks when the activeCell is nuked (set to NULL): even without the activeCell we still want to get the keyboard events and all, unless userland code specifically takes focus elsewhere! Focus managment is hairy stuff. Hopefully it just got a little *less* hairy with this edit. (I think it does; that focus stack is still in there too, though, while it may be a horrible hack to tracking focus in your entire app from within the confines of a slickgrid instance alone, but at least that focus stack helps us determine if we *lose focus* because the user clicks somewhere else in the page, *outside* the slickgrid $container`... Buggerit, millenium hand & shrimp!

- as part of the "dirty" flagging, invalidateAllRows() doesn't render (update) any cells any more by itself; you'll have to call render() to get any visual updates happening. (This was crap lingering from the old days; now that we have lazy/delayed rendering, those updateCell() calls in there should have died alongside the introduction of that lazy render approach -- now at least you are sure of the basic principle holding: activeCells are rendered immediately and are always present as a DOM node, while the rest of the grid is lazy-rendered and may not exist yet when you get certain slickgrid events. (TODO: trigger a 'render started' + 'render done' event so userland code can easily observe when the render actually kicks in. Also TODO: observe both the *active* cell and the *focused* cell: the two don't necessarily have to be the same: the user can click or otherwise focus another cell, while the visuals keep *another* cell marked as "the active cell"!)

- Also: fixed up the rowHeight comparisons to always properly account for the `cellHeightDiff` value (code review).

- new API: invalidateCell(): now you can have much finer-grained control of grid invalidation/updating from userland code: instead of calling invalidateRow or one of the others, single cell updates should now be followed by a call to `invalidateCell()` (and a call to `render()`) to make slickgrid *only* update that single (invalidated) cell.

- Also note that this approach will not destroy the existing DOM node for that cell but rather *update* it via `updateCell()`, thus allowing certain assumptions in userland code which were not valid before (now existing DOM nodes are flagged as "dirty" on invalidation and then *updated* on `render()`, rather than being removed entirely (`removeChild() for cell and row DOM nodes!) and subsequently regenerated in the `render()` call.

GerHobbelt/SlickGrid,GerHobbelt/SlickGrid,GerHobbelt/SlickGrid