optimize table render performance by precalculating widths

This commit is contained in:
Felix Niklas 2016-03-15 16:43:49 +01:00
parent af2488f4d7
commit fe3c8d698d
2 changed files with 32 additions and 25 deletions

View file

@ -24,15 +24,15 @@ class App.ControllerTable extends App.Controller
for key, value of data['headerWidth'] for key, value of data['headerWidth']
@headerWidth[key] = value @headerWidth[key] = value
@availableWidth = @el.width()
@render() @render()
$(window).on 'resize.table', @readjustHeaderWidths $(window).on 'resize.table', @onResize
release: => release: =>
$(window).off 'resize.table', @readjustHeaderWidths $(window).off 'resize.table', @onResize
render: => render: =>
@html @tableGen() @html @tableGen()
@readjustHeaderWidths()
if @dndCallback if @dndCallback
dndOptions = dndOptions =
@ -172,7 +172,7 @@ class App.ControllerTable extends App.Controller
# e.g. column: owner # e.g. column: owner
headerFound = true headerFound = true
if @headerWidth[attribute.name] if @headerWidth[attribute.name]
attribute.displayWidth = @headerWidth[attribute.name] attribute.displayWidth = @headerWidth[attribute.name] * @availableWidth
else if !attribute.width else if !attribute.width
attribute.displayWidth = @baseColWidth attribute.displayWidth = @baseColWidth
else else
@ -191,7 +191,7 @@ class App.ControllerTable extends App.Controller
if attributeName is rowWithoutId if attributeName is rowWithoutId
headerFound = true headerFound = true
if @headerWidth[attribute.name] if @headerWidth[attribute.name]
attribute.displayWidth = @headerWidth[attribute.name] attribute.displayWidth = @headerWidth[attribute.name] * @availableWidth
else if !attribute.width else if !attribute.width
attribute.displayWidth = @baseColWidth attribute.displayWidth = @baseColWidth
else else
@ -281,6 +281,8 @@ class App.ControllerTable extends App.Controller
@objects = @objects.concat groupObjects[group] @objects = @objects.concat groupObjects[group]
groupObjects[group] = [] # release old array groupObjects[group] = [] # release old array
@calculateHeaderWidths()
# get content # get content
table = App.view('generic/table')( table = App.view('generic/table')(
table_id: @table_id table_id: @table_id
@ -360,7 +362,6 @@ class App.ControllerTable extends App.Controller
# if we have a personalised table # if we have a personalised table
if @table_id if @table_id
# enable resize column # enable resize column
table.on 'mousedown', '.js-col-resize', @onColResizeMousedown table.on 'mousedown', '.js-col-resize', @onColResizeMousedown
table.on 'click', '.js-col-resize', @stopPropagation table.on 'click', '.js-col-resize', @stopPropagation
@ -404,17 +405,15 @@ class App.ControllerTable extends App.Controller
item: item item: item
container: @container container: @container
adjustHeaderWidths: -> calculateHeaderWidths: ->
if !@headers if !@headers
return return
availableWidth = @el.width() if @availableWidth is 0
@availableWidth = @minTableWidth
if availableWidth is 0
availableWidth = @minTableWidth
widths = @getHeaderWidths() widths = @getHeaderWidths()
shrinkBy = Math.ceil (widths - availableWidth) / @getShrinkableHeadersCount() shrinkBy = Math.ceil (widths - @availableWidth) / @getShrinkableHeadersCount()
# make all cols evenly smaller # make all cols evenly smaller
@headers = _.map @headers, (col) => @headers = _.map @headers, (col) =>
@ -423,11 +422,13 @@ class App.ControllerTable extends App.Controller
return col return col
# give left-over space from rounding to last column to get to 100% # give left-over space from rounding to last column to get to 100%
roundingLeftOver = availableWidth - @getHeaderWidths() roundingLeftOver = @availableWidth - @getHeaderWidths()
# but only if there is something left over (will get negative when there are too many columns for each column to stay in their min width) # but only if there is something left over (will get negative when there are too many columns for each column to stay in their min width)
if roundingLeftOver > 0 if roundingLeftOver > 0
@headers[@headers.length - 1].displayWidth = @headers[@headers.length - 1].displayWidth + roundingLeftOver @headers[@headers.length - 1].displayWidth = @headers[@headers.length - 1].displayWidth + roundingLeftOver
@storeHeaderWidths()
getShrinkableHeadersCount: -> getShrinkableHeadersCount: ->
_.reduce @headers, (memo, col) -> _.reduce @headers, (memo, col) ->
return if col.unresizable then memo else memo+1 return if col.unresizable then memo else memo+1
@ -449,12 +450,24 @@ class App.ControllerTable extends App.Controller
return widths return widths
readjustHeaderWidths: => setHeaderWidths: =>
@adjustHeaderWidths() @calculateHeaderWidths()
@tableHead.each (i, el) => @tableHead.each (i, el) =>
el.style.width = @headers[i].displayWidth + 'px' el.style.width = @headers[i].displayWidth + 'px'
storeHeaderWidths: ->
widths = {}
for header in @headers
widths[header.name] = header.displayWidth / @availableWidth
App.LocalStorage.set(@preferencesStoreKey(), { headerWidth: widths }, @Session.get('id'))
onResize: =>
@availableWidth = @el.width()
@setHeaderWidths()
stopPropagation: (event) -> stopPropagation: (event) ->
event.stopPropagation() event.stopPropagation()
@ -488,18 +501,12 @@ class App.ControllerTable extends App.Controller
# switch to percentage # switch to percentage
resizeBaseWidth = @resizeTargetLeft.parents('table').width() resizeBaseWidth = @resizeTargetLeft.parents('table').width()
leftWidth = @resizeTargetLeft.width() leftWidth = @resizeTargetLeft.width() / resizeBaseWidth
rightWidth = @resizeTargetRight.width() rightWidth = @resizeTargetRight.width() / resizeBaseWidth
leftColumnKey = @resizeTargetLeft.attr('data-column-key') leftColumnKey = @resizeTargetLeft.attr('data-column-key')
rightColumnKey = @resizeTargetRight.attr('data-column-key') rightColumnKey = @resizeTargetRight.attr('data-column-key')
# save table changed widths
storeColWidths = [
{ key: leftColumnKey, width: leftWidth }
{ key: rightColumnKey, width: rightWidth }
]
# update store and runtime @headerWidth # update store and runtime @headerWidth
@preferencesStore('headerWidth', leftColumnKey, leftWidth) @preferencesStore('headerWidth', leftColumnKey, leftWidth)
_.find(@headers, (column) -> column.name is leftColumnKey).displayWidth = leftWidth _.find(@headers, (column) -> column.name is leftColumnKey).displayWidth = leftWidth
@ -543,4 +550,4 @@ class App.ControllerTable extends App.Controller
data data
preferencesStoreKey: => preferencesStoreKey: =>
"tablePreferences:#{@table_id}" "tablePrefs:#{@table_id}"

View file

@ -56,7 +56,7 @@
<td class="table-draggable"><%- @Icon('draggable') %></td> <td class="table-draggable"><%- @Icon('draggable') %></td>
<% end %> <% end %>
<% if @checkbox: %> <% if @checkbox: %>
<td class="table-checkbox"> <td class="table-checkbox js-checkbox-field">
<label class="checkbox-replacement"> <label class="checkbox-replacement">
<input type="checkbox" value="<%= object.id %>" name="bulk"> <input type="checkbox" value="<%= object.id %>" name="bulk">
<%- @Icon('checkbox', 'icon-unchecked') %> <%- @Icon('checkbox', 'icon-unchecked') %>