gui: Backport angular and angular-translate updates from master

This commit is contained in:
Jakob Borg 2016-05-06 15:35:30 +02:00
parent 94c6110f2e
commit c0abde3157
8 changed files with 24096 additions and 58 deletions

View File

@ -582,9 +582,9 @@
<!-- vendor scripts -->
<script src="vendor/jquery/jquery-2.0.3.min.js"></script>
<script src="vendor/angular/angular.min.js"></script>
<script src="vendor/angular/angular-translate.min.js"></script>
<script src="vendor/angular/angular-translate-loader.min.js"></script>
<script src="vendor/angular/angular.js"></script>
<script src="vendor/angular/angular-translate.js"></script>
<script src="vendor/angular/angular-translate-loader-static-files.js"></script>
<script src="vendor/angular/angular-dirPagination.js"></script>
<script src="vendor/bootstrap/js/bootstrap.min.js"></script>
<!-- / vendor scripts -->

View File

@ -53,6 +53,7 @@ syncthing.config(function ($httpProvider, $translateProvider, LocaleServiceProvi
// language and localisation
$translateProvider.useSanitizeValueStrategy('escape');
$translateProvider.useStaticFilesLoader({
prefix: 'assets/lang/lang-',
suffix: '.json'

6
gui/default/vendor/angular/README.md vendored Normal file
View File

@ -0,0 +1,6 @@
The files contained herein are:
- angular 1.2.9
- angular-translate 2.9.0.1
- angular-translate-loader-static-files 2.11.0
- angular-dirPagination 759009c

View File

@ -25,15 +25,7 @@
/**
* Module
*/
var module;
try {
module = angular.module(moduleName);
} catch(err) {
// named module does not exist, so create one
module = angular.module(moduleName, []);
}
module
angular.module(moduleName, [])
.directive('dirPaginate', ['$compile', '$parse', 'paginationService', dirPaginateDirective])
.directive('dirPaginateNoCompile', noCompileDirective)
.directive('dirPaginationControls', ['paginationService', 'paginationTemplate', dirPaginationControlsDirective])
@ -47,16 +39,17 @@
return {
terminal: true,
multiElement: true,
priority: 100,
compile: dirPaginationCompileFn
};
function dirPaginationCompileFn(tElement, tAttrs){
var expression = tAttrs.dirPaginate;
// regex taken directly from https://github.com/angular/angular.js/blob/master/src/ng/directive/ngRepeat.js#L211
var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
// regex taken directly from https://github.com/angular/angular.js/blob/v1.4.x/src/ng/directive/ngRepeat.js#L339
var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
var filterPattern = /\|\s*itemsPerPage\s*:[^|]*/;
var filterPattern = /\|\s*itemsPerPage\s*:\s*(.*\(\s*\w*\)|([^\)]*?(?=\s+as\s+))|[^\)]*)/;
if (match[2].match(filterPattern) === null) {
throw 'pagination directive: the \'itemsPerPage\' filter must be set.';
}
@ -75,6 +68,9 @@
// Now that we have access to the `scope` we can interpolate any expression given in the paginationId attribute and
// potentially register a new ID if it evaluates to a different value than the rawId.
var paginationId = $parse(attrs.paginationId)(scope) || attrs.paginationId || DEFAULT_ID;
// In case rawId != paginationId we deregister using rawId for the sake of general cleanliness
// before registering using paginationId
paginationService.deregisterInstance(rawId);
paginationService.registerInstance(paginationId);
var repeatExpression = getRepeatExpression(expression, paginationId);
@ -96,17 +92,25 @@
}
});
} else {
paginationService.setAsyncModeFalse(paginationId);
scope.$watchCollection(function() {
return collectionGetter(scope);
}, function(collection) {
if (collection) {
paginationService.setCollectionLength(paginationId, collection.length);
var collectionLength = (collection instanceof Array) ? collection.length : Object.keys(collection).length;
paginationService.setCollectionLength(paginationId, collectionLength);
}
});
}
// Delegate to the link function returned by the new compilation of the ng-repeat
compiled(scope);
// When the scope is destroyed, we make sure to remove the reference to it in paginationService
// so that it can be properly garbage collected
scope.$on('$destroy', function destroyDirPagination() {
paginationService.deregisterInstance(paginationId);
});
};
}
@ -123,7 +127,7 @@
idDefinedInFilter = !!expression.match(/(\|\s*itemsPerPage\s*:[^|]*:[^|]*)/);
if (paginationId !== DEFAULT_ID && !idDefinedInFilter) {
repeatExpression = expression.replace(/(\|\s*itemsPerPage\s*:[^|]*)/, "$1 : '" + paginationId + "'");
repeatExpression = expression.replace(/(\|\s*itemsPerPage\s*:\s*[^|\s]*)/, "$1 : '" + paginationId + "'");
} else {
repeatExpression = expression;
}
@ -154,7 +158,7 @@
*/
function addNoCompileAttributes(tElement) {
angular.forEach(tElement, function(el) {
if (el.nodeType === Node.ELEMENT_NODE) {
if (el.nodeType === 1) {
angular.element(el).attr('dir-paginate-no-compile', true);
}
});
@ -166,7 +170,7 @@
*/
function removeTemporaryAttributes(element) {
angular.forEach(element, function(el) {
if (el.nodeType === Node.ELEMENT_NODE) {
if (el.nodeType === 1) {
angular.element(el).removeAttr('dir-paginate-no-compile');
}
});
@ -188,8 +192,11 @@
if (attrs.currentPage) {
currentPageGetter = $parse(attrs.currentPage);
} else {
// if the current-page attribute was not set, we'll make our own
var defaultCurrentPage = paginationId + '__currentPage';
// If the current-page attribute was not set, we'll make our own.
// Replace any non-alphanumeric characters which might confuse
// the $parse service and give unexpected results.
// See https://github.com/michaelbromley/angularUtils/issues/233
var defaultCurrentPage = (paginationId + '__currentPage').replace(/\W/g, '_');
scope[defaultCurrentPage] = 1;
currentPageGetter = $parse(defaultCurrentPage);
}
@ -210,26 +217,41 @@
}
function dirPaginationControlsTemplateInstaller($templateCache) {
$templateCache.put('angularUtils.directives.dirPagination.template', '<ul class="pagination" ng-if="1 < pages.length"><li ng-if="boundaryLinks" ng-class="{ disabled : pagination.current == 1 }"><a href="" ng-click="setCurrent(1)">&laquo;</a></li><li ng-if="directionLinks" ng-class="{ disabled : pagination.current == 1 }"><a href="" ng-click="setCurrent(pagination.current - 1)">&lsaquo;</a></li><li ng-repeat="pageNumber in pages track by $index" ng-class="{ active : pagination.current == pageNumber, disabled : pageNumber == \'...\' }"><a href="" ng-click="setCurrent(pageNumber)">{{ pageNumber }}</a></li><li ng-if="directionLinks" ng-class="{ disabled : pagination.current == pagination.last }"><a href="" ng-click="setCurrent(pagination.current + 1)">&rsaquo;</a></li><li ng-if="boundaryLinks" ng-class="{ disabled : pagination.current == pagination.last }"><a href="" ng-click="setCurrent(pagination.last)">&raquo;</a></li></ul>');
$templateCache.put('angularUtils.directives.dirPagination.template', '<ul class="pagination" ng-if="1 < pages.length || !autoHide"><li ng-if="boundaryLinks" ng-class="{ disabled : pagination.current == 1 }"><a href="" ng-click="setCurrent(1)">&laquo;</a></li><li ng-if="directionLinks" ng-class="{ disabled : pagination.current == 1 }"><a href="" ng-click="setCurrent(pagination.current - 1)">&lsaquo;</a></li><li ng-repeat="pageNumber in pages track by tracker(pageNumber, $index)" ng-class="{ active : pagination.current == pageNumber, disabled : pageNumber == \'...\' || ( ! autoHide && pages.length === 1 ) }"><a href="" ng-click="setCurrent(pageNumber)">{{ pageNumber }}</a></li><li ng-if="directionLinks" ng-class="{ disabled : pagination.current == pagination.last }"><a href="" ng-click="setCurrent(pagination.current + 1)">&rsaquo;</a></li><li ng-if="boundaryLinks" ng-class="{ disabled : pagination.current == pagination.last }"><a href="" ng-click="setCurrent(pagination.last)">&raquo;</a></li></ul>');
}
function dirPaginationControlsDirective(paginationService, paginationTemplate) {
var numberRegex = /^\d+$/;
return {
var DDO = {
restrict: 'AE',
templateUrl: function(elem, attrs) {
return attrs.templateUrl || paginationTemplate.getPath();
},
scope: {
maxSize: '=?',
onPageChange: '&?',
paginationId: '=?'
paginationId: '=?',
autoHide: '=?'
},
link: dirPaginationControlsLinkFn
};
// We need to check the paginationTemplate service to see whether a template path or
// string has been specified, and add the `template` or `templateUrl` property to
// the DDO as appropriate. The order of priority to decide which template to use is
// (highest priority first):
// 1. paginationTemplate.getString()
// 2. attrs.templateUrl
// 3. paginationTemplate.getPath()
var templateString = paginationTemplate.getString();
if (templateString !== undefined) {
DDO.template = templateString;
} else {
DDO.templateUrl = function(elem, attrs) {
return attrs.templateUrl || paginationTemplate.getPath();
};
}
return DDO;
function dirPaginationControlsLinkFn(scope, element, attrs) {
// rawId is the un-interpolated value of the pagination-id attribute. This is only important when the corresponding dir-paginate directive has
@ -240,10 +262,13 @@
if (!paginationService.isRegistered(paginationId) && !paginationService.isRegistered(rawId)) {
var idMessage = (paginationId !== DEFAULT_ID) ? ' (id: ' + paginationId + ') ' : ' ';
throw 'pagination directive: the pagination controls' + idMessage + 'cannot be used without the corresponding pagination directive.';
if (window.console) {
console.warn('Pagination directive: the pagination controls' + idMessage + 'cannot be used without the corresponding pagination directive, which was not found at link time.');
}
}
if (!scope.maxSize) { scope.maxSize = 9; }
scope.autoHide = scope.autoHide === undefined ? true : scope.autoHide;
scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : true;
scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : false;
@ -259,8 +284,17 @@
total: 1
};
scope.$watch('maxSize', function(val) {
if (val) {
paginationRange = Math.max(scope.maxSize, 5);
generatePagination();
}
});
scope.$watch(function() {
return (paginationService.getCollectionLength(paginationId) + 1) * paginationService.getItemsPerPage(paginationId);
if (paginationService.isRegistered(paginationId)) {
return (paginationService.getCollectionLength(paginationId) + 1) * paginationService.getItemsPerPage(paginationId);
}
}, function(length) {
if (0 < length) {
generatePagination();
@ -268,7 +302,9 @@
});
scope.$watch(function() {
return (paginationService.getItemsPerPage(paginationId));
if (paginationService.isRegistered(paginationId)) {
return (paginationService.getItemsPerPage(paginationId));
}
}, function(current, previous) {
if (current != previous && typeof previous !== 'undefined') {
goToPage(scope.pagination.current);
@ -276,7 +312,9 @@
});
scope.$watch(function() {
return paginationService.getCurrentPage(paginationId);
if (paginationService.isRegistered(paginationId)) {
return paginationService.getCurrentPage(paginationId);
}
}, function(currentPage, previousPage) {
if (currentPage != previousPage) {
goToPage(currentPage);
@ -284,35 +322,54 @@
});
scope.setCurrent = function(num) {
if (isValidPageNumber(num)) {
if (paginationService.isRegistered(paginationId) && isValidPageNumber(num)) {
num = parseInt(num, 10);
paginationService.setCurrentPage(paginationId, num);
}
};
/**
* Custom "track by" function which allows for duplicate "..." entries on long lists,
* yet fixes the problem of wrongly-highlighted links which happens when using
* "track by $index" - see https://github.com/michaelbromley/angularUtils/issues/153
* @param id
* @param index
* @returns {string}
*/
scope.tracker = function(id, index) {
return id + '_' + index;
};
function goToPage(num) {
if (isValidPageNumber(num)) {
if (paginationService.isRegistered(paginationId) && isValidPageNumber(num)) {
var oldPageNumber = scope.pagination.current;
scope.pages = generatePagesArray(num, paginationService.getCollectionLength(paginationId), paginationService.getItemsPerPage(paginationId), paginationRange);
scope.pagination.current = num;
updateRangeValues();
// if a callback has been set, then call it with the page number as an argument
// if a callback has been set, then call it with the page number as the first argument
// and the previous page number as a second argument
if (scope.onPageChange) {
scope.onPageChange({ newPageNumber : num });
scope.onPageChange({
newPageNumber : num,
oldPageNumber : oldPageNumber
});
}
}
}
function generatePagination() {
var page = parseInt(paginationService.getCurrentPage(paginationId)) || 1;
scope.pages = generatePagesArray(page, paginationService.getCollectionLength(paginationId), paginationService.getItemsPerPage(paginationId), paginationRange);
scope.pagination.current = page;
scope.pagination.last = scope.pages[scope.pages.length - 1];
if (scope.pagination.last < scope.pagination.current) {
scope.setCurrent(scope.pagination.last);
} else {
updateRangeValues();
if (paginationService.isRegistered(paginationId)) {
var page = parseInt(paginationService.getCurrentPage(paginationId)) || 1;
scope.pages = generatePagesArray(page, paginationService.getCollectionLength(paginationId), paginationService.getItemsPerPage(paginationId), paginationRange);
scope.pagination.current = page;
scope.pagination.last = scope.pages[scope.pages.length - 1];
if (scope.pagination.last < scope.pagination.current) {
scope.setCurrent(scope.pagination.last);
} else {
updateRangeValues();
}
}
}
@ -321,15 +378,16 @@
* template to display the current page range, e.g. "showing 21 - 40 of 144 results";
*/
function updateRangeValues() {
var currentPage = paginationService.getCurrentPage(paginationId),
itemsPerPage = paginationService.getItemsPerPage(paginationId),
totalItems = paginationService.getCollectionLength(paginationId);
if (paginationService.isRegistered(paginationId)) {
var currentPage = paginationService.getCurrentPage(paginationId),
itemsPerPage = paginationService.getItemsPerPage(paginationId),
totalItems = paginationService.getCollectionLength(paginationId);
scope.range.lower = (currentPage - 1) * itemsPerPage + 1;
scope.range.upper = Math.min(currentPage * itemsPerPage, totalItems);
scope.range.total = totalItems;
scope.range.lower = (currentPage - 1) * itemsPerPage + 1;
scope.range.upper = Math.min(currentPage * itemsPerPage, totalItems);
scope.range.total = totalItems;
}
}
function isValidPageNumber(num) {
return (numberRegex.test(num) && (0 < num && num <= scope.pagination.last));
}
@ -421,7 +479,7 @@
}
var end;
var start;
if (collection instanceof Array) {
if (angular.isObject(collection)) {
itemsPerPage = parseInt(itemsPerPage) || 9999999999;
if (paginationService.isAsyncMode(paginationId)) {
start = 0;
@ -431,13 +489,43 @@
end = start + itemsPerPage;
paginationService.setItemsPerPage(paginationId, itemsPerPage);
return collection.slice(start, end);
if (collection instanceof Array) {
// the array just needs to be sliced
return collection.slice(start, end);
} else {
// in the case of an object, we need to get an array of keys, slice that, then map back to
// the original object.
var slicedObject = {};
angular.forEach(keys(collection).slice(start, end), function(key) {
slicedObject[key] = collection[key];
});
return slicedObject;
}
} else {
return collection;
}
};
}
/**
* Shim for the Object.keys() method which does not exist in IE < 9
* @param obj
* @returns {Array}
*/
function keys(obj) {
if (!Object.keys) {
var objKeys = [];
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
objKeys.push(i);
}
}
return objKeys;
} else {
return Object.keys(obj);
}
}
/**
* This service allows the various parts of the module to communicate and stay in sync.
*/
@ -455,6 +543,10 @@
}
};
this.deregisterInstance = function(instanceId) {
delete instances[instanceId];
};
this.isRegistered = function(instanceId) {
return (typeof instances[instanceId] !== 'undefined');
};
@ -493,6 +585,10 @@
instances[instanceId].asyncMode = true;
};
this.setAsyncModeFalse = function(instanceId) {
instances[instanceId].asyncMode = false;
};
this.isAsyncMode = function(instanceId) {
return instances[instanceId].asyncMode;
};
@ -504,15 +600,33 @@
function paginationTemplateProvider() {
var templatePath = 'angularUtils.directives.dirPagination.template';
var templateString;
/**
* Set a templateUrl to be used by all instances of <dir-pagination-controls>
* @param {String} path
*/
this.setPath = function(path) {
templatePath = path;
};
/**
* Set a string of HTML to be used as a template by all instances
* of <dir-pagination-controls>. If both a path *and* a string have been set,
* the string takes precedence.
* @param {String} str
*/
this.setString = function(str) {
templateString = str;
};
this.$get = function() {
return {
getPath: function() {
return templatePath;
},
getString: function() {
return templateString;
}
};
};

View File

@ -0,0 +1,107 @@
/*!
* angular-translate - v2.11.0 - 2016-03-20
*
* Copyright (c) 2016 The angular-translate team, Pascal Precht; Licensed MIT
*/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module unless amdModuleId is set
define([], function () {
return (factory());
});
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
} else {
factory();
}
}(this, function () {
$translateStaticFilesLoader.$inject = ['$q', '$http'];
angular.module('pascalprecht.translate')
/**
* @ngdoc object
* @name pascalprecht.translate.$translateStaticFilesLoader
* @requires $q
* @requires $http
*
* @description
* Creates a loading function for a typical static file url pattern:
* "lang-en_US.json", "lang-de_DE.json", etc. Using this builder,
* the response of these urls must be an object of key-value pairs.
*
* @param {object} options Options object, which gets prefix, suffix and key.
*/
.factory('$translateStaticFilesLoader', $translateStaticFilesLoader);
function $translateStaticFilesLoader($q, $http) {
'use strict';
return function (options) {
if (!options || (!angular.isArray(options.files) && (!angular.isString(options.prefix) || !angular.isString(options.suffix)))) {
throw new Error('Couldn\'t load static files, no files and prefix or suffix specified!');
}
if (!options.files) {
options.files = [{
prefix: options.prefix,
suffix: options.suffix
}];
}
var load = function (file) {
if (!file || (!angular.isString(file.prefix) || !angular.isString(file.suffix))) {
throw new Error('Couldn\'t load static file, no prefix or suffix specified!');
}
return $http(angular.extend({
url: [
file.prefix,
options.key,
file.suffix
].join(''),
method: 'GET',
params: ''
}, options.$http))
.then(function(result) {
return result.data;
}, function () {
return $q.reject(options.key);
});
};
var promises = [],
length = options.files.length;
for (var i = 0; i < length; i++) {
promises.push(load({
prefix: options.files[i].prefix,
key: options.key,
suffix: options.files[i].suffix
}));
}
return $q.all(promises)
.then(function (data) {
var length = data.length,
mergedData = {};
for (var i = 0; i < length; i++) {
for (var key in data[i]) {
mergedData[key] = data[i][key];
}
}
return mergedData;
});
};
}
$translateStaticFilesLoader.displayName = '$translateStaticFilesLoader';
return 'pascalprecht.translate';
}));

File diff suppressed because it is too large Load Diff

20560
gui/default/vendor/angular/angular.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long