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
+3 -3
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 -->
+1
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
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
+164 -50
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;
}
};
};
@@ -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
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long