mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-09 14:50:56 +00:00
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)
This commit is contained in:
parent
57a5d13c47
commit
7023d3ca2b
@ -601,11 +601,13 @@
|
||||
<div class="form-group">
|
||||
<label translate for="folders">Share Folders With Device</label>
|
||||
<p translate class="help-block">Select the folders to share with this device.</p>
|
||||
<div class="three-columns">
|
||||
<div class="checkbox" ng-repeat="folder in folderList()">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentDevice.selectedFolders[folder.id]"> {{folder.id}}
|
||||
</label>
|
||||
<div class="container-fluid">
|
||||
<div class="row" ng-repeat="folderGroup in folderList() | group:3">
|
||||
<div class="checkbox col-md-4" ng-repeat="folder in folderGroup">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentDevice.selectedFolders[folder.id]"> {{folder.id}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -766,11 +768,13 @@
|
||||
<div class="form-group">
|
||||
<label translate for="devices">Share With Devices</label>
|
||||
<p translate class="help-block">Select the devices to share this folder with.</p>
|
||||
<div class="three-columns">
|
||||
<div class="checkbox" ng-repeat="device in otherDevices()">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentFolder.selectedDevices[device.deviceID]"> {{deviceName(device)}}
|
||||
</label>
|
||||
<div class="container-fluid">
|
||||
<div class="row" ng-repeat="deviceGroup in otherDevices() | group:3">
|
||||
<div class="checkbox col-md-4" ng-repeat="device in deviceGroup">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentFolder.selectedDevices[device.deviceID]"> {{deviceName(device)}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1259,9 +1263,12 @@
|
||||
<script src="scripts/syncthing/core/filters/basenameFilter.js"></script>
|
||||
<script src="scripts/syncthing/core/filters/binaryFilter.js"></script>
|
||||
<script src="scripts/syncthing/core/filters/durationFilter.js"></script>
|
||||
<script src="scripts/syncthing/core/filters/groupFilter.js"></script>
|
||||
<script src="scripts/syncthing/core/filters/naturalFilter.js"></script>
|
||||
<script src="scripts/syncthing/core/filters/lastErrorComponentFilter.js"></script>
|
||||
<script src="scripts/syncthing/core/services/filterStabilize.js"></script>
|
||||
<script src="scripts/syncthing/core/services/localeService.js"></script>
|
||||
<script src="scripts/syncthing/core/services/memoize.js"></script>
|
||||
|
||||
<script src="assets/lang/valid-langs.js"></script>
|
||||
<script src="assets/lang/prettyprint.js"></script>
|
||||
|
25
gui/scripts/syncthing/core/filters/groupFilter.js
Normal file
25
gui/scripts/syncthing/core/filters/groupFilter.js
Normal file
@ -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;
|
||||
});
|
||||
}
|
||||
]);
|
27
gui/scripts/syncthing/core/services/filterStabilize.js
Normal file
27
gui/scripts/syncthing/core/services/filterStabilize.js
Normal file
@ -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;
|
||||
}
|
||||
]);
|
28
gui/scripts/syncthing/core/services/memoize.js
Normal file
28
gui/scripts/syncthing/core/services/memoize.js
Normal file
@ -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;
|
||||
}
|
||||
]);
|
Loading…
Reference in New Issue
Block a user