Refactor: Move initialization code into separate initializers that use the API we
developed for plugins.
This commit is contained in:
parent
de78ee302a
commit
274743b877
|
@ -11,9 +11,6 @@
|
||||||
Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||||
rootElement: '#main',
|
rootElement: '#main',
|
||||||
|
|
||||||
// Whether the app has focus or not
|
|
||||||
hasFocus: true,
|
|
||||||
|
|
||||||
// Helps with integration tests
|
// Helps with integration tests
|
||||||
URL_FIXTURES: {},
|
URL_FIXTURES: {},
|
||||||
|
|
||||||
|
@ -69,61 +66,6 @@ Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||||
this.set('notifyCount', count);
|
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
|
Log the current user out of Discourse
|
||||||
|
|
||||||
|
@ -153,37 +95,6 @@ Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||||
if(this.get('loginRequired')) { route.transitionTo('login'); }
|
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.
|
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
|
@method start
|
||||||
**/
|
**/
|
||||||
start: function() {
|
start: function() {
|
||||||
Discourse.bindDOMEvents();
|
var initializers = this.initializers;
|
||||||
Discourse.MessageBus.alwaysLongPoll = Discourse.Environment === "development";
|
if (initializers) {
|
||||||
Discourse.MessageBus.start();
|
|
||||||
Discourse.KeyValueStore.init("discourse_", Discourse.MessageBus);
|
|
||||||
|
|
||||||
// Developer specific functions
|
|
||||||
Discourse.Development.observeLiveChanges();
|
|
||||||
Discourse.subscribeUserToNotifications();
|
|
||||||
|
|
||||||
if (Discourse.initializers) {
|
|
||||||
var self = this;
|
var self = this;
|
||||||
Em.run.next(function() {
|
Em.run.next(function() {
|
||||||
Discourse.initializers.forEach(function (init) {
|
initializers.forEach(function (init) {
|
||||||
init.call(self);
|
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
|
@namespace Discourse
|
||||||
@module Discourse
|
@module Mobile
|
||||||
**/
|
**/
|
||||||
Discourse.Mobile = {
|
Discourse.Mobile = {
|
||||||
|
|
||||||
isMobileDevice: false,
|
isMobileDevice: false,
|
||||||
mobileView: 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.
|
// note: for bad CSRF we don't loop an extra request right away.
|
||||||
// this allows us to eliminate the possibility of having a loop.
|
// this allows us to eliminate the possibility of having a loop.
|
||||||
if (xhr.status === 403 && xhr.responseText === "['BAD CSRF']") {
|
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
|
// 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
|
// For cached pages we strip out CSRF tokens, need to round trip to server prior to sending the
|
||||||
// request (bypass for GET, not needed)
|
// 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){
|
return Ember.Deferred.promise(function(promise){
|
||||||
$.ajax(Discourse.getURL('/session/csrf'))
|
$.ajax(Discourse.getURL('/session/csrf'))
|
||||||
.success(function(result){
|
.success(function(result){
|
||||||
|
|
|
@ -104,7 +104,7 @@ d.write('<style>#ember-testing-container { position: absolute; background: white
|
||||||
Discourse.rootElement = '#ember-testing';
|
Discourse.rootElement = '#ember-testing';
|
||||||
Discourse.setupForTesting();
|
Discourse.setupForTesting();
|
||||||
Discourse.injectTestHelpers();
|
Discourse.injectTestHelpers();
|
||||||
Discourse.bindDOMEvents();
|
Discourse.runInitializers();
|
||||||
|
|
||||||
Discourse.Router.map(function() {
|
Discourse.Router.map(function() {
|
||||||
Discourse.routeBuilder.call(this);
|
Discourse.routeBuilder.call(this);
|
||||||
|
|
Loading…
Reference in New Issue