Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for inline div w/ SelectionMixin #10

Closed
leepfrog opened this issue Jan 1, 2013 · 6 comments
Closed

Support for inline div w/ SelectionMixin #10

leepfrog opened this issue Jan 1, 2013 · 6 comments

Comments

@leepfrog
Copy link
Contributor

leepfrog commented Jan 1, 2013

It would be a great if you could support adding a div underneath the selected row for the SelectionMixin. I've attached an image to give you an idea of what that might be used for.
Screen Shot 2012-12-31 at 9 18 55 PM

@ppong
Copy link
Contributor

ppong commented Jan 1, 2013

@leepfrog can you elaborate on that a little more. Do you mean attaching a div underneath the selected song "There's no secrets this year"?

@leepfrog
Copy link
Contributor Author

leepfrog commented Jan 1, 2013

@ppong correct. Right now i'm able to do it with a bit of trickery:

table-row.handlebars

{{view Ember.MultiItemViewCollectionView rowBinding="view.row" contentBinding="view.columns" itemViewClassField="tableCellViewClass" widthBinding="controller._tableColumnsWidth"}}

{{if view.row.selected'}}
  <!-- expand content -->
{{/if}}

Then i'm using css transforms to push the cell content down:

css

.table-row.selected ~ .table-row { @include translateY(400px); }

There's a little bit of glitchyness with this, but it works. It would be better if we could have rowHeight set per row.

@ppong
Copy link
Contributor

ppong commented Jan 1, 2013

@leepfrog being able to set rowHeight per row is difficult because of the lazy row rendering. Current the rowHeight is the same for each row and the top offset of a row view is calculated as rowIndex * rowHeight. However, if rowHeight varies for each row, then the calculation becomes more complicated.

If you just want to expand the height of the selected row, I think this shouldn't be too bad... I will see if I could come up with an example for this. However, solving this for the general case will probably need more thoughts...

@Leooo
Copy link

Leooo commented Mar 16, 2015

For the ember 1.10 branch, a dirty hack below to be able to expand one line when hovering:

Ember.Table.TableRow.reopen({
  forceHeight: null,
  forceTop:null,
  height: Ember.computed(function() {
    return (this.forceHeight==null) ? this.tableComponent.rowHeight : this.forceHeight;
  }).property('forceHeight','tableComponent.rowHeight'),
  heightObserver: function(){
    var height=this.get('height');
    this.get('childViews')[0].forEach(function(view){
      view.set('height',height);
      view.set('lineHeight',height);
    });
  }.observes('height'),
  getViewForEvent: function(event) {
    var $rowView, view;
    $rowView = $(event.target).closest('.ember-table-table-row');
    view = Ember.View.views[$rowView.attr('id')];
    if (view) {
      return view;
    }
  },
  getNextRowViews: function(itemIndex) {
    var $rowView, view;
    $rowViews = $('.ember-table-table-row');
    var arr=Ember.A();
    $rowViews.each(function(){
      var view = Ember.View.views[$(this).attr('id')];
      if (view.get('itemIndex')>itemIndex) {
        arr.pushObject(view);
      }
    });
    return arr;
  },
  mouseEnter: function(event) {
    var row_view = this.getViewForEvent(event);
    var $rowView=$(event.target).closest('.ember-table-table-row');
    if (!$rowView.closest(".ember-table-body-container").length) return;
    if (Ember.isEmpty(row_view)) return;
    var itemIndex=row_view.get('itemIndex');
    var nextViews=this.getNextRowViews(itemIndex);
    if (row_view.get('forceHeight')!=null) return;
    $rowView.css("height","auto");
    $rowView.find(".ember-table-cell").css("height","auto");
    var new_height=$rowView.height();
    row_view.set('forceHeight',new_height);
    nextViews.forEach(function(view){
      view.set('forceTop',new_height-view.get('rowHeight'));
    });
    this._super(event);
  },
  mouseLeave: function(event) {
    var row_view = this.getViewForEvent(event);
    var $rowView=$(event.target).closest('.ember-table-table-row');
    if (!$rowView.closest(".ember-table-body-container").length) return;
    if (Ember.isEmpty(row_view)) return;
    var itemIndex=row_view.get('itemIndex');
    var nextViews=this.getNextRowViews(itemIndex);
    if (row_view.get('forceHeight')==null) return;
    row_view.set('forceHeight',null);
    var new_height=null;
    nextViews.forEach(function(view){
      view.set('forceTop',null);
    });
    this._super(event);
  }
});

Ember.LazyItemView.reopen({
  top: Ember.computed(function() {
    var my_top=this.get('itemIndex') * this.get('rowHeight');
    if (this.forceTop!=null) my_top+=this.forceTop;
    return my_top;
  }).property('forceTop','itemIndex', 'rowHeight')
});

Ember.Table.TableCell.reopen({
  styleBindings: ['width','height','lineHeight'],
  height: Ember.computed(function() {
    var row=this.get('parentView').get('parentView');
    var height=row.get('height');
    return height;
  }).property('parentView.parentView'),
  lineHeight:Ember.computed.alias('height')
});

Ideally, to be able to display rows with different heights, it would seem more natural to use table, table-row and table-cell displays with position: relative for the rows. But the way it is structured now (re-using html static elements childView in ViewPortDidChange and changing only the content and the top position) forbids to switch to position: relative (top rows couldn't be switched from the top to the bottom).

Is there a fundamental reason why it is structured that way? i.e: would it be too slow to remove first rows html / add new html at the bottom of the table when scrolling down instead of keeping the row and changing it's content? I suspect it is the case, otherwise it would avoid the obligation to calculate each position through this.get('itemIndex') * this.get('rowHeight'). We could detect when to display a new row when a loader at the bottom gets visible, for example with sthg like:

function isBelowView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();
    return (elemTop > docViewBottom);
}

?

@azirbel
Copy link
Contributor

azirbel commented Mar 17, 2015

That's a good question. Probably you can find more information at https://github.com/emberjs/list-view, which Ember Table is based on.

billy-addepar added a commit that referenced this issue Sep 15, 2017
In current behavior, we have root of linked list tree as an element to display in the table. This assumes that the table has one row that is the ancestor of every other row and this is how the demo app mocks its data.

However, in many table, we do not have one row at the top level but multiple rows at top level. To handle this case, we should have a root node that's the parent of all top level row but does not display in the table. This PR adds a virtual root to the linked list tree to support that.
@billy-addepar
Copy link
Contributor

This version of Ember table is no longer supported. If you want to continue discussion, you can open the issue on Ember Table Legacy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

5 participants