Refactor: Move initialization code into separate initializers that use the API we

developed for plugins.
This commit is contained in:
Robin Ward
2013-12-03 14:22:32 -05:00
parent de78ee302a
commit 274743b877
14 changed files with 219 additions and 189 deletions
+4 -101
View File
@@ -11,9 +11,6 @@
Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
rootElement: '#main',
// Whether the app has focus or not
hasFocus: true,
// Helps with integration tests
URL_FIXTURES: {},
@@ -69,61 +66,6 @@ Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
this.set('notifyCount', count);
},
/**
Establishes global DOM events and bindings via jQuery.
@method bindDOMEvents
**/
bindDOMEvents: function() {
$('#main').on('click.discourse', 'a', function(e) {
if (e.isDefaultPrevented() || e.shiftKey || e.metaKey || e.ctrlKey) { return; }
var $currentTarget = $(e.currentTarget),
href = $currentTarget.attr('href');
if (!href ||
href === '#' ||
$currentTarget.attr('target') ||
$currentTarget.data('ember-action') ||
$currentTarget.data('auto-route') ||
$currentTarget.hasClass('ember-view') ||
$currentTarget.hasClass('lightbox') ||
href.indexOf("mailto:") === 0 ||
(href.match(/^http[s]?:\/\//i) && !href.match(new RegExp("^http:\\/\\/" + window.location.hostname, "i")))) {
return;
}
e.preventDefault();
Discourse.URL.routeTo(href);
return false;
});
$(window).focus(function() {
Discourse.set('hasFocus', true);
Discourse.set('notify', false);
}).blur(function() {
Discourse.set('hasFocus', false);
});
// Add a CSRF token to all AJAX requests
Discourse.csrfToken = $('meta[name=csrf-token]').attr('content');
$.ajaxPrefilter(function(options, originalOptions, xhr) {
if (!options.crossDomain) {
xhr.setRequestHeader('X-CSRF-Token', Discourse.csrfToken);
}
});
bootbox.animate(false);
bootbox.backdrop(true); // clicking outside a bootbox modal closes it
Discourse.Mobile.init();
setInterval(function(){
Discourse.Formatter.updateRelativeAge($('.relative-date'));
},60 * 1000);
},
/**
Log the current user out of Discourse
@@ -153,37 +95,6 @@ Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
if(this.get('loginRequired')) { route.transitionTo('login'); }
},
/**
Subscribes the current user to receive message bus notifications
**/
subscribeUserToNotifications: function() {
var user = Discourse.User.current();
if (user) {
var bus = Discourse.MessageBus;
bus.callbackInterval = Discourse.SiteSettings.polling_interval;
bus.enableLongPolling = true;
bus.baseUrl = Discourse.getURL("/");
if (user.admin || user.moderator) {
bus.subscribe("/flagged_counts", function(data) {
user.set('site_flagged_posts_count', data.total);
});
}
bus.subscribe("/notification/" + user.get('id'), (function(data) {
user.set('unread_notifications', data.unread_notifications);
user.set('unread_private_messages', data.unread_private_messages);
}), user.notification_channel_position);
bus.subscribe("/categories", function(data){
var site = Discourse.Site.current();
_.each(data.categories,function(c){
site.updateCategory(c);
});
});
}
},
/**
Add an initializer hook for after the Discourse Application starts up.
@@ -196,24 +107,16 @@ Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
},
/**
Start up the Discourse application.
Start up the Discourse application by running all the initializers we've defined.
@method start
**/
start: function() {
Discourse.bindDOMEvents();
Discourse.MessageBus.alwaysLongPoll = Discourse.Environment === "development";
Discourse.MessageBus.start();
Discourse.KeyValueStore.init("discourse_", Discourse.MessageBus);
// Developer specific functions
Discourse.Development.observeLiveChanges();
Discourse.subscribeUserToNotifications();
if (Discourse.initializers) {
var initializers = this.initializers;
if (initializers) {
var self = this;
Em.run.next(function() {
Discourse.initializers.forEach(function (init) {
initializers.forEach(function (init) {
init.call(self);
});
});
@@ -0,0 +1,8 @@
/**
Initialize the message bus to receive messages.
**/
Discourse.addInitializer(function() {
Discourse.MessageBus.alwaysLongPoll = Discourse.Environment === "development";
Discourse.MessageBus.start();
Discourse.KeyValueStore.init("discourse_", Discourse.MessageBus);
});
@@ -0,0 +1,11 @@
/**
Default settings for bootbox
**/
Discourse.addInitializer(function() {
bootbox.animate(false);
// clicking outside a bootbox modal closes it
bootbox.backdrop(true);
});
@@ -0,0 +1,32 @@
/**
Discourse does some server side rendering of HTML, such as the `cooked` contents of
posts. The downside of this in an Ember app is the links will not go through the router.
This jQuery code intercepts clicks on those links and routes them properly.
**/
Discourse.addInitializer(function() {
$('#main').on('click.discourse', 'a', function(e) {
if (e.isDefaultPrevented() || e.shiftKey || e.metaKey || e.ctrlKey) { return; }
var $currentTarget = $(e.currentTarget),
href = $currentTarget.attr('href');
if (!href ||
href === '#' ||
$currentTarget.attr('target') ||
$currentTarget.data('ember-action') ||
$currentTarget.data('auto-route') ||
$currentTarget.hasClass('ember-view') ||
$currentTarget.hasClass('lightbox') ||
href.indexOf("mailto:") === 0 ||
(href.match(/^http[s]?:\/\//i) && !href.match(new RegExp("^http:\\/\\/" + window.location.hostname, "i")))) {
return;
}
e.preventDefault();
Discourse.URL.routeTo(href);
return false;
});
});
@@ -0,0 +1,19 @@
/**
Append our CSRF token to AJAX requests when necessary.
**/
Discourse.addInitializer(function() {
var session = Discourse.Session;
// Add a CSRF token to all AJAX requests
session.currentProp('csrfToken', $('meta[name=csrf-token]').attr('content'));
$.ajaxPrefilter(function(options, originalOptions, xhr) {
if (!options.crossDomain) {
xhr.setRequestHeader('X-CSRF-Token', session.currentProp('csrfToken'));
}
});
});
@@ -0,0 +1,16 @@
/**
Keep track of when the browser is in focus.
**/
Discourse.addInitializer(function() {
// Default to true
this.set('hasFocus', true);
var self = this;
$(window).focus(function() {
self.setProperties({hasFocus: true, notify: false});
}).blur(function() {
self.set('hasFocus', false);
});
});
@@ -0,0 +1,7 @@
/**
Initializes the `Discourse.Mobile` helper object.
**/
Discourse.addInitializer(function() {
Discourse.Mobile.init();
});
@@ -0,0 +1,73 @@
/**
Use the message bus for live reloading of components for faster development.
**/
Discourse.addInitializer(function() {
console.log('live reloading');
// subscribe to any site customizations that are loaded
$('link.custom-css').each(function() {
var split = this.href.split("/"),
id = split[split.length - 1].split(".css")[0],
self = this;
return Discourse.MessageBus.subscribe("/file-change/" + id, function(data) {
if (!$(self).data('orig')) {
$(self).data('orig', self.href);
}
var orig = $(self).data('orig'),
sp = orig.split(".css?");
self.href = sp[0] + ".css?" + data;
});
});
// Custom header changes
$('header.custom').each(function() {
var header = $(this);
return Discourse.MessageBus.subscribe("/header-change/" + $(this).data('key'), function(data) {
return header.html(data);
});
});
// Observe file changes
return Discourse.MessageBus.subscribe("/file-change", function(data) {
Ember.TEMPLATES.empty = Handlebars.compile("<div></div>");
_.each(data,function(me,idx) {
if (me === "refresh") {
// Refresh if necessary
document.location.reload(true);
} else if (me.name.substr(-10) === "handlebars") {
// Reload handlebars
var js = me.name.replace(".handlebars", "").replace("app/assets/javascripts", "/assets");
$LAB.script(js + "?hash=" + me.hash).wait(function() {
var templateName;
templateName = js.replace(".js", "").replace("/assets/", "");
return _.each(Ember.View.views, function(view) {
if (view.get('templateName') === templateName) {
view.set('templateName', 'empty');
view.rerender();
Em.run.schedule('afterRender', function() {
view.set('templateName', templateName);
view.rerender();
});
}
});
});
} else {
$('link').each(function() {
if (this.href.match(me.name) && me.hash) {
if (!$(this).data('orig')) {
$(this).data('orig', this.href);
}
this.href = $(this).data('orig') + "&hash=" + me.hash;
}
});
}
});
});
});
@@ -0,0 +1,12 @@
/**
Updates the relative ages of dates on the screen.
**/
Discourse.addInitializer(function() {
setInterval(function(){
Discourse.Formatter.updateRelativeAge($('.relative-date'));
}, 60 * 1000);
});
@@ -0,0 +1,32 @@
/**
Updates the relative ages of dates on the screen.
**/
Discourse.addInitializer(function() {
var user = Discourse.User.current();
if (user) {
var bus = Discourse.MessageBus;
bus.callbackInterval = Discourse.SiteSettings.polling_interval;
bus.enableLongPolling = true;
bus.baseUrl = Discourse.getURL("/");
if (user.admin || user.moderator) {
bus.subscribe("/flagged_counts", function(data) {
user.set('site_flagged_posts_count', data.total);
});
}
bus.subscribe("/notification/" + user.get('id'), (function(data) {
user.set('unread_notifications', data.unread_notifications);
user.set('unread_private_messages', data.unread_private_messages);
}), user.notification_channel_position);
bus.subscribe("/categories", function(data){
var site = Discourse.Site.current();
_.each(data.categories,function(c){
site.updateCategory(c);
});
});
}
});
@@ -1,81 +0,0 @@
/**
Functions to help development of Discourse, such as inserting probes
@class Development
@namespace Discourse
@module Discourse
**/
Discourse.Development = {
/**
Use the message bus for live reloading of components for faster development.
@method observeLiveChanges
**/
observeLiveChanges: function() {
// subscribe to any site customizations that are loaded
$('link.custom-css').each(function() {
var id, split, stylesheet,
_this = this;
split = this.href.split("/");
id = split[split.length - 1].split(".css")[0];
stylesheet = this;
return Discourse.MessageBus.subscribe("/file-change/" + id, function(data) {
var orig, sp;
if (!$(stylesheet).data('orig')) {
$(stylesheet).data('orig', stylesheet.href);
}
orig = $(stylesheet).data('orig');
sp = orig.split(".css?");
stylesheet.href = sp[0] + ".css?" + data;
});
});
// Custom header changes
$('header.custom').each(function() {
var header;
header = $(this);
return Discourse.MessageBus.subscribe("/header-change/" + ($(this).data('key')), function(data) {
return header.html(data);
});
});
// Observe file changes
return Discourse.MessageBus.subscribe("/file-change", function(data) {
Ember.TEMPLATES.empty = Handlebars.compile("<div></div>");
_.each(data,function(me,idx) {
var js;
if (me === "refresh") {
return document.location.reload(true);
} else if (me.name.substr(-10) === "handlebars") {
js = me.name.replace(".handlebars", "").replace("app/assets/javascripts", "/assets");
return $LAB.script(js + "?hash=" + me.hash).wait(function() {
var templateName;
templateName = js.replace(".js", "").replace("/assets/", "");
return _.each(Ember.View.views, function(view) {
if (view.get('templateName') === templateName) {
view.set('templateName', 'empty');
view.rerender();
Em.run.schedule('afterRender', function() {
view.set('templateName', templateName);
view.rerender();
});
}
});
});
} else {
return $('link').each(function() {
if (this.href.match(me.name) && me.hash) {
if (!$(this).data('orig')) {
$(this).data('orig', this.href);
}
this.href = $(this).data('orig') + "&hash=" + me.hash;
}
});
}
});
});
}
};
@@ -1,12 +1,10 @@
/**
A class that is responsible for logic related to mobile devices.
An object that is responsible for logic related to mobile devices.
@class Mobile
@namespace Discourse
@module Discourse
@module Mobile
**/
Discourse.Mobile = {
isMobileDevice: false,
mobileView: false,
@@ -59,7 +59,7 @@ Discourse.Ajax = Em.Mixin.create({
// note: for bad CSRF we don't loop an extra request right away.
// this allows us to eliminate the possibility of having a loop.
if (xhr.status === 403 && xhr.responseText === "['BAD CSRF']") {
Discourse.csrfToken = null;
Discourse.Session.current().set('csrfToken', null);
}
// If it's a parseerror, don't reject
@@ -79,7 +79,7 @@ Discourse.Ajax = Em.Mixin.create({
// For cached pages we strip out CSRF tokens, need to round trip to server prior to sending the
// request (bypass for GET, not needed)
if(args.type && args.type !== 'GET' && !Discourse.csrfToken){
if(args.type && args.type !== 'GET' && !Discourse.Session.currentProp('csrfToken')){
return Ember.Deferred.promise(function(promise){
$.ajax(Discourse.getURL('/session/csrf'))
.success(function(result){
+1 -1
View File
@@ -104,7 +104,7 @@ d.write('<style>#ember-testing-container { position: absolute; background: white
Discourse.rootElement = '#ember-testing';
Discourse.setupForTesting();
Discourse.injectTestHelpers();
Discourse.bindDOMEvents();
Discourse.runInitializers();
Discourse.Router.map(function() {
Discourse.routeBuilder.call(this);