Closed shaunc closed 9 years ago
In my branch here I've replaced the "hidden" ember-collections with simple slices (which helps with speed)... (no longer working after merge). Thus the body rows from the definition are in order. However, the ones from ember-collection are still an unordered map. Do you have something concrete in mind by " body rows using the same technique as header rows"?
btw -- does getting rid of run.next
in "willInsertElement" actually work for you? I tried and got lots of warnings about modifying properties during render cycle. (EDIT ah -- you still have it in eg-column
)
I think it worked for header and footer but not body. I don't understand the glimmer life cycle yet.
By same as header, I mean a simple each...header-cell with inline-block positioning.
Worth speed testing?
I'll give inline-block a whirl ... let me get merged and at least push a branch so you can see what I'm doing at least. After that I want to dive in to this annoying scrolling problem. For me it already renders faster without the hidden ember-collections in the definitions.
Aha!
I'll start doing the draggable column boundaries
If we can get what we have plus resize columns then we just need tests for a first release
:)
ok -- pushed; now on to scrolling
default headers are broken. investigating
column resize worked first time. The architecture seems to be working.
You can mark a column as resizable: false
age is marked as not resizable in the dummy app
excellent -- pulled and had fund resizing. How is rendering speed for you now?
Much faster. But row ordering is completely broken and some rows have no data in them. Startup speed is slow (about 1 second on my machine to fully render)
Just got booked to do a talk on this component on 10th Sept at Ember London. There's some really interesting techniques in here.
Wow -- great!
I'm working on ordering now. VS startup speed perhaps we should try turning off rendering of display table until definitions have been processed.
Ordering I should be able to get working but won't be ideal. For further improvement make want to derive from ember-collection so we can take advantage of the same map it is using.
hmm. Can we not have a body-row
component which deals with laying out the row so that ember-collection
only deals with row ordering?
I have added and then deleted a body-row
three times. :) ... it doesn't really help the situation. Currently ember-collection
is already only dealing with row ordering. Just that it expects rows to "re-render" when it remaps, and as for me rerendering means taking DOM notes off the shelf from the definition, I also have to put them back on the shelf when I'm done with them -- that is what I'm working on now.
aha - they were dissappearing down the worm-plug-hole?
Yes -- and so the old contents is still there out of order.
I've implemented min and max column widths both in column def and in css. I'm going to make styling behave properly re CSP and then I think rendering rows is the only thing left
Speed-wise -- we'll see how it looks. It could be further improved if (a subclass of) ember-collection moved the nodes itself rather than asking for a rerender.
I wonder if having body-row
makes your problem neater if not easier as it's a clean place to put the wormhole behaviour
I think slightly slow is fine for now - let's build tests once we have a v1 functionality. I'm amazed at how fast this has come together. Liking component-style building
right now I've got it pretty well encapsulated:
The definition cell is responsible for getting node:
getCellElement(rowIndex) {
var element = this.element;
if (element == null || element.childNodes == null) {
return null;
}
var {'_body.offset': offset, '_body.limit': limit } = this.getProperties(
'_body.offset', '_body.limit');
if (rowIndex < offset || rowIndex >= offset + limit) { return null; }
return element.getElementsByClassName('eg-body-cell')[rowIndex - offset];
},
The rendering cell asks for the contents and moves into place
didInsertElement: function() {
this._super.apply(this, arguments);
var source = this.get('column._zones.body.source');
var sourceElement = source.getCellElement(this.get('rowIndex'));
this.moveChildren(sourceElement, this.element);
},
moveChildren: function (source, target) {
if (source == null || target == null) { return; }
while (source.childNodes.length > 0) {
target.appendChild(source.childNodes[0]);
}
}
blue header is defined in dummy app styling to confirm that app can override styling
feels a bit dodgy that the definition cell is dealing with offsets and class names. shouldn't it just grab its entire block?
I'm sorry -- thats not the definition cell. Thats the definition body. Your right that I could break it into two steps -- definition body gets cell component, then cell component gets contents. But currently there is no cell component and as this would be the only logic in it its not so bad I think but can clean up if you like. However, first I have to finish up the "put the nodes back" code.
if you look at how I've done the header,
parentView.set('_column._zones.header.element', this.get('element'));
I'm just grabbing the whole element in the definition
Then eg-render/eg-header-cell
moves its children:
renderHeader: function() {
var header = this.get('_header');
if (header)
{
var sourceElement = header.element;
var destinationElement = this.get('element');
var node = sourceElement.firstChild;
var lastNode = sourceElement.lastChild;
while(node) {
destinationElement.insertBefore(node, null);
node = node !== lastNode ? lastNode.parentNode.firstChild : null;
}
}
},
probably
moveChildren: function (source, target) {
if (source == null || target == null) { return; }
while (source.childNodes.length > 0) {
target.appendChild(source.childNodes[0]);
}
should be in a mixin as the header and footer could reuse the same code
(We would need to add a (say) eg-body/eg-cell ... marginal if you ask me)
mixin: +1
ok, let's review when you're done
ok -- there you go. header looks good. Its still a bit too lazy -- scroll lags behind. Simplest way to fix would probably to draw the table (in a window that blocks view of top and bottom) a few rows larger than it was then put sentinel rows at top and bottom so start and end of table arent obscured.
I'm also very surprised it works so well already. One ceveat is its pointing at my private copy of ember-collection, which has some bug fixes still sitting in a PR. Still very good -- I think you've done a great job filling out the architecture.
Take a look at what I've done. I can put in eg-render/body-row and/or eg-body/eg-cell if you think its worthwhile.
btw -- should we remove eg-render components from app/ as they are not part of the public interface?
one small thing with header drag: how to resize last cell
I tried removing eg-render components, but then they're not found by the resolver. Would be nice to find a way around that.
I forgot about the last cell! Do you think the last cell should fill remaining space? That would make sense in a normal table view. min-width settings would work to make the next column collapse when it reached its limit.
Header resize also lags behind a little - much more than in ember-split-view. I'm not too concerned right now.
list-view had functionality for providing a scroll buffer either side of the visible window. Does ember-collection not have that?
scroll is broken with your new code. First page renders correctly, then nothing else as I scroll down
hmm.. not what I see... perhaps -- can you pull the latest shaunc/ember-collection?
can you change package.json to point to the correct branch?
ah! I see - you've fixed ember-collection since I last npm installed. npm updating...
buffer: it keeps a buffer of old nodes, but tells to rerender just as approaches screen. Arguably a bug.
and our rerender is slow?
I think its rather that ember executes the hooks with a lag
so it's already on screen when the hook kicks in?
yes -- exactly. Is it working for you now? (My son awaits my reading to him :)) Just pushed a small fix to give cells height.
scrolling slowly is fine after update, but fast scroll gives lots of empty rows
Given
We need to render
In the context of the individual row. So:
1) look up contents of "eg-body" for given column 2) render contents in a custom wrapper component
What is relevant "contents of 'eg-body'? The dom nodes aren't sufficient. What we really want is the template (template string)? The question is, is that available?