From 69bb70fbd35e3b8553d6996fd5c0d77dcb417602 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Fri, 24 May 2013 11:22:17 -0400 Subject: [PATCH 1/4] Removed bindings to `Discourse.site` --- app/assets/javascripts/discourse.js | 9 ++++--- .../controllers/composer_controller.js | 4 ++++ .../controllers/header_controller.js | 6 ++++- .../discourse/controllers/list_controller.js | 8 ++----- .../discourse/controllers/topic_controller.js | 3 +++ .../javascripts/discourse/models/archetype.js | 6 ++--- .../javascripts/discourse/models/category.js | 5 ++++ .../javascripts/discourse/models/composer.js | 11 +++++---- .../javascripts/discourse/models/nav_item.js | 2 +- .../discourse/models/notification.js | 3 +-- .../javascripts/discourse/models/post.js | 16 ++++++------- .../javascripts/discourse/models/site.js | 14 ++++------- .../javascripts/discourse/models/topic.js | 24 +++++++++---------- .../javascripts/discourse/models/user.js | 2 +- .../discourse/routes/application_route.js | 3 +-- .../discourse/routes/list_category_route.js | 3 +-- .../templates/composer.js.handlebars | 2 +- .../discourse/templates/header.js.handlebars | 4 ++-- .../discourse/templates/topic.js.handlebars | 2 +- .../discourse/views/header_view.js | 2 -- .../discourse/views/list/list_view.js | 5 ++-- .../views/modal/edit_category_view.js | 9 +++---- .../discourse/views/modal/flag_view.js | 2 +- .../discourse/views/modal/login_view.js | 6 ++++- .../javascripts/discourse/views/post_view.js | 2 +- .../javascripts/discourse/views/topic_view.js | 1 - 26 files changed, 82 insertions(+), 72 deletions(-) diff --git a/app/assets/javascripts/discourse.js b/app/assets/javascripts/discourse.js index 58072742843..0b3d018cbbc 100644 --- a/app/assets/javascripts/discourse.js +++ b/app/assets/javascripts/discourse.js @@ -73,11 +73,14 @@ Discourse = Ember.Application.createWithMixins({ 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){ - Discourse.get('site').set('categories', data.categories.map(function(c){ - return Discourse.Category.create(c); - })); + var site = Discourse.Site.instance(); + data.categories.each(function(c){ + site.updateCategory(c) + }); }); + } }.observes('currentUser'), diff --git a/app/assets/javascripts/discourse/controllers/composer_controller.js b/app/assets/javascripts/discourse/controllers/composer_controller.js index f209d5cc84e..688a28d10a2 100644 --- a/app/assets/javascripts/discourse/controllers/composer_controller.js +++ b/app/assets/javascripts/discourse/controllers/composer_controller.js @@ -27,6 +27,10 @@ Discourse.ComposerController = Discourse.Controller.extend({ if (c) return c.appendText(text); }, + categories: function() { + return Discourse.Category.list(); + }.property(), + save: function(force) { var composer, _this = this, diff --git a/app/assets/javascripts/discourse/controllers/header_controller.js b/app/assets/javascripts/discourse/controllers/header_controller.js index 6d60c8437db..57529bb471a 100644 --- a/app/assets/javascripts/discourse/controllers/header_controller.js +++ b/app/assets/javascripts/discourse/controllers/header_controller.js @@ -14,7 +14,11 @@ Discourse.HeaderController = Discourse.Controller.extend({ var topic = this.get('topic'); if (topic) topic.toggleStar(); return false; - } + }, + + categories: function() { + return Discourse.Category.list(); + }.property() }); diff --git a/app/assets/javascripts/discourse/controllers/list_controller.js b/app/assets/javascripts/discourse/controllers/list_controller.js index 9c9bc4b4229..c781917f03f 100644 --- a/app/assets/javascripts/discourse/controllers/list_controller.js +++ b/app/assets/javascripts/discourse/controllers/list_controller.js @@ -8,21 +8,17 @@ **/ Discourse.ListController = Discourse.Controller.extend({ currentUserBinding: 'Discourse.currentUser', - categoriesBinding: 'Discourse.site.categories', categoryBinding: 'topicList.category', canCreateCategory: false, canCreateTopic: false, needs: ['composer', 'modal', 'listTopics'], availableNavItems: function() { - var hasCategories, loggedOn, summary; - summary = this.get('filterSummary'); - loggedOn = !!Discourse.get('currentUser'); - hasCategories = !!this.get('categories'); + var summary = this.get('filterSummary'); + var loggedOn = !!Discourse.get('currentUser'); return Discourse.SiteSettings.top_menu.split("|").map(function(i) { return Discourse.NavItem.fromText(i, { loggedOn: loggedOn, - hasCategories: hasCategories, countSummary: summary }); }).filter(function(i) { diff --git a/app/assets/javascripts/discourse/controllers/topic_controller.js b/app/assets/javascripts/discourse/controllers/topic_controller.js index 0f941d23832..ead6a0b02c4 100644 --- a/app/assets/javascripts/discourse/controllers/topic_controller.js +++ b/app/assets/javascripts/discourse/controllers/topic_controller.js @@ -29,6 +29,9 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected return (this.get('selectedPostsCount') > 0); }.property('selectedPostsCount'), + categories: function() { + return Discourse.Category.list(); + }.property(), canSelectAll: Em.computed.not('allPostsSelected'), diff --git a/app/assets/javascripts/discourse/models/archetype.js b/app/assets/javascripts/discourse/models/archetype.js index 0ff2cb78d25..dd6f07b0051 100644 --- a/app/assets/javascripts/discourse/models/archetype.js +++ b/app/assets/javascripts/discourse/models/archetype.js @@ -13,9 +13,9 @@ Discourse.Archetype = Discourse.Model.extend({ return this.get('options').length > 0; }).property('options.@each'), - isDefault: (function() { - return this.get('id') === Discourse.get('site.default_archetype'); - }).property('id') + isDefault: function() { + return this.get('id') === Discourse.Site.instance().get('default_archetype'); + }.property('id') }); diff --git a/app/assets/javascripts/discourse/models/category.js b/app/assets/javascripts/discourse/models/category.js index 24db481ed85..96a995c5dd9 100644 --- a/app/assets/javascripts/discourse/models/category.js +++ b/app/assets/javascripts/discourse/models/category.js @@ -70,6 +70,11 @@ Discourse.Category = Discourse.Model.extend({ }); Discourse.Category.reopenClass({ + + list: function() { + return Discourse.Site.instance().get('categories'); + }, + findBySlugOrId: function(slugOrId) { return Discourse.ajax("/categories/" + slugOrId + ".json").then(function (result) { return Discourse.Category.create(result.category); diff --git a/app/assets/javascripts/discourse/models/composer.js b/app/assets/javascripts/discourse/models/composer.js index e4d7d51590b..c4a287379b6 100644 --- a/app/assets/javascripts/discourse/models/composer.js +++ b/app/assets/javascripts/discourse/models/composer.js @@ -22,15 +22,18 @@ EDIT = 'edit'; REPLY_AS_NEW_TOPIC_KEY = "reply_as_new_topic"; Discourse.Composer = Discourse.Model.extend({ - archetypesBinding: 'Discourse.site.archetypes', init: function() { this._super(); var val = Discourse.KeyValueStore.get('composer.showPreview') || 'true'; this.set('showPreview', val === 'true'); - this.set('archetypeId', Discourse.get('site.default_archetype')); + this.set('archetypeId', Discourse.Site.instance().get('default_archetype')); }, + archetypes: function() { + return Discourse.Site.instance().get('archetypes'); + }.property(), + creatingTopic: function() { return this.get('action') === CREATE_TOPIC; }.property('action'), @@ -238,7 +241,7 @@ Discourse.Composer = Discourse.Model.extend({ } this.set('categoryName', opts.categoryName || this.get('topic.category.name')); - this.set('archetypeId', opts.archetypeId || Discourse.get('site.default_archetype')); + this.set('archetypeId', opts.archetypeId || Discourse.Site.instance().get('default_archetype')); this.set('metaData', opts.metaData ? Em.Object.create(opts.metaData) : null); this.set('reply', opts.reply || this.get("reply") || ""); if (opts.postId) { @@ -354,7 +357,7 @@ Discourse.Composer = Discourse.Model.extend({ user_id: currentUser.get('id'), metaData: this.get('metaData'), archetype: this.get('archetypeId'), - post_type: Discourse.get('site.post_types.regular'), + post_type: Discourse.Site.instance().get('post_types.regular'), target_usernames: this.get('targetUsernames'), actions_summary: Em.A(), moderator: currentUser.get('moderator'), diff --git a/app/assets/javascripts/discourse/models/nav_item.js b/app/assets/javascripts/discourse/models/nav_item.js index 0e256d6658b..7d268d634d4 100644 --- a/app/assets/javascripts/discourse/models/nav_item.js +++ b/app/assets/javascripts/discourse/models/nav_item.js @@ -34,7 +34,7 @@ Discourse.NavItem.reopenClass({ testName = name.split("/")[0]; if (!opts.loggedOn && !validAnon.contains(testName)) return null; - if (!opts.hasCategories && testName === "categories") return null; + if (!Discourse.Category.list() && testName === "categories") return null; if (!validNavNames.contains(testName)) return null; opts = { diff --git a/app/assets/javascripts/discourse/models/notification.js b/app/assets/javascripts/discourse/models/notification.js index 2c44f40acdc..d1360772604 100644 --- a/app/assets/javascripts/discourse/models/notification.js +++ b/app/assets/javascripts/discourse/models/notification.js @@ -19,8 +19,7 @@ Discourse.Notification = Discourse.Model.extend({ }.property(), rendered: function() { - var notificationName; - notificationName = Discourse.get('site.notificationLookup')[this.notification_type]; + var notificationName = Discourse.Site.instance().get('notificationLookup')[this.notification_type]; return Em.String.i18n("notifications." + notificationName, { username: this.data.display_username, link: "" + this.data.topic_title + "" diff --git a/app/assets/javascripts/discourse/models/post.js b/app/assets/javascripts/discourse/models/post.js index be63fd05ab4..c86171a2c54 100644 --- a/app/assets/javascripts/discourse/models/post.js +++ b/app/assets/javascripts/discourse/models/post.js @@ -124,11 +124,11 @@ Discourse.Post = Discourse.Model.extend({ flagsAvailable: function() { var _this = this; - var flags = Discourse.get('site.flagTypes').filter(function(item) { + var flags = Discourse.Site.instance().get('flagTypes').filter(function(item) { return _this.get("actionByName." + (item.get('name_key')) + ".can_act"); }); return flags; - }.property('Discourse.site.flagTypes', 'actions_summary.@each.can_act'), + }.property('actions_summary.@each.can_act'), actionsHistory: function() { if (!this.present('actions_summary')) return null; @@ -153,7 +153,7 @@ Discourse.Post = Discourse.Model.extend({ } }).then(function(result) { // If we received a category update, update it - if (result.category) Discourse.get('site').updateCategory(result.category); + if (result.category) Discourse.Site.instance().updateCategory(result.category); if (complete) complete(Discourse.Post.create(result.post)); }, function(result) { // Post failed to update @@ -220,7 +220,7 @@ Discourse.Post = Discourse.Model.extend({ obj.actions_summary.each(function(a) { var actionSummary; a.post = post; - a.actionType = Discourse.get("site").postActionTypeById(a.id); + a.actionType = Discourse.Site.instance().postActionTypeById(a.id); actionSummary = Discourse.ActionSummary.create(a); post.get('actions_summary').pushObject(actionSummary); lookup.set(a.actionType.get('name_key'), actionSummary); @@ -278,10 +278,9 @@ Discourse.Post.reopenClass({ if (result.actions_summary) { lookup = Em.Object.create(); result.actions_summary = result.actions_summary.map(function(a) { - var actionSummary; a.post = result; - a.actionType = Discourse.get("site").postActionTypeById(a.id); - actionSummary = Discourse.ActionSummary.create(a); + a.actionType = Discourse.Site.instance().postActionTypeById(a.id); + var actionSummary = Discourse.ActionSummary.create(a); lookup.set(a.actionType.get('name_key'), actionSummary); return actionSummary; }); @@ -290,8 +289,7 @@ Discourse.Post.reopenClass({ }, create: function(obj, topic) { - var result; - result = this._super(obj); + var result = this._super(obj); this.createActionSummary(result); if (obj.reply_to_user) { result.set('reply_to_user', Discourse.User.create(obj.reply_to_user)); diff --git a/app/assets/javascripts/discourse/models/site.js b/app/assets/javascripts/discourse/models/site.js index 8f6e987599c..4ad9877cfb3 100644 --- a/app/assets/javascripts/discourse/models/site.js +++ b/app/assets/javascripts/discourse/models/site.js @@ -8,21 +8,17 @@ **/ Discourse.Site = Discourse.Model.extend({ - notificationLookup: (function() { - var result; - result = []; + notificationLookup: function() { + var result = []; Object.keys(this.get('notification_types'), function(k, v) { result[v] = k; }); return result; - }).property('notification_types'), + }.property('notification_types'), flagTypes: function() { - var postActionTypes; - postActionTypes = this.get('post_action_types'); - if (!postActionTypes) { - return []; - } + var postActionTypes = this.get('post_action_types'); + if (!postActionTypes) return []; return postActionTypes.filterProperty('is_flag', true); }.property('post_action_types.@each'), diff --git a/app/assets/javascripts/discourse/models/topic.js b/app/assets/javascripts/discourse/models/topic.js index 9ba308645c6..43a0ad5bf0b 100644 --- a/app/assets/javascripts/discourse/models/topic.js +++ b/app/assets/javascripts/discourse/models/topic.js @@ -7,12 +7,11 @@ @module Discourse **/ Discourse.Topic = Discourse.Model.extend({ - categoriesBinding: 'Discourse.site.categories', - fewParticipants: (function() { + fewParticipants: function() { if (!this.present('participants')) return null; return this.get('participants').slice(0, 3); - }).property('participants'), + }.property('participants'), canConvertToRegular: (function() { var a = this.get('archetype'); @@ -31,10 +30,8 @@ Discourse.Topic = Discourse.Model.extend({ }, category: function() { - if (this.get('categories')) { - return this.get('categories').findProperty('name', this.get('categoryName')); - } - }.property('categoryName', 'categories'), + return Discourse.Category.list().findProperty('name', this.get('categoryName')); + }.property('categoryName'), shareUrl: function(){ var user = Discourse.get('currentUser'); @@ -130,9 +127,9 @@ Discourse.Topic = Discourse.Model.extend({ return null; }.property('views'), - archetypeObject: (function() { - return Discourse.get('site.archetypes').findProperty('id', this.get('archetype')); - }).property('archetype'), + archetypeObject: function() { + return Discourse.Site.instance().get('archetypes').findProperty('id', this.get('archetype')); + }.property('archetype'), isPrivateMessage: (function() { return this.get('archetype') === 'private_message'; @@ -220,6 +217,7 @@ Discourse.Topic = Discourse.Model.extend({ // If loading the topic succeeded... var afterTopicLoaded = function(result) { + var closestPostNumber, lastPost, postDiff; // Update the slug if different @@ -246,6 +244,7 @@ Discourse.Topic = Discourse.Model.extend({ if (result.suggested_topics) { topic.set('suggested_topics', Em.A()); } + topic.mergeAttributes(result, { suggested_topics: Discourse.Topic }); topic.set('posts', Em.A()); if (opts.trackVisit && result.draft && result.draft.length > 0) { @@ -261,17 +260,18 @@ Discourse.Topic = Discourse.Model.extend({ // Okay this is weird, but let's store the length of the next post when there lastPost = null; result.posts.each(function(p) { - var post; p.scrollToAfterInsert = opts.nearPost; - post = Discourse.Post.create(p); + var post = Discourse.Post.create(p); post.set('topic', topic); topic.get('posts').pushObject(post); lastPost = post; }); + topic.set('loaded', true); } var errorLoadingTopic = function(result) { + topic.set('errorLoading', true); // If the result was 404 the post is not found diff --git a/app/assets/javascripts/discourse/models/user.js b/app/assets/javascripts/discourse/models/user.js index bc6a37e5c9a..080bb6c6379 100644 --- a/app/assets/javascripts/discourse/models/user.js +++ b/app/assets/javascripts/discourse/models/user.js @@ -92,7 +92,7 @@ Discourse.User = Discourse.Model.extend({ @type {Integer} **/ trustLevel: function() { - return Discourse.get('site.trust_levels').findProperty('id', this.get('trust_level')); + return Discourse.Site.instance().get('trust_levels').findProperty('id', this.get('trust_level')); }.property('trust_level'), /** diff --git a/app/assets/javascripts/discourse/routes/application_route.js b/app/assets/javascripts/discourse/routes/application_route.js index 19c986af410..1b067d203dd 100644 --- a/app/assets/javascripts/discourse/routes/application_route.js +++ b/app/assets/javascripts/discourse/routes/application_route.js @@ -8,8 +8,7 @@ **/ Discourse.ApplicationRoute = Discourse.Route.extend({ setupController: function(controller) { - Discourse.set('site', Discourse.Site.instance()); - + //Discourse.set('site', Discourse.Site.instance()); var currentUser = PreloadStore.get('currentUser'); if (currentUser) { Discourse.set('currentUser', Discourse.User.create(currentUser)); diff --git a/app/assets/javascripts/discourse/routes/list_category_route.js b/app/assets/javascripts/discourse/routes/list_category_route.js index c2127df8653..7ac95308382 100644 --- a/app/assets/javascripts/discourse/routes/list_category_route.js +++ b/app/assets/javascripts/discourse/routes/list_category_route.js @@ -9,10 +9,9 @@ Discourse.ListCategoryRoute = Discourse.FilteredListRoute.extend({ model: function(params) { - var categories = Discourse.Site.instance().get('categories'); + var categories = Discourse.Category.list(); var slug = Em.get(params, 'slug'); - var category = categories.findProperty('slug', Em.get(params, 'slug')) // In case the slug didn't work, try to find it by id instead. diff --git a/app/assets/javascripts/discourse/templates/composer.js.handlebars b/app/assets/javascripts/discourse/templates/composer.js.handlebars index 800fcf194f8..54361f62760 100644 --- a/app/assets/javascripts/discourse/templates/composer.js.handlebars +++ b/app/assets/javascripts/discourse/templates/composer.js.handlebars @@ -34,7 +34,7 @@ {{/if}} {{textField value=content.title tabindex="2" id="reply-title" maxlength="255" class="span8" placeholderKey="composer.title_placeholder"}} {{#unless content.creatingPrivateMessage}} - {{view Discourse.ComboboxViewCategory valueAttribute="name" contentBinding="Discourse.site.categories" valueBinding="content.categoryName"}} + {{view Discourse.ComboboxViewCategory valueAttribute="name" contentBinding="categories" valueBinding="content.categoryName"}} {{#if content.archetype.hasOptions}} {{/if}} diff --git a/app/assets/javascripts/discourse/templates/header.js.handlebars b/app/assets/javascripts/discourse/templates/header.js.handlebars index 02f31ce432a..5294b0503ab 100644 --- a/app/assets/javascripts/discourse/templates/header.js.handlebars +++ b/app/assets/javascripts/discourse/templates/header.js.handlebars @@ -77,12 +77,12 @@ {{#titledLinkTo "list.latest" titleKey="filters.latest.help"}}{{i18n filters.latest.title}}{{/titledLinkTo}}
  • {{#linkTo 'faq'}}{{i18n faq}}{{/linkTo}}
  • - {{#if view.categories}} + {{#if categories}}
  • {{#linkTo "list.categories"}}{{i18n filters.categories.title}}{{/linkTo}}
  • - {{#each view.categories}} + {{#each categories}}
  • {{categoryLink this}} {{unbound topic_count}} diff --git a/app/assets/javascripts/discourse/templates/topic.js.handlebars b/app/assets/javascripts/discourse/templates/topic.js.handlebars index ff53bf1b0d3..ed5b894e4d8 100644 --- a/app/assets/javascripts/discourse/templates/topic.js.handlebars +++ b/app/assets/javascripts/discourse/templates/topic.js.handlebars @@ -10,7 +10,7 @@ {{/if}} {{#if view.editingTopic}} - {{view Discourse.ComboboxViewCategory valueAttribute="name" contentBinding="Discourse.site.categories" sourceBinding="view.topic.categoryName"}} + {{view Discourse.ComboboxViewCategory valueAttribute="name" contentBinding="categories" sourceBinding="view.topic.categoryName"}} {{else}} diff --git a/app/assets/javascripts/discourse/views/header_view.js b/app/assets/javascripts/discourse/views/header_view.js index 924cf2073e6..afde98e8643 100644 --- a/app/assets/javascripts/discourse/views/header_view.js +++ b/app/assets/javascripts/discourse/views/header_view.js @@ -11,9 +11,7 @@ Discourse.HeaderView = Discourse.View.extend({ classNames: ['d-header', 'clearfix'], classNameBindings: ['editingTopic'], templateName: 'header', - siteBinding: 'Discourse.site', currentUserBinding: 'Discourse.currentUser', - categoriesBinding: 'site.categories', topicBinding: 'Discourse.router.topicController.content', showDropdown: function($target) { diff --git a/app/assets/javascripts/discourse/views/list/list_view.js b/app/assets/javascripts/discourse/views/list/list_view.js index d9789ceb8ee..4c8b07ff46a 100644 --- a/app/assets/javascripts/discourse/views/list/list_view.js +++ b/app/assets/javascripts/discourse/views/list/list_view.js @@ -9,7 +9,6 @@ Discourse.ListView = Discourse.View.extend({ templateName: 'list/list', composeViewBinding: Ember.Binding.oneWay('Discourse.composeView'), - categoriesBinding: 'Discourse.site.categories', // The window has been scrolled scrolled: function(e) { @@ -18,7 +17,7 @@ Discourse.ListView = Discourse.View.extend({ return currentView ? typeof currentView.scrolled === "function" ? currentView.scrolled(e) : void 0 : void 0; }, - createTopicText: (function() { + createTopicText: function() { if (this.get('controller.category.name')) { return Em.String.i18n("topic.create_in", { categoryName: this.get('controller.category.name') @@ -26,7 +25,7 @@ Discourse.ListView = Discourse.View.extend({ } else { return Em.String.i18n("topic.create"); } - }).property('controller.category.name') + }.property('controller.category.name') }); diff --git a/app/assets/javascripts/discourse/views/modal/edit_category_view.js b/app/assets/javascripts/discourse/views/modal/edit_category_view.js index 0d99c4c6b56..233a782c237 100644 --- a/app/assets/javascripts/discourse/views/modal/edit_category_view.js +++ b/app/assets/javascripts/discourse/views/modal/edit_category_view.js @@ -56,15 +56,16 @@ Discourse.EditCategoryView = Discourse.ModalBodyView.extend({ // background colors are available as a pipe-separated string backgroundColors: function() { return Discourse.SiteSettings.category_colors.split("|").map(function(i) { return i.toUpperCase(); }).concat( - Discourse.site.categories.map(function(c) { return c.color.toUpperCase(); }) ).uniq(); + categories.map(function(c) { return c.color.toUpperCase(); }) ).uniq(); }.property('Discourse.SiteSettings.category_colors'), usedBackgroundColors: function() { - return Discourse.site.categories.map(function(c) { + var categories = Discourse.Category.list(); + return categories.map(function(c) { // If editing a category, don't include its color: return (this.get('category.id') && this.get('category.color').toUpperCase() === c.color.toUpperCase()) ? null : c.color.toUpperCase(); }, this).compact(); - }.property('Discourse.site.categories', 'category.id', 'category.color'), + }.property('category.id', 'category.color'), title: function() { if (this.get('category.id')) return Em.String.i18n("category.edit_long"); @@ -97,7 +98,7 @@ Discourse.EditCategoryView = Discourse.ModalBodyView.extend({ // We need the topic_count to be correct, so get the most up-to-date info about this category from the server. Discourse.Category.findBySlugOrId( this.get('category.slug') || this.get('category.id') ).then( function(cat) { categoryView.set('category', cat); - Discourse.get('site').updateCategory(cat); + Discourse.Site.instance().updateCategory(cat); categoryView.set('id', categoryView.get('category.slug')); categoryView.set('loading', false); }); diff --git a/app/assets/javascripts/discourse/views/modal/flag_view.js b/app/assets/javascripts/discourse/views/modal/flag_view.js index 7c9ac37d7eb..20e2151a68f 100644 --- a/app/assets/javascripts/discourse/views/modal/flag_view.js +++ b/app/assets/javascripts/discourse/views/modal/flag_view.js @@ -47,7 +47,7 @@ Discourse.FlagView = Discourse.ModalBodyView.extend({ var action = this.get('selected'); var postAction = this.get('post.actionByName.' + (action.get('name_key'))); - var actionType = Discourse.get('site').postActionTypeById(this.get('postActionTypeId')); + var actionType = Discourse.Site.instance().postActionTypeById(this.get('postActionTypeId')); if (postAction) { postAction.act({ message: action.get('message') diff --git a/app/assets/javascripts/discourse/views/modal/login_view.js b/app/assets/javascripts/discourse/views/modal/login_view.js index 8bf21210f47..fd73662379c 100644 --- a/app/assets/javascripts/discourse/views/modal/login_view.js +++ b/app/assets/javascripts/discourse/views/modal/login_view.js @@ -8,11 +8,15 @@ **/ Discourse.LoginView = Discourse.ModalBodyView.extend({ templateName: 'modal/login', - siteBinding: 'Discourse.site', title: Em.String.i18n('login.title'), authenticate: null, loggingIn: false, + + site: function() { + return Discourse.Site.instance(); + }.property(), + showView: function(view) { return this.get('controller').show(view); }, diff --git a/app/assets/javascripts/discourse/views/post_view.js b/app/assets/javascripts/discourse/views/post_view.js index faadf48cdac..bb6be7f6694 100644 --- a/app/assets/javascripts/discourse/views/post_view.js +++ b/app/assets/javascripts/discourse/views/post_view.js @@ -29,7 +29,7 @@ Discourse.PostView = Discourse.View.extend({ }.property('parentView'), postTypeClass: function() { - return this.get('post.post_type') === Discourse.get('site.post_types.moderator_action') ? 'moderator' : 'regular'; + return this.get('post.post_type') === Discourse.Site.instance().get('post_types.moderator_action') ? 'moderator' : 'regular'; }.property('post.post_type'), // If the cooked content changed, add the quote controls diff --git a/app/assets/javascripts/discourse/views/topic_view.js b/app/assets/javascripts/discourse/views/topic_view.js index b4b717eb3a9..8118ce56189 100644 --- a/app/assets/javascripts/discourse/views/topic_view.js +++ b/app/assets/javascripts/discourse/views/topic_view.js @@ -12,7 +12,6 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, { topicBinding: 'controller.content', userFiltersBinding: 'controller.userFilters', classNameBindings: ['controller.multiSelect:multi-select', 'topic.archetype', 'topic.category.secure:secure_category'], - siteBinding: 'Discourse.site', progressPosition: 1, menuVisible: true, SHORT_POST: 1200, From 962f0dd5f9c46f625bba2cde7c15825d7bd2c0c8 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Fri, 24 May 2013 12:21:53 -0400 Subject: [PATCH 2/4] Search correctly passes context data to server --- .../javascripts/discourse/components/search.js | 17 ++++++++++++----- .../discourse/controllers/search_controller.js | 7 ++++++- .../javascripts/discourse/models/category.js | 4 ++++ .../javascripts/discourse/models/topic.js | 8 ++++++-- app/assets/javascripts/discourse/models/user.js | 4 ++++ .../discourse/routes/list_category_route.js | 2 +- .../javascripts/discourse/routes/topic_route.js | 2 +- .../javascripts/discourse/routes/user_route.js | 2 +- .../discourse/views/choose_topic_view.js | 2 +- .../discourse/views/modal/edit_category_view.js | 1 + 10 files changed, 37 insertions(+), 12 deletions(-) diff --git a/app/assets/javascripts/discourse/components/search.js b/app/assets/javascripts/discourse/components/search.js index ae733877119..a05a28e1a1e 100644 --- a/app/assets/javascripts/discourse/components/search.js +++ b/app/assets/javascripts/discourse/components/search.js @@ -12,13 +12,20 @@ Discourse.Search = { @method forTerm @param {String} term The term to search for - @param {String} typeFilter An optional filter to restrict the search by type + @param {Object} opts Options for searching + @param {String} opts.typeFilter Filter our results to one type only + @param {Ember.Object} opts.searchContext data to help searching within a context (say, a category or user) @return {Promise} a promise that resolves the search results **/ - forTerm: function(term, typeFilter) { - return Discourse.ajax('/search', { - data: { term: term, type_filter: typeFilter } - }); + forTerm: function(term, opts) { + if (!opts) opts = {}; + + // Only include the data we have + var data = { term: term } + if (opts.typeFilter) data.typeFilter = opts.typeFilter; + if (opts.searchContext) data.search_context = opts.searchContext; + + return Discourse.ajax('/search', { data: data }); } } diff --git a/app/assets/javascripts/discourse/controllers/search_controller.js b/app/assets/javascripts/discourse/controllers/search_controller.js index f01cc4d68f5..c93fbc80a41 100644 --- a/app/assets/javascripts/discourse/controllers/search_controller.js +++ b/app/assets/javascripts/discourse/controllers/search_controller.js @@ -25,7 +25,12 @@ Discourse.SearchController = Em.ArrayController.extend(Discourse.Presence, { var searchController = this; this.set('count', 0); - return Discourse.Search.forTerm(term, typeFilter).then(function(results) { + var searcher = Discourse.Search.forTerm(term, { + typeFilter: typeFilter, + searchContext: searchController.get('searchContext') + }); + + return searcher.then(function(results) { searchController.set('results', results); if (results) { searchController.set('noResults', results.length === 0); diff --git a/app/assets/javascripts/discourse/models/category.js b/app/assets/javascripts/discourse/models/category.js index 96a995c5dd9..46bc8af4925 100644 --- a/app/assets/javascripts/discourse/models/category.js +++ b/app/assets/javascripts/discourse/models/category.js @@ -20,6 +20,10 @@ Discourse.Category = Discourse.Model.extend({ this.set("groups", Em.A(this.groups)); }, + searchContext: function() { + return ({ type: 'category', id: this.get('id') }); + }.property('id'), + url: function() { return Discourse.getURL("/category/") + (this.get('slug')); }.property('name'), diff --git a/app/assets/javascripts/discourse/models/topic.js b/app/assets/javascripts/discourse/models/topic.js index 43a0ad5bf0b..b6df4e317f7 100644 --- a/app/assets/javascripts/discourse/models/topic.js +++ b/app/assets/javascripts/discourse/models/topic.js @@ -13,10 +13,10 @@ Discourse.Topic = Discourse.Model.extend({ return this.get('participants').slice(0, 3); }.property('participants'), - canConvertToRegular: (function() { + canConvertToRegular: function() { var a = this.get('archetype'); return a !== 'regular' && a !== 'private_message'; - }).property('archetype'), + }.property('archetype'), convertArchetype: function(archetype) { var a = this.get('archetype'); @@ -29,6 +29,10 @@ Discourse.Topic = Discourse.Model.extend({ } }, + searchContext: function() { + return ({ type: 'topic', id: this.get('id') }); + }.property('id'), + category: function() { return Discourse.Category.list().findProperty('name', this.get('categoryName')); }.property('categoryName'), diff --git a/app/assets/javascripts/discourse/models/user.js b/app/assets/javascripts/discourse/models/user.js index 080bb6c6379..fa1f462f890 100644 --- a/app/assets/javascripts/discourse/models/user.js +++ b/app/assets/javascripts/discourse/models/user.js @@ -28,6 +28,10 @@ Discourse.User = Discourse.Model.extend({ return Discourse.Utilities.avatarUrl(this.get('username'), 'small', this.get('avatar_template')); }).property('username'), + searchContext: function() { + return ({ type: 'user', id: this.get('username_lower') }); + }.property('username_lower'), + /** This user's website. diff --git a/app/assets/javascripts/discourse/routes/list_category_route.js b/app/assets/javascripts/discourse/routes/list_category_route.js index 7ac95308382..a3fc1f59925 100644 --- a/app/assets/javascripts/discourse/routes/list_category_route.js +++ b/app/assets/javascripts/discourse/routes/list_category_route.js @@ -47,7 +47,7 @@ Discourse.ListCategoryRoute = Discourse.FilteredListRoute.extend({ this._super(); // Add a search context - this.controllerFor('search').set('searchContext', this.modelFor('listCategory')); + this.controllerFor('search').set('searchContext', this.modelFor('listCategory').get('searchContext')); }, deactivate: function() { diff --git a/app/assets/javascripts/discourse/routes/topic_route.js b/app/assets/javascripts/discourse/routes/topic_route.js index 65a3b2eafef..34eb934158e 100644 --- a/app/assets/javascripts/discourse/routes/topic_route.js +++ b/app/assets/javascripts/discourse/routes/topic_route.js @@ -25,7 +25,7 @@ Discourse.TopicRoute = Discourse.Route.extend({ Discourse.set('transient.lastTopicIdViewed', parseInt(topic.get('id'), 10)); // Set the search context - this.controllerFor('search').set('searchContext', topic); + this.controllerFor('search').set('searchContext', topic.get('searchContext')); }, deactivate: function() { diff --git a/app/assets/javascripts/discourse/routes/user_route.js b/app/assets/javascripts/discourse/routes/user_route.js index 8cb7991877b..d033f265406 100644 --- a/app/assets/javascripts/discourse/routes/user_route.js +++ b/app/assets/javascripts/discourse/routes/user_route.js @@ -28,7 +28,7 @@ Discourse.UserRoute = Discourse.Route.extend({ }); // Add a search context - this.controllerFor('search').set('searchContext', user); + this.controllerFor('search').set('searchContext', user.get('searchContext')); }, deactivate: function() { diff --git a/app/assets/javascripts/discourse/views/choose_topic_view.js b/app/assets/javascripts/discourse/views/choose_topic_view.js index e2c75e793f7..e0c4f4ebdce 100644 --- a/app/assets/javascripts/discourse/views/choose_topic_view.js +++ b/app/assets/javascripts/discourse/views/choose_topic_view.js @@ -26,7 +26,7 @@ Discourse.ChooseTopicView = Discourse.View.extend({ search: Discourse.debounce(function(title) { var chooseTopicView = this; - Discourse.Search.forTerm(title, 'topic').then(function (facets) { + Discourse.Search.forTerm(title, {typeFilter: 'topic'}).then(function (facets) { if (facets && facets[0] && facets[0].results) { chooseTopicView.set('topics', facets[0].results); } else { diff --git a/app/assets/javascripts/discourse/views/modal/edit_category_view.js b/app/assets/javascripts/discourse/views/modal/edit_category_view.js index 233a782c237..f67eab4f799 100644 --- a/app/assets/javascripts/discourse/views/modal/edit_category_view.js +++ b/app/assets/javascripts/discourse/views/modal/edit_category_view.js @@ -55,6 +55,7 @@ Discourse.EditCategoryView = Discourse.ModalBodyView.extend({ // background colors are available as a pipe-separated string backgroundColors: function() { + var categories = Discourse.Category.list(); return Discourse.SiteSettings.category_colors.split("|").map(function(i) { return i.toUpperCase(); }).concat( categories.map(function(c) { return c.color.toUpperCase(); }) ).uniq(); }.property('Discourse.SiteSettings.category_colors'), From e600b45155dc4b0594a65c74f85b4556065d27c4 Mon Sep 17 00:00:00 2001 From: Neil Lalonde Date: Fri, 24 May 2013 12:25:28 -0400 Subject: [PATCH 3/4] Composer uses bouncing popup messages beside fields with invalid values when you click the submit button --- .../controllers/composer_controller.js | 9 ++++ .../discourse/helpers/application_helpers.js | 15 ++++++ .../javascripts/discourse/models/composer.js | 4 +- .../templates/composer.js.handlebars | 10 +++- .../templates/popup_input_tip.js.handlebars | 2 + .../discourse/views/composer_view.js | 28 +++++++++- .../views/dismissable_input_tip_view.js | 51 +++++++++++++++++++ .../discourse/views/input_tip_view.js | 1 - .../stylesheets/application/compose.css.scss | 16 ++++-- .../application/input_tip.css.scss | 29 +++++++++++ .../stylesheets/components/buttons.css.scss | 2 +- config/locales/client.en.yml | 6 +++ 12 files changed, 164 insertions(+), 9 deletions(-) create mode 100644 app/assets/javascripts/discourse/templates/popup_input_tip.js.handlebars create mode 100644 app/assets/javascripts/discourse/views/dismissable_input_tip_view.js create mode 100644 app/assets/stylesheets/application/input_tip.css.scss diff --git a/app/assets/javascripts/discourse/controllers/composer_controller.js b/app/assets/javascripts/discourse/controllers/composer_controller.js index 688a28d10a2..b0940bea272 100644 --- a/app/assets/javascripts/discourse/controllers/composer_controller.js +++ b/app/assets/javascripts/discourse/controllers/composer_controller.js @@ -39,6 +39,13 @@ Discourse.ComposerController = Discourse.Controller.extend({ buttons; composer = this.get('content'); + + if( composer.get('cantSubmitPost') ) { + this.set('view.showTitleTip', true); + this.set('view.showReplyTip', true); + return; + } + composer.set('disableDrafts', true); // for now handle a very narrow use case @@ -328,6 +335,8 @@ Discourse.ComposerController = Discourse.Controller.extend({ close: function() { this.set('content', null); this.set('view.content', null); + this.set('view.showTitleTip', false); + this.set('view.showReplyTip', false); }, closeIfCollapsed: function() { diff --git a/app/assets/javascripts/discourse/helpers/application_helpers.js b/app/assets/javascripts/discourse/helpers/application_helpers.js index 44d86537eac..dd8caec7b15 100644 --- a/app/assets/javascripts/discourse/helpers/application_helpers.js +++ b/app/assets/javascripts/discourse/helpers/application_helpers.js @@ -98,6 +98,21 @@ Ember.Handlebars.registerHelper('inputTip', function(options) { return Ember.Handlebars.helpers.view.call(this, Discourse.InputTipView, options); }); +/** + Inserts a Discourse.PopupInputTipView + + @method popupInputTip + @for Handlebars +**/ +Ember.Handlebars.registerHelper('popupInputTip', function(options) { + var hash = options.hash, + types = options.hashTypes; + + normalizeHash(hash, types); + + return Ember.Handlebars.helpers.view.call(this, Discourse.PopupInputTipView, options); +}); + /** Produces a bound link to a category diff --git a/app/assets/javascripts/discourse/models/composer.js b/app/assets/javascripts/discourse/models/composer.js index c4a287379b6..68ceff6f64b 100644 --- a/app/assets/javascripts/discourse/models/composer.js +++ b/app/assets/javascripts/discourse/models/composer.js @@ -276,7 +276,9 @@ Discourse.Composer = Discourse.Model.extend({ }, save: function(opts) { - return this.get('editingPost') ? this.editPost(opts) : this.createPost(opts); + if( !this.get('cantSubmitPost') ) { + return this.get('editingPost') ? this.editPost(opts) : this.createPost(opts); + } }, // When you edit a post diff --git a/app/assets/javascripts/discourse/templates/composer.js.handlebars b/app/assets/javascripts/discourse/templates/composer.js.handlebars index 54361f62760..aab1e64fed9 100644 --- a/app/assets/javascripts/discourse/templates/composer.js.handlebars +++ b/app/assets/javascripts/discourse/templates/composer.js.handlebars @@ -32,7 +32,12 @@ {{#if content.creatingPrivateMessage}} {{view Discourse.UserSelector topicIdBinding="controller.controllers.topic.content.id" excludeCurrentUser="true" id="private-message-users" class="span8" placeholderKey="composer.users_placeholder" tabindex="1" usernamesBinding="content.targetUsernames"}} {{/if}} - {{textField value=content.title tabindex="2" id="reply-title" maxlength="255" class="span8" placeholderKey="composer.title_placeholder"}} + +
    + {{textField value=content.title tabindex="2" id="reply-title" maxlength="255" class="span8" placeholderKey="composer.title_placeholder"}} + {{popupInputTip validation=view.titleValidation show=view.showTitleTip}} +
    + {{#unless content.creatingPrivateMessage}} {{view Discourse.ComboboxViewCategory valueAttribute="name" contentBinding="categories" valueBinding="content.categoryName"}} {{#if content.archetype.hasOptions}} @@ -53,6 +58,7 @@
    {{view Discourse.NotifyingTextArea parentBinding="view" tabindex="3" valueBinding="content.reply" id="wmd-input" placeholderKey="composer.reply_placeholder"}} + {{popupInputTip validation=view.replyValidation show=view.showReplyTip}}
    @@ -70,7 +76,7 @@ {{#if Discourse.currentUser}}
    - + {{i18n cancel}}
    {{/if}} diff --git a/app/assets/javascripts/discourse/templates/popup_input_tip.js.handlebars b/app/assets/javascripts/discourse/templates/popup_input_tip.js.handlebars new file mode 100644 index 00000000000..8fa9bc38f55 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/popup_input_tip.js.handlebars @@ -0,0 +1,2 @@ + +{{view.validation.reason}} \ No newline at end of file diff --git a/app/assets/javascripts/discourse/views/composer_view.js b/app/assets/javascripts/discourse/views/composer_view.js index f2154519bc7..2d8b7d0b5db 100644 --- a/app/assets/javascripts/discourse/views/composer_view.js +++ b/app/assets/javascripts/discourse/views/composer_view.js @@ -369,7 +369,33 @@ Discourse.ComposerView = Discourse.View.extend({ $adminOpts.show(); $wmd.css('top', wmdTop + parseInt($adminOpts.css('height'),10) + 'px' ); } - } + }, + + titleValidation: function() { + var title = this.get('content.title'), reason; + if( !title || title.length < 1 ){ + reason = Em.String.i18n('composer.error.title_missing'); + } else if( title.length < Discourse.SiteSettings.min_topic_title_length || title.length > Discourse.SiteSettings.max_topic_title_length ) { + reason = Em.String.i18n('composer.error.title_length', {min: Discourse.SiteSettings.min_topic_title_length, max: Discourse.SiteSettings.max_topic_title_length}) + } + + if( reason ) { + return Discourse.InputValidation.create({ failed: true, reason: reason }); + } + }.property('content.title'), + + replyValidation: function() { + var reply = this.get('content.reply'), reason; + if( !reply || reply.length < 1 ){ + reason = Em.String.i18n('composer.error.post_missing'); + } else if( reply.length < Discourse.SiteSettings.min_post_length ) { + reason = Em.String.i18n('composer.error.post_length', {min: Discourse.SiteSettings.min_post_length}) + } + + if( reason ) { + return Discourse.InputValidation.create({ failed: true, reason: reason }); + } + }.property('content.reply') }); // not sure if this is the right way, keeping here for now, we could use a mixin perhaps diff --git a/app/assets/javascripts/discourse/views/dismissable_input_tip_view.js b/app/assets/javascripts/discourse/views/dismissable_input_tip_view.js new file mode 100644 index 00000000000..a4c5be876c3 --- /dev/null +++ b/app/assets/javascripts/discourse/views/dismissable_input_tip_view.js @@ -0,0 +1,51 @@ +/** + This view extends the functionality of InputTipView with these extra features: + * it can be dismissed + * it bounces when it's shown + * it's absolutely positioned beside the input element, with the help of + extra css you'll need to write to line it up correctly. + + @class PopupInputTipView + @extends Discourse.View + @namespace Discourse + @module Discourse +**/ +Discourse.PopupInputTipView = Discourse.View.extend({ + templateName: 'popup_input_tip', + classNameBindings: [':popup-tip', 'good', 'bad', 'show::hide'], + animateAttribute: null, + bouncePixels: 6, + bounceDelay: 100, + + good: function() { + return !this.get('validation.failed'); + }.property('validation'), + + bad: function() { + return this.get('validation.failed'); + }.property('validation'), + + hide: function() { + this.set('show', false); + }, + + bounce: function() { + var $elem = this.$() + if( !this.animateAttribute ) { + this.animateAttribute = $elem.css('left') == 'auto' ? 'right' : 'left'; + } + this.animateAttribute == 'left' ? this.bounceLeft($elem) : this.bounceRight($elem); + }.observes('show'), + + bounceLeft: function($elem) { + for( var i = 0; i < 5; i++ ) { + $elem.animate({ left: '+=' + this.bouncePixels }, this.bounceDelay).animate({ left: '-=' + this.bouncePixels }, this.bounceDelay); + } + }, + + bounceRight: function($elem) { + for( var i = 0; i < 5; i++ ) { + $elem.animate({ right: '-=' + this.bouncePixels }, this.bounceDelay).animate({ right: '+=' + this.bouncePixels }, this.bounceDelay); + } + } +}); diff --git a/app/assets/javascripts/discourse/views/input_tip_view.js b/app/assets/javascripts/discourse/views/input_tip_view.js index 108cf0c1d59..f2f5eca3737 100644 --- a/app/assets/javascripts/discourse/views/input_tip_view.js +++ b/app/assets/javascripts/discourse/views/input_tip_view.js @@ -7,7 +7,6 @@ @module Discourse **/ Discourse.InputTipView = Discourse.View.extend({ - templateName: 'input_tip', classNameBindings: [':tip', 'good', 'bad'], good: function() { diff --git a/app/assets/stylesheets/application/compose.css.scss b/app/assets/stylesheets/application/compose.css.scss index 4d3e113c5cd..a1477934b0b 100644 --- a/app/assets/stylesheets/application/compose.css.scss +++ b/app/assets/stylesheets/application/compose.css.scss @@ -104,9 +104,6 @@ } #reply-control { - .requirements-not-met { - background-color: rgba(255, 0, 0, 0.12); - } .toggle-preview, #draft-status, #image-uploading { position: absolute; bottom: -31px; @@ -325,6 +322,15 @@ bottom: 8px; } } + .title-input { + position: relative; + display: inline; + .popup-tip { + width: 300px; + left: -8px; + margin-top: 8px; + } + } } .reply-to { @@ -450,6 +456,10 @@ div.ac-wrap { .textarea-wrapper { padding-right: 5px; float: left; + .popup-tip { + margin-top: 3px; + right: 4px; + } } .preview-wrapper { padding-left: 5px; diff --git a/app/assets/stylesheets/application/input_tip.css.scss b/app/assets/stylesheets/application/input_tip.css.scss new file mode 100644 index 00000000000..fabfdaba7ae --- /dev/null +++ b/app/assets/stylesheets/application/input_tip.css.scss @@ -0,0 +1,29 @@ +@import "foundation/variables"; +@import "foundation/mixins"; + +.popup-tip { + position: absolute; + display: block; + padding: 5px 10px; + z-index: 101; + @include border-radius-all(2px); + border: solid 1px #955; + &.bad { + background-color: #b66; + color: white; + box-shadow: 1px 1px 5px #777, inset 0 0 9px #b55; + } + &.hide, &.good { + display: none; + } + a.close { + float: right; + color: $black; + opacity: 0.5; + font-size: 15px; + margin-left: 4px; + } + a.close:hover { + opacity: 1.0; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/components/buttons.css.scss b/app/assets/stylesheets/components/buttons.css.scss index d65cd88dcbc..21bcefbf2c7 100644 --- a/app/assets/stylesheets/components/buttons.css.scss +++ b/app/assets/stylesheets/components/buttons.css.scss @@ -22,7 +22,7 @@ &:active { text-shadow: none; } - &[disabled] { + &[disabled], &.disabled { cursor: default; opacity: 0.4; } diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 56a34ba9d5b..b116b51a42f 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -338,6 +338,12 @@ en: need_more_for_title: "{{n}} to go for the title" need_more_for_reply: "{{n}} to go for the reply" + error: + title_missing: "Title is required." + title_length: "Title needs between {{min}} and {{max}} characters." + post_missing: "Post can't be empty." + post_length: "Post must be at least {{min}} characters long." + save_edit: "Save Edit" reply_original: "Reply on Original Topic" reply_here: "Reply Here" From 48d39d2f8c3546bab9f0d4501f342864523fa7bb Mon Sep 17 00:00:00 2001 From: Neil Lalonde Date: Fri, 24 May 2013 12:45:58 -0400 Subject: [PATCH 4/4] Oops jshint fail again --- ...missable_input_tip_view.js => popup_input_tip_view.js} | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) rename app/assets/javascripts/discourse/views/{dismissable_input_tip_view.js => popup_input_tip_view.js} (87%) diff --git a/app/assets/javascripts/discourse/views/dismissable_input_tip_view.js b/app/assets/javascripts/discourse/views/popup_input_tip_view.js similarity index 87% rename from app/assets/javascripts/discourse/views/dismissable_input_tip_view.js rename to app/assets/javascripts/discourse/views/popup_input_tip_view.js index a4c5be876c3..0b71b346f11 100644 --- a/app/assets/javascripts/discourse/views/dismissable_input_tip_view.js +++ b/app/assets/javascripts/discourse/views/popup_input_tip_view.js @@ -32,9 +32,13 @@ Discourse.PopupInputTipView = Discourse.View.extend({ bounce: function() { var $elem = this.$() if( !this.animateAttribute ) { - this.animateAttribute = $elem.css('left') == 'auto' ? 'right' : 'left'; + this.animateAttribute = $elem.css('left') === 'auto' ? 'right' : 'left'; + } + if( this.animateAttribute === 'left' ) { + this.bounceLeft($elem); + } else { + this.bounceRight($elem); } - this.animateAttribute == 'left' ? this.bounceLeft($elem) : this.bounceRight($elem); }.observes('show'), bounceLeft: function($elem) {