diff --git a/app/assets/javascripts/discourse/initializers/inject-objects.js.es6 b/app/assets/javascripts/discourse/initializers/inject-objects.js.es6 index 31933358d5b..885a3edd14a 100644 --- a/app/assets/javascripts/discourse/initializers/inject-objects.js.es6 +++ b/app/assets/javascripts/discourse/initializers/inject-objects.js.es6 @@ -1,11 +1,12 @@ import Session from 'discourse/models/session'; +import AppEvents from 'discourse/lib/app-events'; export default { name: "inject-objects", initialize: function(container, application) { // Inject appEvents everywhere - var appEvents = Ember.Object.createWithMixins(Ember.Evented); + var appEvents = AppEvents.create(); application.register('app-events:main', appEvents, { instantiate: false }); application.inject('controller', 'appEvents', 'app-events:main'); diff --git a/app/assets/javascripts/discourse/lib/app-events.js.es6 b/app/assets/javascripts/discourse/lib/app-events.js.es6 new file mode 100644 index 00000000000..26135d3f7c5 --- /dev/null +++ b/app/assets/javascripts/discourse/lib/app-events.js.es6 @@ -0,0 +1,23 @@ +export default Ember.Object.extend(Ember.Evented); + +var id = 1; +function newKey() { + return "_view_app_event_" + (id++); +} + +export function createViewListener(eventName, cb) { + var extension = {}; + extension[newKey()] = function() { + this.appEvents.on(eventName, this, cb); + }.on('didInsertElement'); + + extension[newKey()] = function() { + this.appEvents.off(eventName, this, cb); + }.on('willDestroyElement'); + + return extension; +} + +export function listenForViewEvent(viewClass, eventName, cb) { + viewClass.reopen(createViewListener(eventName, cb)); +} diff --git a/app/assets/javascripts/discourse/lib/url.js b/app/assets/javascripts/discourse/lib/url.js index 8c6b1dcccb7..2c6c212a284 100644 --- a/app/assets/javascripts/discourse/lib/url.js +++ b/app/assets/javascripts/discourse/lib/url.js @@ -2,7 +2,7 @@ var jumpScheduled = false, rewrites = []; -Discourse.URL = Em.Object.createWithMixins({ +Discourse.URL = Ember.Object.createWithMixins({ // Used for matching a topic TOPIC_REGEXP: /\/t\/([^\/]+)\/(\d+)\/?(\d+)?/, @@ -210,10 +210,10 @@ Discourse.URL = Em.Object.createWithMixins({ if (path.match(/last$/)) { opts.nearPost = topicController.get('highest_post_number'); } var closest = opts.nearPost || 1; + var self = this; postStream.refresh(opts).then(function() { topicController.setProperties({ currentPost: closest, - highlightOnInsert: closest, enteredAt: new Date().getTime().toString() }); var closestPost = postStream.closestPostForPostNumber(closest), @@ -221,7 +221,7 @@ Discourse.URL = Em.Object.createWithMixins({ progressController = container.lookup('controller:topic-progress'); progressController.set('progressPosition', progress); - Discourse.PostView.considerHighlighting(topicController, closest); + self.appEvents.trigger('post:highlight', closest); }).then(function() { Discourse.URL.jumpToPost(closest); }); diff --git a/app/assets/javascripts/discourse/mixins/url-refresh.js.es6 b/app/assets/javascripts/discourse/mixins/url-refresh.js.es6 index 389f60c76da..e5ab51cb3db 100644 --- a/app/assets/javascripts/discourse/mixins/url-refresh.js.es6 +++ b/app/assets/javascripts/discourse/mixins/url-refresh.js.es6 @@ -4,16 +4,9 @@ // // This is useful if you want to get around Ember's default // behavior of not refreshing when navigating to the same place. -export default Em.Mixin.create({ - _initURLRefresh: function() { - this.appEvents.on('url:refresh', this, '_urlRefresh'); - }.on('didInsertElement'), - _tearDownURLRefresh: function() { - this.appEvents.off('url:refresh', this, '_urlRefresh'); - }.on('willDestroyElement'), +import { createViewListener } from 'discourse/lib/app-events'; - _urlRefresh: function() { - this.get('controller').send('refresh'); - } +export default createViewListener('url:refresh', function() { + this.get('controller').send('refresh'); }); diff --git a/app/assets/javascripts/discourse/routes/topic-from-params.js.es6 b/app/assets/javascripts/discourse/routes/topic-from-params.js.es6 index 0f648039ba8..cd6acccc815 100644 --- a/app/assets/javascripts/discourse/routes/topic-from-params.js.es6 +++ b/app/assets/javascripts/discourse/routes/topic-from-params.js.es6 @@ -1,5 +1,4 @@ // This route is used for retrieving a topic based on params - export default Discourse.Route.extend({ setupController: function(controller, params) { @@ -15,6 +14,7 @@ export default Discourse.Route.extend({ // I sincerely hope no topic gets this many posts if (params.nearPost === "last") { params.nearPost = 999999999; } + var self = this; postStream.refresh(params).then(function () { // TODO we are seeing errors where closest post is null and this is exploding @@ -28,13 +28,13 @@ export default Discourse.Route.extend({ topicController.setProperties({ currentPost: closest, enteredAt: new Date().getTime().toString(), - highlightOnInsert: closest }); topicProgressController.setProperties({ progressPosition: progress, expanded: false }); + self.appEvents.trigger('post:highlight', closest); Discourse.URL.jumpToPost(closest); if (topic.present('draft')) { diff --git a/app/assets/javascripts/discourse/views/post_view.js b/app/assets/javascripts/discourse/views/post.js.es6 similarity index 89% rename from app/assets/javascripts/discourse/views/post_view.js rename to app/assets/javascripts/discourse/views/post.js.es6 index 77806e1074c..879f51b6760 100644 --- a/app/assets/javascripts/discourse/views/post_view.js +++ b/app/assets/javascripts/discourse/views/post.js.es6 @@ -1,6 +1,6 @@ var DAY = 60 * 50 * 1000; -Discourse.PostView = Discourse.GroupedView.extend(Ember.Evented, { +var PostView = Discourse.GroupedView.extend(Ember.Evented, { classNames: ['topic-post', 'clearfix'], templateName: 'post', classNameBindings: ['postTypeClass', @@ -175,11 +175,7 @@ Discourse.PostView = Discourse.GroupedView.extend(Ember.Evented, { }, actions: { - /** - Toggle the replies this post is a reply to - - @method showReplyHistory - **/ + // Toggle the replies this post is a reply to toggleReplyHistory: function(post) { var replyHistory = post.get('replyHistory'), @@ -203,7 +199,7 @@ Discourse.PostView = Discourse.GroupedView.extend(Ember.Evented, { } Em.run.next(function() { - Discourse.PostView.highlight(replyPostNumber); + PostView.highlight(replyPostNumber); $(window).scrollTop(self.$().position().top - offsetFromTop); }); return; @@ -267,15 +263,7 @@ Discourse.PostView = Discourse.GroupedView.extend(Ember.Evented, { this._showLinkCounts(); - // Track this post Discourse.ScreenTrack.current().track(this.$().prop('id'), postNumber); - - // Highlight the post if required - if (postNumber > 1) { - Discourse.PostView.considerHighlighting(this.get('controller'), postNumber); - } - - // Add syntax highlighting Discourse.SyntaxHighlighting.apply($post); Discourse.Lightbox.apply($post); @@ -307,27 +295,4 @@ Discourse.PostView = Discourse.GroupedView.extend(Ember.Evented, { }.observes('controller.searchHighlight', 'cooked') }); -function highlight(postNumber) { - var $contents = $('#post_' + postNumber +' .topic-body'), - origColor = $contents.data('orig-color') || $contents.css('backgroundColor'); - - $contents.data("orig-color", origColor) - .addClass('highlighted') - .stop() - .animate({ backgroundColor: origColor }, 2500, 'swing', function(){ - $contents.removeClass('highlighted'); - $contents.css({'background-color': ''}); - }); -} - -Discourse.PostView.reopenClass({ - considerHighlighting: function(controller, postNumber) { - var highlightNumber = controller.get('highlightOnInsert'); - - // If we're meant to highlight a post - if (highlightNumber === postNumber) { - controller.set('highlightOnInsert', null); - Ember.run.scheduleOnce('afterRender', null, highlight, postNumber); - } - } -}); +export default PostView; diff --git a/app/assets/javascripts/discourse/views/topic.js.es6 b/app/assets/javascripts/discourse/views/topic.js.es6 index 76733c7950a..66e73adb49d 100644 --- a/app/assets/javascripts/discourse/views/topic.js.es6 +++ b/app/assets/javascripts/discourse/views/topic.js.es6 @@ -1,6 +1,7 @@ import AddCategoryClass from 'discourse/mixins/add-category-class'; +import { listenForViewEvent } from 'discourse/lib/app-events'; -export default Discourse.View.extend(AddCategoryClass, Discourse.Scrolling, { +var TopicView = Discourse.View.extend(AddCategoryClass, Discourse.Scrolling, { templateName: 'topic', topicBinding: 'controller.model', userFiltersBinding: 'controller.userFilters', @@ -157,3 +158,22 @@ export default Discourse.View.extend(AddCategoryClass, Discourse.Scrolling, { } }.property('topicTrackingState.messageCount') }); + +function highlight(postNumber) { + var $contents = $('#post_' + postNumber +' .topic-body'), + origColor = $contents.data('orig-color') || $contents.css('backgroundColor'); + + $contents.data("orig-color", origColor) + .addClass('highlighted') + .stop() + .animate({ backgroundColor: origColor }, 2500, 'swing', function(){ + $contents.removeClass('highlighted'); + $contents.css({'background-color': ''}); + }); +} + +listenForViewEvent(TopicView, 'post:highlight', function(postNumber) { + Ember.run.scheduleOnce('afterRender', null, highlight, postNumber); +}); + +export default TopicView; diff --git a/app/assets/javascripts/main_include.js b/app/assets/javascripts/main_include.js index 5759d7a9625..23b70b106c8 100644 --- a/app/assets/javascripts/main_include.js +++ b/app/assets/javascripts/main_include.js @@ -10,6 +10,7 @@ // // Stuff we need to load first +//= require ./discourse/lib/app-events //= require ./discourse/helpers/i18n //= require ./discourse/lib/ember_compat_handlebars //= require ./discourse/lib/computed diff --git a/plugins/poll/assets/javascripts/initializers/poll.js.es6 b/plugins/poll/assets/javascripts/initializers/poll.js.es6 index 61bdeb321f3..701b6edad18 100644 --- a/plugins/poll/assets/javascripts/initializers/poll.js.es6 +++ b/plugins/poll/assets/javascripts/initializers/poll.js.es6 @@ -1,4 +1,5 @@ import PollController from "discourse/plugins/poll/controllers/poll"; +import PostView from "discourse/views/post"; var Poll = Discourse.Model.extend({ post: null, @@ -71,7 +72,7 @@ export default { name: 'poll', initialize: function() { - Discourse.PostView.reopen({ + PostView.reopen({ createPollUI: function($post) { var post = this.get('post');