Browse Source

Implemented deferred based initialization to allow async operations to complete before config.

pull/92/head
Simon Eisenmann 11 years ago
parent
commit
be7598a087
  1. 209
      static/js/app.js
  2. 64
      static/js/main.js

209
static/js/app.js

@ -61,7 +61,53 @@ define([ @@ -61,7 +61,53 @@ define([
})(window.location.search.substr(1).split("&"));
}());
var initialize = function(ms) {
// Base application config shared during initialization.
var appConfig = {};
// Implement translation store.
var TranslationData = function() {
// Create data structure.
this.data = {
locale_data: {}
};
};
TranslationData.prototype.add = function(domain, data) {
var src;
if (data && data.locale_data) {
src = data.locale_data[domain];
}
var dst = this.data.locale_data[domain];
if (!dst) {
dst = this.data.locale_data[domain] = {
"": {
"domain": domain,
"plural_forms": "nplurals=2; plural=(n != 1);"
}
}
_.extend(dst, src);
}
};
TranslationData.prototype.load = function(domain, url) {
var that = this;
return $.ajax({
dataType: "json",
url: url,
success: function(data) {
//console.log("loaded translation data", data);
that.add(domain, data);
},
error: function(err, textStatus, errorThrown) {
console.warn("Failed to load translation data " + url + ": " + errorThrown);
that.add(domain, null);
}
});
};
TranslationData.prototype.get = function() {
return this.data;
};
var translationData = new TranslationData();
var create = function(ms) {
var modules = ['ui.bootstrap', 'ngSanitize', 'ngAnimate', 'ngHumanize', 'ngRoute'];
if (ms && ms.length) {
@ -99,92 +145,16 @@ define([ @@ -99,92 +145,16 @@ define([
app.constant("availableLanguages", languages);
angular.element(document).ready(function() {
var globalContext = JSON.parse($("#globalcontext").text());
app.constant("globalContext", globalContext);
// Configure language.
var lang = (function() {
var lang = "en";
var wanted = [];
var html = document.getElementsByTagName("html")[0];
// Get from storage.
if (modernizr.localstorage) {
var lsl = localStorage.getItem("mediastream-language");
if (lsl && lsl !== "undefined") {
wanted.push(lsl);
}
}
// Get from query.
var qsl = urlQuery.lang;
if (qsl) {
wanted.push(qsl);
}
// Expand browser languages with combined fallback.
_.each(globalContext.Languages, function(l) {
wanted.push(l);
if (l.indexOf("-") != -1) {
wanted.push(l.split("-")[0]);
}
});
// Loop through browser languages and use first one we got.
for (var i = 0; i < wanted.length; i++) {
if (languages.hasOwnProperty(wanted[i])) {
lang = wanted[i];
break;
}
}
html.setAttribute("lang", lang);
return lang;
}());
app.provider("translationData", function translationDataProvider() {
// Prepare bootstrap function with injected locale data.
var domain = "messages";
var catalog = domain + "-" + lang;
var bootstrap = function(translationData) {
if (!translationData) {
// Fallback catalog in case translation could not be loaded.
lang = "en";
translationData = {};
translationData.locale_data = {};
translationData.domain = domain;
translationData.locale_data[domain] = {
"": {
"domain": domain,
"lang": lang,
"plural_forms": "nplurals=2; plural=(n != 1);"
}
};
}
// Set date language too.
moment.lang([lang, "en"]);
// Inject translation data globally.
app.constant("translationData", translationData);
// Bootstrap AngularJS app.
console.log("Bootstrapping ...");
angular.bootstrap(document, ['app']);
};
if (lang !== "en") {
// Load translation file.
//console.log("Loading translation data: " + lang);
$.ajax({
dataType: "json",
url: require.toUrl('translation/' + catalog + '.json'),
success: function(data) {
//console.log("Loaded translation data.");
bootstrap(data);
},
error: function(err, textStatus, errorThrown) {
console.warn("Failed to load translation data " + catalog + ": " + errorThrown);
bootstrap(null);
}
});
} else {
// No need to load english as this is built in.
_.defer(bootstrap);
}
// Make available functions for config phase.
this.add = _.bind(translationData.add, translationData);
this.load = _.bind(translationData.load, translationData);
// Out creater returns raw data.
this.$get = [function translationDataFactory() {
return translationData.get();
}];
});
@ -192,8 +162,73 @@ define([ @@ -192,8 +162,73 @@ define([
};
var initialize = function(app) {
var deferred = $.Deferred();
var globalContext = JSON.parse($("#globalcontext").text());
app.constant("globalContext", globalContext);
// Configure language.
var lang = (function() {
var lang = "en";
var wanted = [];
var html = document.getElementsByTagName("html")[0];
// Get from storage.
if (modernizr.localstorage) {
var lsl = localStorage.getItem("mediastream-language");
if (lsl && lsl !== "undefined") {
wanted.push(lsl);
}
}
// Get from query.
var qsl = urlQuery.lang;
if (qsl) {
wanted.push(qsl);
}
// Expand browser languages with combined fallback.
_.each(globalContext.Languages, function(l) {
wanted.push(l);
if (l.indexOf("-") != -1) {
wanted.push(l.split("-")[0]);
}
});
// Loop through browser languages and use first one we got.
for (var i = 0; i < wanted.length; i++) {
if (languages.hasOwnProperty(wanted[i])) {
lang = wanted[i];
break;
}
}
html.setAttribute("lang", lang);
return lang;
}());
// Inject language to config.
appConfig.lang = lang;
if (lang === "en") {
// No need to load english as this is built in.
deferred.resolve();
} else {
// Load default translation catalog.
var domain = "messages";
var url = require.toUrl('translation/' + domain + "-" + lang + '.json');
$.when(translationData.load(domain, url)).always(function() {
deferred.resolve();
});
}
return deferred.promise();
};
return {
initialize: initialize
create: create,
initialize: initialize,
query: urlQuery,
config: appConfig,
translationData: translationData
};
});

64
static/js/main.js

@ -193,8 +193,17 @@ if (Object.create) { @@ -193,8 +193,17 @@ if (Object.create) {
load.push(dataPlugin);
}
});
require(load, function(App) {
// All other arguments are plugins.
var args = Array.prototype.slice.call(arguments, 1);
// Prepare our promised based initialization.
var promises = [];
var loading = $.Deferred();
promises.push(loading.promise());
// Add Angular modules from plugins.
var modules = [];
_.each(args, function(plugin) {
@ -202,26 +211,59 @@ if (Object.create) { @@ -202,26 +211,59 @@ if (Object.create) {
plugin.module(modules);
}
});
// External plugin support.
var externalPlugin
var externalPlugin;
if (window.externalPlugin) {
externalPlugin = window.externalPlugin($, _, angular);
if (externalPlugin && externalPlugin.module) {
externalPlugin.module(modules);
}
}
// Init Angular app.
var app = App.initialize(modules);
// Init plugins.
_.each(args, function(plugin) {
if (plugin && plugin.initialize) {
plugin.initialize(app);
// Create Angular app.
var app = App.create(modules);
// Helper function to initialize with deferreds.
var initialize = function(obj) {
if (obj && obj.initialize) {
var result = obj.initialize(app);
if (result && result.done) {
// If we got a promise add it to our wait queue.
promises.push(result);
}
}
};
// Wait until dom is ready before we initialize.
angular.element(document).ready(function() {
// Init base application.
initialize(App);
// Init plugins.
_.each(args, function(plugin) {
initialize(plugin);
});
// Init external plugin.
if (externalPlugin) {
initialize(externalPlugin);
}
// Resolve the base loader.
loading.resolve();
// Wait for all others to complete and then boostrap the app.
$.when.apply($, promises).done(function() {
console.log("Bootstrapping ...");
angular.bootstrap(document, ['app'], {
strictDi: true
});
});
});
// Init external plugin.
if (externalPlugin && externalPlugin.initialize) {
externalPlugin.initialize(app);
}
});
});

Loading…
Cancel
Save