1
0
mirror of https://github.com/flarum/core.git synced 2025-07-17 23:01:17 +02:00

Use component prototypes instead of instances

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.
This commit is contained in:
Toby Zerner
2015-02-26 09:43:53 +10:30
parent bde89cdc31
commit f5aa7bfefa
14 changed files with 43 additions and 33 deletions

View File

@@ -16,7 +16,7 @@ export default ComposerBody.extend({
title: '', title: '',
populateControls: function(items) { populateControls: function(items) {
var title = Ember.Component.create({ var title = Ember.Component.extend({
tagName: 'h3', tagName: 'h3',
layout: precompileTemplate('{{ui/text-input value=component.title class="form-control" placeholder=component.titlePlaceholder disabled=component.disabled autoGrow=true}}'), layout: precompileTemplate('{{ui/text-input value=component.title class="form-control" placeholder=component.titlePlaceholder disabled=component.disabled autoGrow=true}}'),
component: this component: this

View File

@@ -15,7 +15,7 @@ export default ComposerBody.extend({
originalContent: Ember.computed.oneWay('post.content'), originalContent: Ember.computed.oneWay('post.content'),
populateControls: function(controls) { populateControls: function(controls) {
var title = Ember.Component.create({ var title = Ember.Component.extend({
tagName: 'h3', tagName: 'h3',
layout: precompileTemplate('Editing Post #{{component.post.number}} in <em>{{discussion.title}}</em>'), layout: precompileTemplate('Editing Post #{{component.post.number}} in <em>{{discussion.title}}</em>'),
discussion: this.get('post.discussion'), discussion: this.get('post.discussion'),

View File

@@ -12,7 +12,7 @@ export default ComposerBody.extend({
submitLabel: 'Post Reply', submitLabel: 'Post Reply',
populateControls: function(items) { populateControls: function(items) {
var title = Ember.Component.create({ var title = Ember.Component.extend({
tagName: 'h3', tagName: 'h3',
layout: precompileTemplate('Replying to <em>{{component.discussion.title}}</em>'), layout: precompileTemplate('Replying to <em>{{component.discussion.title}}</em>'),
component: this component: this

View File

@@ -49,10 +49,10 @@ export default Ember.Component.extend(FadeIn, HasItemLists, UseComposer, {
populateHeader: function(items) { populateHeader: function(items) {
var properties = this.getProperties('post'); var properties = this.getProperties('post');
items.pushObjectWithTag(PostHeaderUser.create(properties), 'user'); items.pushObjectWithTag(PostHeaderUser.extend(properties), 'user');
items.pushObjectWithTag(PostHeaderMeta.create(properties), 'meta'); items.pushObjectWithTag(PostHeaderMeta.extend(properties), 'meta');
items.pushObjectWithTag(PostHeaderEdited.create(properties), 'edited'); items.pushObjectWithTag(PostHeaderEdited.extend(properties), 'edited');
items.pushObjectWithTag(PostHeaderToggle.create(properties, {parent: this}), 'toggle'); items.pushObjectWithTag(PostHeaderToggle.extend(properties, {parent: this}), 'toggle');
}, },
savePost: function(post, data) { savePost: function(post, data) {

View File

@@ -64,7 +64,8 @@ export default Ember.Component.extend(FadeIn, HasItemLists, {
layoutName: 'components/index/discussion-info/terminal-post', layoutName: 'components/index/discussion-info/terminal-post',
discussion: Ember.computed.alias('parent.discussion'), discussion: Ember.computed.alias('parent.discussion'),
displayLastPost: Ember.computed.alias('parent.displayLastPost'), displayLastPost: Ember.computed.alias('parent.displayLastPost'),
}).create({parent: this}), 'terminalPost'); parent: this
}), 'terminalPost');
}, },
actions: { actions: {

View File

@@ -14,7 +14,7 @@ export default Ember.Component.extend({
return []; return [];
} }
items.forEach(function(item) { items.forEach(function(item) {
item.set('isListItem', item.get('tagName') === 'li'); item.reopenClass({isListItem: item.proto().tagName === 'li'});
}); });
return items; return items;
}) })

View File

@@ -22,7 +22,7 @@ export default Ember.Component.extend(HasItemLists, {
}, },
populateControls: function(items) { 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: { actions: {

View File

@@ -50,7 +50,7 @@ export default Ember.Controller.extend(Ember.Evented, UseComposerMixin, {
// Otherwise, we'll create an alert message to inform the user // Otherwise, we'll create an alert message to inform the user
// that their reply has been posted, containing a button which // that their reply has been posted, containing a button which
// will transition to their new post when clicked. // will transition to their new post when clicked.
var message = AlertMessage.create({ var message = AlertMessage.extend({
type: 'success', type: 'success',
message: 'Your reply was posted.', message: 'Your reply was posted.',
buttons: [{ buttons: [{

View File

@@ -21,6 +21,7 @@ export default Ember.Mixin.create({
populateItemList: function(name) { populateItemList: function(name) {
var items = TaggedArray.create(); var items = TaggedArray.create();
this.trigger('populate'+name.charAt(0).toUpperCase()+name.slice(1), items); this.trigger('populate'+name.charAt(0).toUpperCase()+name.slice(1), items);
this.removeUnneededSeparatorItems(items);
return 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 item;
return itemInstance;
}, },
addSeparatorItem: function(items) { addSeparatorItem: function(items) {
var length = items.get('length'); items.pushObject(SeparatorItem);
var last = items.objectAt(length - 1); },
if (last && !(last instanceof SeparatorItem)) {
items.pushObject(SeparatorItem.create()); 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);
} }
} }
}); });

View File

@@ -27,7 +27,7 @@ export default Ember.Mixin.create({
showErrorsAsAlertMessages: function(errors) { showErrorsAsAlertMessages: function(errors) {
for (var i in errors) { for (var i in errors) {
var message = AlertMessage.create({ var message = AlertMessage.extend({
type: 'warning', type: 'warning',
message: errors[i] message: errors[i]
}); });

View File

@@ -60,7 +60,7 @@ export default Ember.View.extend(HasItemLists, {
populateHeaderSecondary: function(items) { populateHeaderSecondary: function(items) {
var controller = this.get('controller'); var controller = this.get('controller');
items.pushObjectWithTag(SearchInput.create({ items.pushObjectWithTag(SearchInput.extend({
placeholder: 'Search Forum', placeholder: 'Search Forum',
controller: controller, controller: controller,
valueBinding: Ember.Binding.oneWay('controller.searchQuery'), valueBinding: Ember.Binding.oneWay('controller.searchQuery'),
@@ -69,7 +69,7 @@ export default Ember.View.extend(HasItemLists, {
}), 'search'); }), 'search');
if (this.get('controller.session.isAuthenticated')) { if (this.get('controller.session.isAuthenticated')) {
items.pushObjectWithTag(UserDropdown.create({ items.pushObjectWithTag(UserDropdown.extend({
user: this.get('controller.session.user'), user: this.get('controller.session.user'),
logout: function() { controller.send('invalidateSession'); } logout: function() { controller.send('invalidateSession'); }
}), 'user'); }), 'user');
@@ -81,7 +81,7 @@ export default Ember.View.extend(HasItemLists, {
populateFooterPrimary: function(items) { populateFooterPrimary: function(items) {
var addStatistic = function(label, number) { var addStatistic = function(label, number) {
items.pushObjectWithTag(ForumStatistic.create({ items.pushObjectWithTag(ForumStatistic.extend({
label: label, label: label,
number: number number: number
}), 'statistics.'+label); }), 'statistics.'+label);
@@ -93,6 +93,6 @@ export default Ember.View.extend(HasItemLists, {
}, },
populateFooterSecondary: function(items) { populateFooterSecondary: function(items) {
items.pushObjectWithTag(PoweredBy.create(), 'poweredBy'); items.pushObjectWithTag(PoweredBy, 'poweredBy');
} }
}); });

View File

@@ -233,7 +233,7 @@ export default Ember.View.extend(HasItemLists, {
populateControls: function(items) { populateControls: function(items) {
var view = this; var view = this;
var addControl = function(tag, title, icon) { 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')) { if (this.get('fullscreen')) {

View File

@@ -48,13 +48,13 @@ export default Ember.View.extend(HasItemLists, {
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
populateSidebar: function(items) { populateSidebar: function(items) {
items.pushObjectWithTag(DropdownSplit.create({ items.pushObjectWithTag(DropdownSplit.extend({
items: this.populateItemList('controls'), items: this.populateItemList('controls'),
icon: 'reply', icon: 'reply',
buttonClass: 'btn-primary' buttonClass: 'btn-primary'
}), 'controls'); }), 'controls');
items.pushObjectWithTag(StreamScrubber.create({ items.pushObjectWithTag(StreamScrubber.extend({
streamContent: this.get('streamContent') streamContent: this.get('streamContent')
}), 'scrubber'); }), 'scrubber');
}, },

View File

@@ -13,7 +13,7 @@ export default Ember.View.extend(HasItemLists, {
itemLists: ['sidebar'], itemLists: ['sidebar'],
didInsertElement: function() { didInsertElement: function() {
this.set('hero', WelcomeHero.create({ this.set('hero', WelcomeHero.extend({
title: this.get('controller.controllers.application.forumTitle'), title: this.get('controller.controllers.application.forumTitle'),
description: 'Thanks for stopping by!' description: 'Thanks for stopping by!'
})); }));
@@ -73,26 +73,26 @@ export default Ember.View.extend(HasItemLists, {
}), }),
populateSidebar: function(items) { 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'); var nav = this.populateItemList('nav');
items.pushObjectWithTag(DropdownSelect.create({ items: nav }), 'nav'); items.pushObjectWithTag(DropdownSelect.extend({items: nav}), 'nav');
}, },
populateNav: function(items) { populateNav: function(items) {
items.pushObjectWithTag(NavItem.create({ items.pushObjectWithTag(NavItem.extend({
label: 'All Discussions', label: 'All Discussions',
icon: 'comments-o', icon: 'comments-o',
layout: precompileTemplate('{{#link-to "index" (query-params filter="")}}{{fa-icon icon}} {{label}} <span class="count">{{badge}}</span>{{/link-to}}') layout: precompileTemplate('{{#link-to "index" (query-params filter="")}}{{fa-icon icon}} {{label}} <span class="count">{{badge}}</span>{{/link-to}}')
}), 'all'); }), 'all');
items.pushObjectWithTag(NavItem.create({ items.pushObjectWithTag(NavItem.extend({
label: 'Private', label: 'Private',
icon: 'envelope-o', icon: 'envelope-o',
layout: precompileTemplate('{{#link-to "index" (query-params filter="private")}}{{fa-icon icon}} {{label}} <span class="count">{{badge}}</span>{{/link-to}}') layout: precompileTemplate('{{#link-to "index" (query-params filter="private")}}{{fa-icon icon}} {{label}} <span class="count">{{badge}}</span>{{/link-to}}')
}), 'private'); }), 'private');
items.pushObjectWithTag(NavItem.create({ items.pushObjectWithTag(NavItem.extend({
label: 'Following', label: 'Following',
icon: 'star', icon: 'star',
layout: precompileTemplate('{{#link-to "index" (query-params filter="following")}}{{fa-icon icon}} {{label}} <span class="count">{{badge}}</span>{{/link-to}}') layout: precompileTemplate('{{#link-to "index" (query-params filter="following")}}{{fa-icon icon}} {{label}} <span class="count">{{badge}}</span>{{/link-to}}')