From 7023d3ca2bd605894f9fd3f1825cfd0a4d358d20 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Sun, 5 Jul 2015 17:08:16 +0100 Subject: [PATCH] Use bootstrap grid instead of column-count:3 for aligning checkboxes (fixes #2029) Upgrading to bootstrap 3.3.5 meant that checkboxes inside a div with column-count:3 set would be unclickable in Chrome: in fact, the entire div appears to sit on top of its contents, making interaction impossible. This affected both the 'show folder with these devices' and 'these devices can access this folder' sections of the UI. I'm not sure what the the underlying cause is, but moving to Bootstrap's grid system appears work around the issue. Devices/folders have to be explicitly split out into rows, otherwise the final element appears offset. To do this grouping by row, a new filter (groupFilter) has been added, which turns an input of e.g. [1, 2, 3, 4, 5] with a groupSize of 3 into [[1, 2, 3], [4, 5]]. However altering the collection in this way throws Angular into an infinite watch loop, terminating in infdig. m59peacemaker's pmkr.filterStabilize (MIT) was added to work around this issue. This also has the nice side-effect of wrapping the list of devices/folders when the screen width decreases. See also: - #2027 (bootstrap update which triggered this issue) - #1121 (last time it happened) --- gui/index.html | 27 +++++++++++------- .../syncthing/core/filters/groupFilter.js | 25 +++++++++++++++++ .../core/services/filterStabilize.js | 27 ++++++++++++++++++ .../syncthing/core/services/memoize.js | 28 +++++++++++++++++++ 4 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 gui/scripts/syncthing/core/filters/groupFilter.js create mode 100644 gui/scripts/syncthing/core/services/filterStabilize.js create mode 100644 gui/scripts/syncthing/core/services/memoize.js diff --git a/gui/index.html b/gui/index.html index a2b3fa894..ae5c21031 100755 --- a/gui/index.html +++ b/gui/index.html @@ -601,11 +601,13 @@

Select the folders to share with this device.

-
-
- +
+
+
+ +
@@ -766,11 +768,13 @@

Select the devices to share this folder with.

-
-
- +
+
+
+ +
@@ -1259,9 +1263,12 @@ + + + diff --git a/gui/scripts/syncthing/core/filters/groupFilter.js b/gui/scripts/syncthing/core/filters/groupFilter.js new file mode 100644 index 000000000..d960651df --- /dev/null +++ b/gui/scripts/syncthing/core/filters/groupFilter.js @@ -0,0 +1,25 @@ +/** + * Groups input in chunks of the specified size + * + * E.g. [1, 2, 3, 4, 5] with groupSize = 3 => [[1, 2, 3], [4, 5]] + * Uses pmkr.memoize to avoid infdig, see 'Johnny Hauser's "Filter Stablize" Solution' + * here: http://sobrepere.com/blog/2014/10/14/creating-groupby-filter-angularjs/ + */ +angular.module('syncthing.core') + .filter('group', [ + 'pmkr.filterStabilize', + function (stabilize) { + return stabilize(function(items, groupSize) { + var groups = []; + var inner; + for (var i = 0; i < items.length; i++) { + if (i % groupSize === 0) { + inner = []; + groups.push(inner); + } + inner.push(items[i]); + } + return groups; + }); + } + ]); diff --git a/gui/scripts/syncthing/core/services/filterStabilize.js b/gui/scripts/syncthing/core/services/filterStabilize.js new file mode 100644 index 000000000..7eb31f75e --- /dev/null +++ b/gui/scripts/syncthing/core/services/filterStabilize.js @@ -0,0 +1,27 @@ +/** + * m59peacemaker's filterStabilize + * + * See https://github.com/m59peacemaker/angular-pmkr-components/tree/master/src/services/filterStabilize + * Released under the MIT license + */ +angular.module('syncthing.core') + .factory('pmkr.filterStabilize', [ + 'pmkr.memoize', + function(memoize) { + function service(fn) { + function filter() { + var args = [].slice.call(arguments); + // always pass a copy of the args so that the original input can't be modified + args = angular.copy(args); + // return the `fn` return value or input reference (makes `fn` return optional) + var filtered = fn.apply(this, args) || args[0]; + return filtered; + } + + var memoized = memoize(filter); + return memoized; + + } + return service; + } + ]); diff --git a/gui/scripts/syncthing/core/services/memoize.js b/gui/scripts/syncthing/core/services/memoize.js new file mode 100644 index 000000000..db72e5c0a --- /dev/null +++ b/gui/scripts/syncthing/core/services/memoize.js @@ -0,0 +1,28 @@ +/** + * m59peacemaker's memoize + * + * See https://github.com/m59peacemaker/angular-pmkr-components/tree/master/src/services/memoize + * Released under the MIT license + */ +angular.module('syncthing.core') + .factory('pmkr.memoize', [ + function() { + function service() { + return memoizeFactory.apply(this, arguments); + } + function memoizeFactory(fn) { + var cache = {}; + function memoized() { + var args = [].slice.call(arguments); + var key = JSON.stringify(args); + if (cache.hasOwnProperty(key)) { + return cache[key]; + } + cache[key] = fn.apply(this, arguments); + return cache[key]; + } + return memoized; + } + return service; + } + ]);