A mucher saner API for updating the title of routes, even when nested.
Properly sends the title of the page to google analytics
This commit is contained in:
parent
e8637344c3
commit
5fc150e057
|
@ -1,17 +1,9 @@
|
||||||
/**
|
|
||||||
The base admin route
|
|
||||||
|
|
||||||
@class AdminRoute
|
|
||||||
@extends Discourse.Route
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.AdminRoute = Discourse.Route.extend({
|
Discourse.AdminRoute = Discourse.Route.extend({
|
||||||
renderTemplate: function() {
|
renderTemplate: function() {
|
||||||
this.render('admin/templates/admin');
|
this.render('admin/templates/admin');
|
||||||
},
|
},
|
||||||
|
|
||||||
activate: function() {
|
titleToken: function() {
|
||||||
Discourse.set('title', I18n.t('admin_title'));
|
return I18n.t('admin_title');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,6 +10,7 @@ var DiscourseResolver = require('discourse/ember/resolver').default;
|
||||||
|
|
||||||
window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||||
rootElement: '#main',
|
rootElement: '#main',
|
||||||
|
_docTitle: null,
|
||||||
|
|
||||||
getURL: function(url) {
|
getURL: function(url) {
|
||||||
// If it's a non relative URL, return it.
|
// If it's a non relative URL, return it.
|
||||||
|
@ -25,13 +26,8 @@ window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||||
|
|
||||||
Resolver: DiscourseResolver,
|
Resolver: DiscourseResolver,
|
||||||
|
|
||||||
titleChanged: function() {
|
_titleChanged: function() {
|
||||||
var title = "";
|
var title = this.get('_docTitle') || Discourse.SiteSettings.title;
|
||||||
|
|
||||||
if (this.get('title')) {
|
|
||||||
title += "" + (this.get('title')) + " - ";
|
|
||||||
}
|
|
||||||
title += Discourse.SiteSettings.title;
|
|
||||||
|
|
||||||
// if we change this we can trigger changes on document.title
|
// if we change this we can trigger changes on document.title
|
||||||
// only set if changed.
|
// only set if changed.
|
||||||
|
@ -44,14 +40,14 @@ window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
||||||
title = "(" + notifyCount + ") " + title;
|
title = "(" + notifyCount + ") " + title;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(title !== document.title) {
|
if (title !== document.title) {
|
||||||
// chrome bug workaround see: http://stackoverflow.com/questions/2952384/changing-the-window-title-when-focussing-the-window-doesnt-work-in-chrome
|
// chrome bug workaround see: http://stackoverflow.com/questions/2952384/changing-the-window-title-when-focussing-the-window-doesnt-work-in-chrome
|
||||||
window.setTimeout(function() {
|
window.setTimeout(function() {
|
||||||
document.title = ".";
|
document.title = ".";
|
||||||
document.title = title;
|
document.title = title;
|
||||||
}, 200);
|
}, 200);
|
||||||
}
|
}
|
||||||
}.observes('title', 'hasFocus', 'notifyCount'),
|
}.observes('_docTitle', 'hasFocus', 'notifyCount'),
|
||||||
|
|
||||||
faviconChanged: function() {
|
faviconChanged: function() {
|
||||||
if(Discourse.User.currentProp('dynamic_favicon')) {
|
if(Discourse.User.currentProp('dynamic_favicon')) {
|
||||||
|
|
|
@ -11,11 +11,21 @@ export default ObjectController.extend(Discourse.SelectedPostsCount, {
|
||||||
|
|
||||||
maxTitleLength: Discourse.computed.setting('max_topic_title_length'),
|
maxTitleLength: Discourse.computed.setting('max_topic_title_length'),
|
||||||
|
|
||||||
contextChanged: function(){
|
contextChanged: function() {
|
||||||
this.set('controllers.search.searchContext', this.get('model.searchContext'));
|
this.set('controllers.search.searchContext', this.get('model.searchContext'));
|
||||||
}.observes('topic'),
|
}.observes('topic'),
|
||||||
|
|
||||||
termChanged: function(){
|
_titleChanged: function() {
|
||||||
|
var title = this.get('title');
|
||||||
|
if (!Em.empty(title)) {
|
||||||
|
|
||||||
|
// Note normally you don't have to trigger this, but topic titles can be updated
|
||||||
|
// and are sometimes lazily loaded.
|
||||||
|
this.send('refreshTitle');
|
||||||
|
}
|
||||||
|
}.observes('title'),
|
||||||
|
|
||||||
|
termChanged: function() {
|
||||||
var dropdown = this.get('controllers.header.visibleDropdown');
|
var dropdown = this.get('controllers.header.visibleDropdown');
|
||||||
var term = this.get('controllers.search.term');
|
var term = this.get('controllers.search.term');
|
||||||
|
|
||||||
|
|
|
@ -12,16 +12,18 @@ export default {
|
||||||
// Out of the box, Discourse tries to track google analytics
|
// Out of the box, Discourse tries to track google analytics
|
||||||
// if it is present
|
// if it is present
|
||||||
if (typeof window._gaq !== 'undefined') {
|
if (typeof window._gaq !== 'undefined') {
|
||||||
pageTracker.on('change', function() {
|
pageTracker.on('change', function(url, title) {
|
||||||
window._gaq.push(['_trackPageview', window.location.pathname+window.location.search]);
|
window._gaq.push(["_set", "title", title]);
|
||||||
|
window._gaq.push(['_trackPageview', url]);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Also use Universal Analytics if it is present
|
// Also use Universal Analytics if it is present
|
||||||
if (typeof window.ga !== 'undefined') {
|
if (typeof window.ga !== 'undefined') {
|
||||||
pageTracker.on('change', function() {
|
pageTracker.on('change', function(url, title) {
|
||||||
window.ga('send', 'pageview', window.location.pathname+window.location.search);
|
window.ga('send', 'pageview', {page: url, title: title});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,8 @@ Discourse.PageTracker = Ember.Object.extend(Ember.Evented, {
|
||||||
self = this;
|
self = this;
|
||||||
|
|
||||||
router.on('didTransition', function() {
|
router.on('didTransition', function() {
|
||||||
var router = this;
|
this.send('refreshTitle');
|
||||||
self.trigger('change', router.get('url'));
|
self.trigger('change', this.get('url'), Discourse.get('_docTitle'));
|
||||||
});
|
});
|
||||||
this.set('started', true);
|
this.set('started', true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,7 @@ export default Discourse.Route.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController: function(controller, model) {
|
titleToken: function() {
|
||||||
controller.set('model', model);
|
return I18n.t('about.simple_title');
|
||||||
Discourse.set('title', I18n.t('about.simple_title'));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
var ApplicationRoute = Em.Route.extend({
|
var ApplicationRoute = Em.Route.extend({
|
||||||
|
|
||||||
|
siteTitle: Discourse.computed.setting('title'),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
_collectTitleTokens: function(tokens) {
|
||||||
|
tokens.push(this.get('siteTitle'));
|
||||||
|
Discourse.set('_docTitle', tokens.join(' - '));
|
||||||
|
},
|
||||||
|
|
||||||
showTopicEntrance: function(data) {
|
showTopicEntrance: function(data) {
|
||||||
this.controllerFor('topic-entrance').send('show', data);
|
this.controllerFor('topic-entrance').send('show', data);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
export default Discourse.Route.extend({
|
export default Discourse.Route.extend({
|
||||||
|
|
||||||
model: function() {
|
model: function() {
|
||||||
if (PreloadStore.get('badges')) {
|
if (PreloadStore.get('badges')) {
|
||||||
return PreloadStore.getAndRemove('badges').then(function(json) {
|
return PreloadStore.getAndRemove('badges').then(function(json) {
|
||||||
|
@ -10,8 +9,7 @@ export default Discourse.Route.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController: function(controller, model) {
|
titleToken: function() {
|
||||||
controller.set('model', model);
|
return I18n.t('badges.title');
|
||||||
Discourse.set('title', I18n.t('badges.title'));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export default Ember.Route.extend({
|
export default Discourse.Route.extend({
|
||||||
serialize: function(model) {
|
serialize: function(model) {
|
||||||
return {id: model.get('id'), slug: model.get('name').replace(/[^A-Za-z0-9_]+/g, '-').toLowerCase()};
|
return {id: model.get('id'), slug: model.get('name').replace(/[^A-Za-z0-9_]+/g, '-').toLowerCase()};
|
||||||
},
|
},
|
||||||
|
@ -13,12 +13,18 @@ export default Ember.Route.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
titleToken: function() {
|
||||||
|
var model = this.modelFor('badges.show');
|
||||||
|
if (model) {
|
||||||
|
return model.get('displayName');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
setupController: function(controller, model) {
|
setupController: function(controller, model) {
|
||||||
Discourse.UserBadge.findByBadgeId(model.get('id')).then(function(userBadges) {
|
Discourse.UserBadge.findByBadgeId(model.get('id')).then(function(userBadges) {
|
||||||
controller.set('userBadges', userBadges);
|
controller.set('userBadges', userBadges);
|
||||||
controller.set('userBadgesLoaded', true);
|
controller.set('userBadgesLoaded', true);
|
||||||
});
|
});
|
||||||
controller.set('model', model);
|
controller.set('model', model);
|
||||||
Discourse.set('title', model.get('displayName'));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -61,13 +61,17 @@ export default function(filter, params) {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
titleToken: function() {
|
||||||
|
var filterText = I18n.t('filters.' + filter.replace('/', '.') + '.title', {count: 0}),
|
||||||
|
model = this.currentModel;
|
||||||
|
|
||||||
|
return I18n.t('filters.with_category', { filter: filterText, category: model.get('name') });
|
||||||
|
},
|
||||||
|
|
||||||
setupController: function(controller, model) {
|
setupController: function(controller, model) {
|
||||||
var topics = this.get('topics'),
|
var topics = this.get('topics'),
|
||||||
periods = this.controllerFor('discovery').get('periods'),
|
periods = this.controllerFor('discovery').get('periods'),
|
||||||
periodId = topics.get('for_period') || (filter.indexOf('/') > 0 ? filter.split('/')[1] : ''),
|
periodId = topics.get('for_period') || (filter.indexOf('/') > 0 ? filter.split('/')[1] : '');
|
||||||
filterText = I18n.t('filters.' + filter.replace('/', '.') + '.title', {count: 0});
|
|
||||||
|
|
||||||
Discourse.set('title', I18n.t('filters.with_category', { filter: filterText, category: model.get('name') }));
|
|
||||||
|
|
||||||
this.controllerFor('navigation/category').set('canCreateTopic', topics.get('can_create_topic'));
|
this.controllerFor('navigation/category').set('canCreateTopic', topics.get('can_create_topic'));
|
||||||
this.controllerFor('discovery/topics').setProperties({
|
this.controllerFor('discovery/topics').setProperties({
|
||||||
|
|
|
@ -32,6 +32,13 @@ export default function(filter, extras) {
|
||||||
return Discourse.TopicList.list(filter, findOpts, extras);
|
return Discourse.TopicList.list(filter, findOpts, extras);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
titleToken: function() {
|
||||||
|
if (filter === Discourse.Utilities.defaultHomepage()) { return; }
|
||||||
|
|
||||||
|
var filterText = I18n.t('filters.' + filter.replace('/', '.') + '.title', {count: 0});
|
||||||
|
return I18n.t('filters.with_topics', {filter: filterText});
|
||||||
|
},
|
||||||
|
|
||||||
setupController: function(controller, model, trans) {
|
setupController: function(controller, model, trans) {
|
||||||
|
|
||||||
controller.setProperties(Em.getProperties(trans, _.keys(queryParams).map(function(v){
|
controller.setProperties(Em.getProperties(trans, _.keys(queryParams).map(function(v){
|
||||||
|
@ -39,14 +46,7 @@ export default function(filter, extras) {
|
||||||
})));
|
})));
|
||||||
|
|
||||||
var periods = this.controllerFor('discovery').get('periods'),
|
var periods = this.controllerFor('discovery').get('periods'),
|
||||||
periodId = model.get('for_period') || (filter.indexOf('/') > 0 ? filter.split('/')[1] : ''),
|
periodId = model.get('for_period') || (filter.indexOf('/') > 0 ? filter.split('/')[1] : '');
|
||||||
filterText = I18n.t('filters.' + filter.replace('/', '.') + '.title', {count: 0});
|
|
||||||
|
|
||||||
if (filter === Discourse.Utilities.defaultHomepage()) {
|
|
||||||
Discourse.set('title', '');
|
|
||||||
} else {
|
|
||||||
Discourse.set('title', I18n.t('filters.with_topics', {filter: filterText}));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.controllerFor('discovery/topics').setProperties({
|
this.controllerFor('discovery/topics').setProperties({
|
||||||
model: model,
|
model: model,
|
||||||
|
|
|
@ -21,6 +21,29 @@ Discourse.Route = Em.Route.extend({
|
||||||
Em.run.scheduleOnce('afterRender', Discourse.Route, 'cleanDOM');
|
Em.run.scheduleOnce('afterRender', Discourse.Route, 'cleanDOM');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
_collectTitleTokens: function(tokens) {
|
||||||
|
// If there's a title token method, call it and get the token
|
||||||
|
if (this.titleToken) {
|
||||||
|
var t = this.titleToken();
|
||||||
|
if (t && t.length) {
|
||||||
|
if (t instanceof Array) {
|
||||||
|
t.forEach(function(ti) {
|
||||||
|
tokens.push(ti);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
tokens.push(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
refreshTitle: function() {
|
||||||
|
this.send('_collectTitleTokens', []);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
redirectIfLoginRequired: function() {
|
redirectIfLoginRequired: function() {
|
||||||
var app = this.controllerFor('application');
|
var app = this.controllerFor('application');
|
||||||
if (app.get('loginRequired')) {
|
if (app.get('loginRequired')) {
|
||||||
|
|
|
@ -1,11 +1,3 @@
|
||||||
/**
|
|
||||||
The route for handling the "Categories" view
|
|
||||||
|
|
||||||
@class DiscoveryCategoriesRoute
|
|
||||||
@extends Discourse.Route
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.DiscoveryCategoriesRoute = Discourse.Route.extend(Discourse.OpenComposer, {
|
Discourse.DiscoveryCategoriesRoute = Discourse.Route.extend(Discourse.OpenComposer, {
|
||||||
renderTemplate: function() {
|
renderTemplate: function() {
|
||||||
this.render('navigation/categories', { outlet: 'navigation-bar' });
|
this.render('navigation/categories', { outlet: 'navigation-bar' });
|
||||||
|
@ -31,16 +23,18 @@ Discourse.DiscoveryCategoriesRoute = Discourse.Route.extend(Discourse.OpenCompos
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
titleToken: function() {
|
||||||
|
return I18n.t('filters.categories.title');
|
||||||
|
},
|
||||||
|
|
||||||
setupController: function(controller, model) {
|
setupController: function(controller, model) {
|
||||||
controller.set('model', model);
|
controller.set('model', model);
|
||||||
Discourse.set('title', I18n.t('filters.categories.title'));
|
|
||||||
|
|
||||||
// Only show either the Create Category or Create Topic button
|
// Only show either the Create Category or Create Topic button
|
||||||
this.controllerFor('navigation/categories').set('canCreateCategory', model.get('can_create_category'));
|
this.controllerFor('navigation/categories').set('canCreateCategory', model.get('can_create_category'));
|
||||||
this.controllerFor('navigation/categories').set('canCreateTopic', model.get('can_create_topic') && !model.get('can_create_category'));
|
this.controllerFor('navigation/categories').set('canCreateTopic', model.get('can_create_topic') && !model.get('can_create_category'));
|
||||||
|
|
||||||
this.openTopicDraft(model);
|
this.openTopicDraft(model);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|
|
@ -12,7 +12,15 @@ Discourse.TopicRoute = Discourse.Route.extend({
|
||||||
show_deleted: { replace: true }
|
show_deleted: { replace: true }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
titleToken: function() {
|
||||||
|
var model = this.modelFor('topic');
|
||||||
|
if (model) {
|
||||||
|
return model.get('title');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|
||||||
showTopicAdminMenu: function() {
|
showTopicAdminMenu: function() {
|
||||||
this.controllerFor("topic-admin-menu").send("show");
|
this.controllerFor("topic-admin-menu").send("show");
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
export default Discourse.Route.extend({
|
export default Discourse.Route.extend({
|
||||||
|
|
||||||
|
titleToken: function() {
|
||||||
|
var model = this.modelFor('user');
|
||||||
|
var username = model.get('username');
|
||||||
|
if (username) {
|
||||||
|
return [I18n.t("user.profile"), username];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
logout: function() {
|
logout: function() {
|
||||||
Discourse.logout();
|
Discourse.logout();
|
||||||
|
|
|
@ -17,11 +17,6 @@ export default Discourse.View.extend(AddCategoryClass, Discourse.Scrolling, {
|
||||||
|
|
||||||
postStream: Em.computed.alias('controller.postStream'),
|
postStream: Em.computed.alias('controller.postStream'),
|
||||||
|
|
||||||
_updateTitle: function() {
|
|
||||||
var title = this.get('topic.title');
|
|
||||||
if (title) return Discourse.set('title', _.unescape(title));
|
|
||||||
}.observes('topic.loaded', 'topic.title'),
|
|
||||||
|
|
||||||
_composeChanged: function() {
|
_composeChanged: function() {
|
||||||
var composerController = Discourse.get('router.composerController');
|
var composerController = Discourse.get('router.composerController');
|
||||||
composerController.clearState();
|
composerController.clearState();
|
||||||
|
|
|
@ -1,11 +1,4 @@
|
||||||
export default Ember.View.extend(Discourse.ScrollTop, {
|
export default Ember.View.extend(Discourse.ScrollTop, {
|
||||||
templateName: 'user/user',
|
templateName: 'user/user',
|
||||||
userBinding: 'controller.content',
|
userBinding: 'controller.content'
|
||||||
|
|
||||||
updateTitle: function() {
|
|
||||||
var username = this.get('user.username');
|
|
||||||
if (username) {
|
|
||||||
Discourse.set('title', "" + (I18n.t("user.profile")) + " - " + username);
|
|
||||||
}
|
|
||||||
}.observes('user.loaded', 'user.username')
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue