1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2024-12-04 15:24:23 +01:00
fab-manager/vendor/assets/components/angular-translate-loader-partial/angular-translate-loader-partial.js
2016-03-23 18:39:41 +01:00

523 lines
18 KiB
JavaScript

/*!
* angular-translate - v2.8.1 - 2015-10-01
*
* Copyright (c) 2015 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 () {
angular.module('pascalprecht.translate')
/**
* @ngdoc object
* @name pascalprecht.translate.$translatePartialLoaderProvider
*
* @description
* By using a $translatePartialLoaderProvider you can configure a list of a needed
* translation parts directly during the configuration phase of your application's
* lifetime. All parts you add by using this provider would be loaded by
* angular-translate at the startup as soon as possible.
*/
.provider('$translatePartialLoader', $translatePartialLoader);
function $translatePartialLoader() {
'use strict';
/**
* @constructor
* @name Part
*
* @description
* Represents Part object to add and set parts at runtime.
*/
function Part(name, priority) {
this.name = name;
this.isActive = true;
this.tables = {};
this.priority = priority || 0;
}
/**
* @name parseUrl
* @method
*
* @description
* Returns a parsed url template string and replaces given target lang
* and part name it.
*
* @param {string|function} urlTemplate - Either a string containing an url pattern (with
* '{part}' and '{lang}') or a function(part, lang)
* returning a string.
* @param {string} targetLang - Language key for language to be used.
* @return {string} Parsed url template string
*/
Part.prototype.parseUrl = function(urlTemplate, targetLang) {
if (angular.isFunction(urlTemplate)) {
return urlTemplate(this.name, targetLang);
}
return urlTemplate.replace(/\{part\}/g, this.name).replace(/\{lang\}/g, targetLang);
};
Part.prototype.getTable = function(lang, $q, $http, $httpOptions, urlTemplate, errorHandler) {
if (!this.tables[lang]) {
var self = this;
return $http(angular.extend({
method : 'GET',
url: this.parseUrl(urlTemplate, lang)
}, $httpOptions))
.then(function(result){
self.tables[lang] = result.data;
return result.data;
}, function() {
if (errorHandler) {
return errorHandler(self.name, lang)
.then(function(data) {
self.tables[lang] = data;
return data;
}, function() {
return $q.reject(self.name);
});
} else {
return $q.reject(self.name);
}
});
} else {
return $q.when(this.tables[lang]);
}
};
var parts = {};
function hasPart(name) {
return Object.prototype.hasOwnProperty.call(parts, name);
}
function isStringValid(str) {
return angular.isString(str) && str !== '';
}
function isPartAvailable(name) {
if (!isStringValid(name)) {
throw new TypeError('Invalid type of a first argument, a non-empty string expected.');
}
return (hasPart(name) && parts[name].isActive);
}
function deepExtend(dst, src) {
for (var property in src) {
if (src[property] && src[property].constructor &&
src[property].constructor === Object) {
dst[property] = dst[property] || {};
deepExtend(dst[property], src[property]);
} else {
dst[property] = src[property];
}
}
return dst;
}
function getPrioritizedParts() {
var prioritizedParts = [];
for(var part in parts) {
if (parts[part].isActive) {
prioritizedParts.push(parts[part]);
}
}
prioritizedParts.sort(function (a, b) {
return a.priority - b.priority;
});
return prioritizedParts;
}
/**
* @ngdoc function
* @name pascalprecht.translate.$translatePartialLoaderProvider#addPart
* @methodOf pascalprecht.translate.$translatePartialLoaderProvider
*
* @description
* Registers a new part of the translation table to be loaded once the
* `angular-translate` gets into runtime phase. It does not actually load any
* translation data, but only registers a part to be loaded in the future.
*
* @param {string} name A name of the part to add
* @param {int} [priority=0] Sets the load priority of this part.
*
* @returns {object} $translatePartialLoaderProvider, so this method is chainable
* @throws {TypeError} The method could throw a **TypeError** if you pass the param
* of the wrong type. Please, note that the `name` param has to be a
* non-empty **string**.
*/
this.addPart = function(name, priority) {
if (!isStringValid(name)) {
throw new TypeError('Couldn\'t add part, part name has to be a string!');
}
if (!hasPart(name)) {
parts[name] = new Part(name, priority);
}
parts[name].isActive = true;
return this;
};
/**
* @ngdocs function
* @name pascalprecht.translate.$translatePartialLoaderProvider#setPart
* @methodOf pascalprecht.translate.$translatePartialLoaderProvider
*
* @description
* Sets a translation table to the specified part. This method does not make the
* specified part available, but only avoids loading this part from the server.
*
* @param {string} lang A language of the given translation table
* @param {string} part A name of the target part
* @param {object} table A translation table to set to the specified part
*
* @return {object} $translatePartialLoaderProvider, so this method is chainable
* @throws {TypeError} The method could throw a **TypeError** if you pass params
* of the wrong type. Please, note that the `lang` and `part` params have to be a
* non-empty **string**s and the `table` param has to be an object.
*/
this.setPart = function (lang, part, table) {
if (!isStringValid(lang)) {
throw new TypeError('Couldn\'t set part.`lang` parameter has to be a string!');
}
if (!isStringValid(part)) {
throw new TypeError('Couldn\'t set part.`part` parameter has to be a string!');
}
if (typeof table !== 'object' || table === null) {
throw new TypeError('Couldn\'t set part. `table` parameter has to be an object!');
}
if (!hasPart(part)) {
parts[part] = new Part(part);
parts[part].isActive = false;
}
parts[part].tables[lang] = table;
return this;
};
/**
* @ngdoc function
* @name pascalprecht.translate.$translatePartialLoaderProvider#deletePart
* @methodOf pascalprecht.translate.$translatePartialLoaderProvider
*
* @description
* Removes the previously added part of the translation data. So, `angular-translate` will not
* load it at the startup.
*
* @param {string} name A name of the part to delete
*
* @returns {object} $translatePartialLoaderProvider, so this method is chainable
*
* @throws {TypeError} The method could throw a **TypeError** if you pass the param of the wrong
* type. Please, note that the `name` param has to be a non-empty **string**.
*/
this.deletePart = function (name) {
if (!isStringValid(name)) {
throw new TypeError('Couldn\'t delete part, first arg has to be string.');
}
if (hasPart(name)) {
parts[name].isActive = false;
}
return this;
};
/**
* @ngdoc function
* @name pascalprecht.translate.$translatePartialLoaderProvider#isPartAvailable
* @methodOf pascalprecht.translate.$translatePartialLoaderProvider
*
* @description
* Checks if the specific part is available. A part becomes available after it was added by the
* `addPart` method. Available parts would be loaded from the server once the `angular-translate`
* asks the loader to that.
*
* @param {string} name A name of the part to check
*
* @returns {boolean} Returns **true** if the part is available now and **false** if not.
*
* @throws {TypeError} The method could throw a **TypeError** if you pass the param of the wrong
* type. Please, note that the `name` param has to be a non-empty **string**.
*/
this.isPartAvailable = isPartAvailable;
/**
* @ngdoc object
* @name pascalprecht.translate.$translatePartialLoader
*
* @requires $q
* @requires $http
* @requires $injector
* @requires $rootScope
* @requires $translate
*
* @description
*
* @param {object} options Options object
*
* @throws {TypeError}
*/
this.$get = ['$rootScope', '$injector', '$q', '$http',
function($rootScope, $injector, $q, $http) {
/**
* @ngdoc event
* @name pascalprecht.translate.$translatePartialLoader#$translatePartialLoaderStructureChanged
* @eventOf pascalprecht.translate.$translatePartialLoader
* @eventType broadcast on root scope
*
* @description
* A $translatePartialLoaderStructureChanged event is called when a state of the loader was
* changed somehow. It could mean either some part is added or some part is deleted. Anyway when
* you get this event the translation table is not longer current and has to be updated.
*
* @param {string} name A name of the part which is a reason why the event was fired
*/
var service = function(options) {
if (!isStringValid(options.key)) {
throw new TypeError('Unable to load data, a key is not a non-empty string.');
}
if (!isStringValid(options.urlTemplate) && !angular.isFunction(options.urlTemplate)) {
throw new TypeError('Unable to load data, a urlTemplate is not a non-empty string or not a function.');
}
var errorHandler = options.loadFailureHandler;
if (errorHandler !== undefined) {
if (!angular.isString(errorHandler)) {
throw new Error('Unable to load data, a loadFailureHandler is not a string.');
} else {
errorHandler = $injector.get(errorHandler);
}
}
var loaders = [],
deferred = $q.defer(),
prioritizedParts = getPrioritizedParts();
angular.forEach(prioritizedParts, function(part) {
loaders.push(
part.getTable(options.key, $q, $http, options.$http, options.urlTemplate, errorHandler)
);
part.urlTemplate = options.urlTemplate;
});
$q.all(loaders)
.then(function() {
var table = {};
angular.forEach(prioritizedParts, function(part) {
deepExtend(table, part.tables[options.key]);
});
deferred.resolve(table);
}, function() {
deferred.reject(options.key);
}
);
return deferred.promise;
};
/**
* @ngdoc function
* @name pascalprecht.translate.$translatePartialLoader#addPart
* @methodOf pascalprecht.translate.$translatePartialLoader
*
* @description
* Registers a new part of the translation table. This method does not actually perform any xhr
* requests to get translation data. The new parts will be loaded in order of priority from the server next time
* `angular-translate` asks the loader to load translations.
*
* @param {string} name A name of the part to add
* @param {int} [priority=0] Sets the load priority of this part.
*
* @returns {object} $translatePartialLoader, so this method is chainable
*
* @fires {$translatePartialLoaderStructureChanged} The $translatePartialLoaderStructureChanged
* event would be fired by this method in case the new part affected somehow on the loaders
* state. This way it means that there are a new translation data available to be loaded from
* the server.
*
* @throws {TypeError} The method could throw a **TypeError** if you pass the param of the wrong
* type. Please, note that the `name` param has to be a non-empty **string**.
*/
service.addPart = function(name, priority) {
if (!isStringValid(name)) {
throw new TypeError('Couldn\'t add part, first arg has to be a string');
}
if (!hasPart(name)) {
parts[name] = new Part(name, priority);
$rootScope.$emit('$translatePartialLoaderStructureChanged', name);
} else if (!parts[name].isActive) {
parts[name].isActive = true;
$rootScope.$emit('$translatePartialLoaderStructureChanged', name);
}
return service;
};
/**
* @ngdoc function
* @name pascalprecht.translate.$translatePartialLoader#deletePart
* @methodOf pascalprecht.translate.$translatePartialLoader
*
* @description
* Deletes the previously added part of the translation data. The target part could be deleted
* either logically or physically. When the data is deleted logically it is not actually deleted
* from the browser, but the loader marks it as not active and prevents it from affecting on the
* translations. If the deleted in such way part is added again, the loader will use the
* previously loaded data rather than loading it from the server once more time. But if the data
* is deleted physically, the loader will completely remove all information about it. So in case
* of recycling this part will be loaded from the server again.
*
* @param {string} name A name of the part to delete
* @param {boolean=} [removeData=false] An indicator if the loader has to remove a loaded
* translation data physically. If the `removeData` if set to **false** the loaded data will not be
* deleted physically and might be reused in the future to prevent an additional xhr requests.
*
* @returns {object} $translatePartialLoader, so this method is chainable
*
* @fires {$translatePartialLoaderStructureChanged} The $translatePartialLoaderStructureChanged
* event would be fired by this method in case a part deletion process affects somehow on the
* loaders state. This way it means that some part of the translation data is now deprecated and
* the translation table has to be recompiled with the remaining translation parts.
*
* @throws {TypeError} The method could throw a **TypeError** if you pass some param of the
* wrong type. Please, note that the `name` param has to be a non-empty **string** and
* the `removeData` param has to be either **undefined** or **boolean**.
*/
service.deletePart = function(name, removeData) {
if (!isStringValid(name)) {
throw new TypeError('Couldn\'t delete part, first arg has to be string');
}
if (removeData === undefined) {
removeData = false;
} else if (typeof removeData !== 'boolean') {
throw new TypeError('Invalid type of a second argument, a boolean expected.');
}
if (hasPart(name)) {
var wasActive = parts[name].isActive;
if (removeData) {
var $translate = $injector.get('$translate');
var cache = $translate.loaderCache();
if (typeof(cache) === 'string') {
// getting on-demand instance of loader
cache = $injector.get(cache);
}
// Purging items from cache...
if (typeof(cache) === 'object') {
angular.forEach(parts[name].tables, function(value, key) {
cache.remove(parts[name].parseUrl(parts[name].urlTemplate, key));
});
}
delete parts[name];
} else {
parts[name].isActive = false;
}
if (wasActive) {
$rootScope.$emit('$translatePartialLoaderStructureChanged', name);
}
}
return service;
};
/**
* @ngdoc function
* @name pascalprecht.translate.$translatePartialLoader#isPartLoaded
* @methodOf pascalprecht.translate.$translatePartialLoader
*
* @description
* Checks if the registered translation part is loaded into the translation table.
*
* @param {string} name A name of the part
* @param {string} lang A key of the language
*
* @returns {boolean} Returns **true** if the translation of the part is loaded to the translation table and **false** if not.
*
* @throws {TypeError} The method could throw a **TypeError** if you pass the param of the wrong
* type. Please, note that the `name` and `lang` params have to be non-empty **string**.
*/
service.isPartLoaded = function(name, lang) {
return angular.isDefined(parts[name]) && angular.isDefined(parts[name].tables[lang]);
};
/**
* @ngdoc function
* @name pascalprecht.translate.$translatePartialLoader#getRegisteredParts
* @methodOf pascalprecht.translate.$translatePartialLoader
*
* @description
* Gets names of the parts that were added with the `addPart`.
*
* @returns {array} Returns array of registered parts, if none were registered then an empty array is returned.
*/
service.getRegisteredParts = function() {
var registeredParts = [];
angular.forEach(parts, function(p){
if(p.isActive) {
registeredParts.push(p.name);
}
});
return registeredParts;
};
/**
* @ngdoc function
* @name pascalprecht.translate.$translatePartialLoader#isPartAvailable
* @methodOf pascalprecht.translate.$translatePartialLoader
*
* @description
* Checks if a target translation part is available. The part becomes available just after it was
* added by the `addPart` method. Part's availability does not mean that it was loaded from the
* server, but only that it was added to the loader. The available part might be loaded next
* time the loader is called.
*
* @param {string} name A name of the part to delete
*
* @returns {boolean} Returns **true** if the part is available now and **false** if not.
*
* @throws {TypeError} The method could throw a **TypeError** if you pass the param of the wrong
* type. Please, note that the `name` param has to be a non-empty **string**.
*/
service.isPartAvailable = isPartAvailable;
return service;
}];
}
$translatePartialLoader.displayName = '$translatePartialLoader';
return 'pascalprecht.translate';
}));