From f5aa7bfefaa1caa0eca0704a98f76ade00da4e16 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Thu, 26 Feb 2015 09:43:53 +1030 Subject: [PATCH] Use component prototypes instead of instances MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This means the component instance is created in the template, meaning properties can be overridden in the view helper. It also just makes more sense - a view instance doesn’t need to exist until it is rendered in the template. --- .../composer/composer-discussion.js | 2 +- .../app/components/composer/composer-edit.js | 2 +- .../app/components/composer/composer-reply.js | 2 +- .../app/components/discussion/post-comment.js | 8 +++--- .../components/index/discussion-listing.js | 3 ++- .../core/ember/app/components/ui/item-list.js | 2 +- .../ember/app/components/ui/text-editor.js | 2 +- .../core/ember/app/controllers/discussion.js | 2 +- .../core/ember/app/mixins/has-item-lists.js | 25 +++++++++++++------ .../core/ember/app/mixins/use-composer.js | 2 +- framework/core/ember/app/views/application.js | 8 +++--- framework/core/ember/app/views/composer.js | 2 +- framework/core/ember/app/views/discussion.js | 4 +-- framework/core/ember/app/views/index.js | 12 ++++----- 14 files changed, 43 insertions(+), 33 deletions(-) diff --git a/framework/core/ember/app/components/composer/composer-discussion.js b/framework/core/ember/app/components/composer/composer-discussion.js index a3698b8aa..7dee13621 100644 --- a/framework/core/ember/app/components/composer/composer-discussion.js +++ b/framework/core/ember/app/components/composer/composer-discussion.js @@ -16,7 +16,7 @@ export default ComposerBody.extend({ title: '', populateControls: function(items) { - var title = Ember.Component.create({ + var title = Ember.Component.extend({ tagName: 'h3', layout: precompileTemplate('{{ui/text-input value=component.title class="form-control" placeholder=component.titlePlaceholder disabled=component.disabled autoGrow=true}}'), component: this diff --git a/framework/core/ember/app/components/composer/composer-edit.js b/framework/core/ember/app/components/composer/composer-edit.js index 8cf2c8f58..03896d1d2 100644 --- a/framework/core/ember/app/components/composer/composer-edit.js +++ b/framework/core/ember/app/components/composer/composer-edit.js @@ -15,7 +15,7 @@ export default ComposerBody.extend({ originalContent: Ember.computed.oneWay('post.content'), populateControls: function(controls) { - var title = Ember.Component.create({ + var title = Ember.Component.extend({ tagName: 'h3', layout: precompileTemplate('Editing Post #{{component.post.number}} in {{discussion.title}}'), discussion: this.get('post.discussion'), diff --git a/framework/core/ember/app/components/composer/composer-reply.js b/framework/core/ember/app/components/composer/composer-reply.js index d681589d4..7778310d0 100644 --- a/framework/core/ember/app/components/composer/composer-reply.js +++ b/framework/core/ember/app/components/composer/composer-reply.js @@ -12,7 +12,7 @@ export default ComposerBody.extend({ submitLabel: 'Post Reply', populateControls: function(items) { - var title = Ember.Component.create({ + var title = Ember.Component.extend({ tagName: 'h3', layout: precompileTemplate('Replying to {{component.discussion.title}}'), component: this diff --git a/framework/core/ember/app/components/discussion/post-comment.js b/framework/core/ember/app/components/discussion/post-comment.js index b9393558e..a8dbd604b 100644 --- a/framework/core/ember/app/components/discussion/post-comment.js +++ b/framework/core/ember/app/components/discussion/post-comment.js @@ -49,10 +49,10 @@ export default Ember.Component.extend(FadeIn, HasItemLists, UseComposer, { populateHeader: function(items) { var properties = this.getProperties('post'); - items.pushObjectWithTag(PostHeaderUser.create(properties), 'user'); - items.pushObjectWithTag(PostHeaderMeta.create(properties), 'meta'); - items.pushObjectWithTag(PostHeaderEdited.create(properties), 'edited'); - items.pushObjectWithTag(PostHeaderToggle.create(properties, {parent: this}), 'toggle'); + items.pushObjectWithTag(PostHeaderUser.extend(properties), 'user'); + items.pushObjectWithTag(PostHeaderMeta.extend(properties), 'meta'); + items.pushObjectWithTag(PostHeaderEdited.extend(properties), 'edited'); + items.pushObjectWithTag(PostHeaderToggle.extend(properties, {parent: this}), 'toggle'); }, savePost: function(post, data) { diff --git a/framework/core/ember/app/components/index/discussion-listing.js b/framework/core/ember/app/components/index/discussion-listing.js index cc5e71cba..2631eacbc 100755 --- a/framework/core/ember/app/components/index/discussion-listing.js +++ b/framework/core/ember/app/components/index/discussion-listing.js @@ -64,7 +64,8 @@ export default Ember.Component.extend(FadeIn, HasItemLists, { layoutName: 'components/index/discussion-info/terminal-post', discussion: Ember.computed.alias('parent.discussion'), displayLastPost: Ember.computed.alias('parent.displayLastPost'), - }).create({parent: this}), 'terminalPost'); + parent: this + }), 'terminalPost'); }, actions: { diff --git a/framework/core/ember/app/components/ui/item-list.js b/framework/core/ember/app/components/ui/item-list.js index 75d119451..a7d477f2e 100644 --- a/framework/core/ember/app/components/ui/item-list.js +++ b/framework/core/ember/app/components/ui/item-list.js @@ -14,7 +14,7 @@ export default Ember.Component.extend({ return []; } items.forEach(function(item) { - item.set('isListItem', item.get('tagName') === 'li'); + item.reopenClass({isListItem: item.proto().tagName === 'li'}); }); return items; }) diff --git a/framework/core/ember/app/components/ui/text-editor.js b/framework/core/ember/app/components/ui/text-editor.js index c8a755f7b..654923cb5 100644 --- a/framework/core/ember/app/components/ui/text-editor.js +++ b/framework/core/ember/app/components/ui/text-editor.js @@ -22,7 +22,7 @@ export default Ember.Component.extend(HasItemLists, { }, populateControls: function(items) { - this.addActionItem(items, 'submit', this.get('submitLabel')).set('className', 'btn btn-primary'); + this.addActionItem(items, 'submit', this.get('submitLabel')).reopen({className: 'btn btn-primary'}); }, actions: { diff --git a/framework/core/ember/app/controllers/discussion.js b/framework/core/ember/app/controllers/discussion.js index e992e0f02..78d3dc60d 100644 --- a/framework/core/ember/app/controllers/discussion.js +++ b/framework/core/ember/app/controllers/discussion.js @@ -50,7 +50,7 @@ export default Ember.Controller.extend(Ember.Evented, UseComposerMixin, { // Otherwise, we'll create an alert message to inform the user // that their reply has been posted, containing a button which // will transition to their new post when clicked. - var message = AlertMessage.create({ + var message = AlertMessage.extend({ type: 'success', message: 'Your reply was posted.', buttons: [{ diff --git a/framework/core/ember/app/mixins/has-item-lists.js b/framework/core/ember/app/mixins/has-item-lists.js index fef154eab..24942b39f 100644 --- a/framework/core/ember/app/mixins/has-item-lists.js +++ b/framework/core/ember/app/mixins/has-item-lists.js @@ -21,6 +21,7 @@ export default Ember.Mixin.create({ populateItemList: function(name) { var items = TaggedArray.create(); this.trigger('populate'+name.charAt(0).toUpperCase()+name.slice(1), items); + this.removeUnneededSeparatorItems(items); return items; }, @@ -36,18 +37,26 @@ export default Ember.Mixin.create({ } }); - var itemInstance = item.create(); + items.pushObjectWithTag(item, tag); - items.pushObjectWithTag(itemInstance, tag); - - return itemInstance; + return item; }, addSeparatorItem: function(items) { - var length = items.get('length'); - var last = items.objectAt(length - 1); - if (last && !(last instanceof SeparatorItem)) { - items.pushObject(SeparatorItem.create()); + items.pushObject(SeparatorItem); + }, + + removeUnneededSeparatorItems: function(items) { + var prevItem = null; + items.forEach(function(item) { + if (prevItem === SeparatorItem && item === SeparatorItem) { + items.removeObject(item); + return; + } + prevItem = item; + }); + if (prevItem === SeparatorItem) { + items.removeObject(prevItem); } } }); diff --git a/framework/core/ember/app/mixins/use-composer.js b/framework/core/ember/app/mixins/use-composer.js index 01ad6821f..971a09ea3 100644 --- a/framework/core/ember/app/mixins/use-composer.js +++ b/framework/core/ember/app/mixins/use-composer.js @@ -27,7 +27,7 @@ export default Ember.Mixin.create({ showErrorsAsAlertMessages: function(errors) { for (var i in errors) { - var message = AlertMessage.create({ + var message = AlertMessage.extend({ type: 'warning', message: errors[i] }); diff --git a/framework/core/ember/app/views/application.js b/framework/core/ember/app/views/application.js index bbd6cb34e..3ce3d7d6e 100644 --- a/framework/core/ember/app/views/application.js +++ b/framework/core/ember/app/views/application.js @@ -60,7 +60,7 @@ export default Ember.View.extend(HasItemLists, { populateHeaderSecondary: function(items) { var controller = this.get('controller'); - items.pushObjectWithTag(SearchInput.create({ + items.pushObjectWithTag(SearchInput.extend({ placeholder: 'Search Forum', controller: controller, valueBinding: Ember.Binding.oneWay('controller.searchQuery'), @@ -69,7 +69,7 @@ export default Ember.View.extend(HasItemLists, { }), 'search'); if (this.get('controller.session.isAuthenticated')) { - items.pushObjectWithTag(UserDropdown.create({ + items.pushObjectWithTag(UserDropdown.extend({ user: this.get('controller.session.user'), logout: function() { controller.send('invalidateSession'); } }), 'user'); @@ -81,7 +81,7 @@ export default Ember.View.extend(HasItemLists, { populateFooterPrimary: function(items) { var addStatistic = function(label, number) { - items.pushObjectWithTag(ForumStatistic.create({ + items.pushObjectWithTag(ForumStatistic.extend({ label: label, number: number }), 'statistics.'+label); @@ -93,6 +93,6 @@ export default Ember.View.extend(HasItemLists, { }, populateFooterSecondary: function(items) { - items.pushObjectWithTag(PoweredBy.create(), 'poweredBy'); + items.pushObjectWithTag(PoweredBy, 'poweredBy'); } }); diff --git a/framework/core/ember/app/views/composer.js b/framework/core/ember/app/views/composer.js index c45f68b9b..1a5d89b24 100644 --- a/framework/core/ember/app/views/composer.js +++ b/framework/core/ember/app/views/composer.js @@ -233,7 +233,7 @@ export default Ember.View.extend(HasItemLists, { populateControls: function(items) { var view = this; var addControl = function(tag, title, icon) { - view.addActionItem(items, tag, null, icon).set('className', 'btn btn-icon btn-link').set('title', title); + view.addActionItem(items, tag, null, icon).reopen({className: 'btn btn-icon btn-link', title: title}); }; if (this.get('fullscreen')) { diff --git a/framework/core/ember/app/views/discussion.js b/framework/core/ember/app/views/discussion.js index ecdf68313..ebe2802f0 100644 --- a/framework/core/ember/app/views/discussion.js +++ b/framework/core/ember/app/views/discussion.js @@ -48,13 +48,13 @@ export default Ember.View.extend(HasItemLists, { // ------------------------------------------------------------------------ populateSidebar: function(items) { - items.pushObjectWithTag(DropdownSplit.create({ + items.pushObjectWithTag(DropdownSplit.extend({ items: this.populateItemList('controls'), icon: 'reply', buttonClass: 'btn-primary' }), 'controls'); - items.pushObjectWithTag(StreamScrubber.create({ + items.pushObjectWithTag(StreamScrubber.extend({ streamContent: this.get('streamContent') }), 'scrubber'); }, diff --git a/framework/core/ember/app/views/index.js b/framework/core/ember/app/views/index.js index 6e15f585b..12ff7d158 100644 --- a/framework/core/ember/app/views/index.js +++ b/framework/core/ember/app/views/index.js @@ -13,7 +13,7 @@ export default Ember.View.extend(HasItemLists, { itemLists: ['sidebar'], didInsertElement: function() { - this.set('hero', WelcomeHero.create({ + this.set('hero', WelcomeHero.extend({ title: this.get('controller.controllers.application.forumTitle'), description: 'Thanks for stopping by!' })); @@ -73,26 +73,26 @@ export default Ember.View.extend(HasItemLists, { }), populateSidebar: function(items) { - this.addActionItem(items, 'newDiscussion', 'Start a Discussion', 'edit').set('className', 'btn btn-primary new-discussion'); + this.addActionItem(items, 'newDiscussion', 'Start a Discussion', 'edit').reopen({className: 'btn btn-primary new-discussion'}); var nav = this.populateItemList('nav'); - items.pushObjectWithTag(DropdownSelect.create({ items: nav }), 'nav'); + items.pushObjectWithTag(DropdownSelect.extend({items: nav}), 'nav'); }, populateNav: function(items) { - items.pushObjectWithTag(NavItem.create({ + items.pushObjectWithTag(NavItem.extend({ label: 'All Discussions', icon: 'comments-o', layout: precompileTemplate('{{#link-to "index" (query-params filter="")}}{{fa-icon icon}} {{label}} {{badge}}{{/link-to}}') }), 'all'); - items.pushObjectWithTag(NavItem.create({ + items.pushObjectWithTag(NavItem.extend({ label: 'Private', icon: 'envelope-o', layout: precompileTemplate('{{#link-to "index" (query-params filter="private")}}{{fa-icon icon}} {{label}} {{badge}}{{/link-to}}') }), 'private'); - items.pushObjectWithTag(NavItem.create({ + items.pushObjectWithTag(NavItem.extend({ label: 'Following', icon: 'star', layout: precompileTemplate('{{#link-to "index" (query-params filter="following")}}{{fa-icon icon}} {{label}} {{badge}}{{/link-to}}')