diff options
author | Vincent Petry <pvince81@owncloud.com> | 2014-02-03 18:00:39 +0100 |
---|---|---|
committer | Vincent Petry <pvince81@owncloud.com> | 2014-02-25 19:37:23 +0100 |
commit | 34d17e61685f479b406bbd300c1d41e35df35cd0 (patch) | |
tree | bbbf501da15a971882ade0258f25eb27b0b06f81 | |
parent | c30377392b0ab0b6fdb2068bcbfe0fe0dea4c3de (diff) | |
download | nextcloud-server-34d17e61685f479b406bbd300c1d41e35df35cd0.tar.gz nextcloud-server-34d17e61685f479b406bbd300c1d41e35df35cd0.zip |
Improve users list scrolling performance
- fixed JS error when avatar mode is disabled
- added spinner at the bottom of the table
- scroll detection now happens earlier
- single/multiselect init is deferred so that the new rows are first appended
into the list (more responsive) and initialized afterwards
- disabled users sorting after add (assuming they are always sorted on
the server side)
-rw-r--r-- | core/css/multiselect.css | 8 | ||||
-rw-r--r-- | core/css/styles.css | 12 | ||||
-rw-r--r-- | settings/js/users.js | 77 |
3 files changed, 72 insertions, 25 deletions
diff --git a/core/css/multiselect.css b/core/css/multiselect.css index e2a35ac3633..0c683ad51c6 100644 --- a/core/css/multiselect.css +++ b/core/css/multiselect.css @@ -48,7 +48,7 @@ ul.multiselectoptions > li input[type='checkbox']:checked+label { font-weight: bold; } -div.multiselect { +div.multiselect, select.multiselect { display: inline-block; max-width: 400px; min-width: 150px; @@ -58,6 +58,12 @@ div.multiselect { vertical-align: bottom; } +/* To make a select look like a multiselect until it's initialized */ +select.multiselect { + height: 30px; + min-width: 113px; +} + div.multiselect.active { background-color: #fff; position: relative; diff --git a/core/css/styles.css b/core/css/styles.css index 3be7bbc3b90..a44780156bd 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -890,3 +890,15 @@ div.crumb:active { opacity:.7; } +.appear { + opacity: 1; + transition: opacity 500ms ease 0s; + -moz-transition: opacity 500ms ease 0s; + -ms-transition: opacity 500ms ease 0s; + -o-transition: opacity 500ms ease 0s; + -webkit-transition: opacity 500ms ease 0s; +} +.appear.transparent { + opacity: 0; +} + diff --git a/settings/js/users.js b/settings/js/users.js index 540b849875b..8b98e5928ad 100644 --- a/settings/js/users.js +++ b/settings/js/users.js @@ -85,19 +85,24 @@ var UserList = { add: function (username, displayname, groups, subadmin, quota, sort) { var tr = $('tbody tr').first().clone(); - if (tr.find('div.avatardiv')){ + var subadminsEl; + var subadminSelect; + var groupsSelect; + if (tr.find('div.avatardiv').length){ $('div.avatardiv', tr).avatar(username, 32); } tr.attr('data-uid', username); tr.attr('data-displayName', displayname); tr.find('td.name').text(username); tr.find('td.displayName > span').text(displayname); - var groupsSelect = $('<select multiple="multiple" class="groupsselect" data-placehoder="Groups" title="' + t('settings', 'Groups') + '"></select>') + + // make them look like the multiselect buttons + // until they get time to really get initialized + groupsSelect = $('<select multiple="multiple" class="groupsselect multiselect button" data-placehoder="Groups" title="' + t('settings', 'Groups') + '"></select>') .attr('data-username', username) .data('user-groups', groups); - tr.find('td.groups').empty(); if (tr.find('td.subadmins').length > 0) { - var subadminSelect = $('<select multiple="multiple" class="subadminsselect" data-placehoder="subadmins" title="' + t('settings', 'Group Admin') + '">') + subadminSelect = $('<select multiple="multiple" class="subadminsselect multiselect button" data-placehoder="subadmins" title="' + t('settings', 'Group Admin') + '">') .attr('data-username', username) .data('user-groups', groups) .data('subadmin', subadmin); @@ -109,11 +114,10 @@ var UserList = { subadminSelect.append($('<option value="' + escapeHTML(group) + '">' + escapeHTML(group) + '</option>')); } }); - tr.find('td.groups').append(groupsSelect); - UserList.applyMultiplySelect(groupsSelect); - if (tr.find('td.subadmins').length > 0) { - tr.find('td.subadmins').append(subadminSelect); - UserList.applyMultiplySelect(subadminSelect); + tr.find('td.groups').empty().append(groupsSelect); + subadminsEl = tr.find('td.subadmins'); + if (subadminsEl.length > 0) { + subadminsEl.append(subadminSelect); } if (tr.find('td.remove img').length === 0 && OC.currentUser !== username) { var rm_img = $('<img class="svg action">').attr({ @@ -139,11 +143,11 @@ var UserList = { } } $(tr).appendTo('tbody'); + if (sort) { UserList.doSort(); } - quotaSelect.singleSelect(); quotaSelect.on('change', function () { var uid = $(this).parent().parent().attr('data-uid'); var quota = $(this).val(); @@ -153,6 +157,16 @@ var UserList = { } }); }); + + // defer init so the user first sees the list appear more quickly + window.setTimeout(function(){ + quotaSelect.singleSelect(); + UserList.applyMultiplySelect(groupsSelect); + if (subadminSelect) { + UserList.applyMultiplySelect(subadminSelect); + } + }, 0); + return tr; }, // From http://my.opera.com/GreyWyvern/blog/show.dml/1671288 alphanum: function(a, b) { @@ -211,26 +225,34 @@ var UserList = { } UserList.updating = true; $.get(OC.Router.generate('settings_ajax_userlist', { offset: UserList.offset, limit: UserList.usersToLoad }), function (result) { + var loadedUsers = 0; + var trs = []; if (result.status === 'success') { //The offset does not mirror the amount of users available, //because it is backend-dependent. For correct retrieval, //always the limit(requested amount of users) needs to be added. - UserList.offset += UserList.usersToLoad; $.each(result.data, function (index, user) { if($('tr[data-uid="' + user.name + '"]').length > 0) { return true; } var tr = UserList.add(user.name, user.displayname, user.groups, user.subadmin, user.quota, false); - if (index === 9) { - $(tr).bind('inview', function (event, isInView, visiblePartX, visiblePartY) { - $(this).unbind(event); - UserList.update(); - }); - } + tr.addClass('appear transparent'); + trs.push(tr); + loadedUsers++; }); if (result.data.length > 0) { UserList.doSort(); } + else { + UserList.noMoreEntries = true; + } + UserList.offset += loadedUsers; + // animate + setTimeout(function() { + for (var i = 0; i < trs.length; i++) { + trs[i].removeClass('transparent'); + } + }, 0); } UserList.updating = false; }); @@ -239,7 +261,7 @@ var UserList = { applyMultiplySelect: function (element) { var checked = []; var user = element.attr('data-username'); - if ($(element).attr('class') === 'groupsselect') { + if ($(element).hasClass('groupsselect')) { if (element.data('userGroups')) { checked = element.data('userGroups'); } @@ -295,7 +317,7 @@ var UserList = { minWidth: 100 }); } - if ($(element).attr('class') === 'subadminsselect') { + if ($(element).hasClass('subadminsselect')) { if (element.data('subadmin')) { checked = element.data('subadmin'); } @@ -330,17 +352,24 @@ var UserList = { minWidth: 100 }); } - } + }, + + _onScroll: function(e) { + if (!!UserList.noMoreEntries) { + return; + } + if ($(window).scrollTop() + $(window).height() > $(document).height() - 500) { + UserList.update(true); + } + }, }; $(document).ready(function () { UserList.doSort(); UserList.availableGroups = $('#content table').data('groups'); - $('tbody tr:last').bind('inview', function (event, isInView, visiblePartX, visiblePartY) { - OC.Router.registerLoadedCallback(function () { - UserList.update(); - }); + OC.Router.registerLoadedCallback(function() { + $(window).scroll(function(e) {UserList._onScroll(e);}); }); $('select[multiple]').each(function (index, element) { |