mirror of
https://github.com/flarum/core.git
synced 2025-07-31 21:50:50 +02:00
Upgrade to Ember 1.11-beta.1
HTMLBars goodness! Since there was some breakage and a lot of fiddling around to get some things working, I took this opportunity to do a big cleanup of the whole Ember app. I accidentally worked on some new features too :3 Note that the app is still broken right now, pending on https://github.com/emberjs/ember.js/issues/10401 Cleanup: - Restructuring of components - Consolidation of some stuff into mixins, cleanup of some APIs that will be public - Change all instances of .property() / .observes() / .on() to Ember.computed() / Ember.observer() / Ember.on() respectively (I think it is more readable) - More comments - Start conforming to a code style (2 spaces for indentation) New features: - Post hiding/restoring - Mark individual discussions as read by clicking - Clicking on a read discussion jumps to the end - Mark all discussions as read - Progressively mark the discussion as read as the page is scrolled - Unordered list post formatting - Post permalink popup Demo once that Ember regression is fixed!
This commit is contained in:
29
ember/app/components/ui/action-button.js
Normal file
29
ember/app/components/ui/action-button.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
var precompileTemplate = Ember.Handlebars.compile;
|
||||
|
||||
/**
|
||||
Button which sends an action when clicked.
|
||||
*/
|
||||
export default Ember.Component.extend({
|
||||
tagName: 'a',
|
||||
attributeBindings: ['href', 'title'],
|
||||
classNameBindings: ['className'],
|
||||
href: '#',
|
||||
layout: precompileTemplate('{{#if icon}}{{fa-icon icon class="fa-fw icon-glyph"}} {{/if}}<span>{{label}}</span>'),
|
||||
|
||||
label: '',
|
||||
icon: '',
|
||||
className: '',
|
||||
action: null,
|
||||
|
||||
click: function(e) {
|
||||
e.preventDefault();
|
||||
var action = this.get('action');
|
||||
if (typeof action === 'string') {
|
||||
this.sendAction('action');
|
||||
} else if (typeof action === 'function') {
|
||||
action();
|
||||
}
|
||||
}
|
||||
});
|
53
ember/app/components/ui/alert-message.js
Executable file
53
ember/app/components/ui/alert-message.js
Executable file
@@ -0,0 +1,53 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
import HasItemLists from 'flarum/mixins/has-item-lists';
|
||||
import ActionButton from 'flarum/components/ui/action-button';
|
||||
|
||||
/**
|
||||
An alert message. Has a message, a `controls` item list, and a dismiss
|
||||
button.
|
||||
*/
|
||||
export default Ember.Component.extend(HasItemLists, {
|
||||
layoutName: 'components/ui/alert-message',
|
||||
classNames: ['alert'],
|
||||
classNameBindings: ['classForType'],
|
||||
itemLists: ['controls'],
|
||||
|
||||
message: '',
|
||||
type: '',
|
||||
dismissable: true,
|
||||
buttons: [],
|
||||
|
||||
classForType: Ember.computed('type', function() {
|
||||
return 'alert-'+this.get('type');
|
||||
}),
|
||||
|
||||
populateControls: function(controls) {
|
||||
var component = this;
|
||||
|
||||
this.get('buttons').forEach(function(button) {
|
||||
controls.pushObject(ActionButton.create({
|
||||
label: button.label,
|
||||
action: function() {
|
||||
component.send('dismiss');
|
||||
button.action();
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
if (this.get('dismissable')) {
|
||||
var dismiss = ActionButton.create({
|
||||
icon: 'times',
|
||||
className: 'btn btn-icon btn-link',
|
||||
action: function() { component.send('dismiss'); }
|
||||
});
|
||||
controls.pushObjectWithTag(dismiss, 'dismiss');
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
dismiss: function() {
|
||||
this.sendAction('dismiss', this);
|
||||
}
|
||||
}
|
||||
});
|
@@ -1,28 +0,0 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
label: '',
|
||||
icon: '',
|
||||
className: '',
|
||||
action: null,
|
||||
divider: false,
|
||||
active: false,
|
||||
|
||||
classNames: [],
|
||||
|
||||
tagName: 'a',
|
||||
attributeBindings: ['href', 'title'],
|
||||
classNameBindings: ['className'],
|
||||
href: '#',
|
||||
layout: Ember.Handlebars.compile('{{#if icon}}{{fa-icon icon class="fa-fw icon-glyph"}} {{/if}}<span>{{label}}</span>'),
|
||||
|
||||
click: function(e) {
|
||||
e.preventDefault();
|
||||
var action = this.get('action');
|
||||
if (typeof action === 'string') {
|
||||
this.sendAction('action');
|
||||
} else if (typeof action === 'function') {
|
||||
action();
|
||||
}
|
||||
}
|
||||
});
|
@@ -1,27 +0,0 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
items: null, // TaggedArray
|
||||
layoutName: 'components/ui/controls/dropdown-button',
|
||||
classNames: ['dropdown', 'btn-group'],
|
||||
classNameBindings: ['itemCountClass', 'class'],
|
||||
|
||||
label: 'Controls',
|
||||
icon: 'ellipsis-v',
|
||||
buttonClass: 'btn btn-default',
|
||||
menuClass: '',
|
||||
|
||||
dropdownMenuClass: function() {
|
||||
return 'dropdown-menu '+this.get('menuClass');
|
||||
}.property('menuClass'),
|
||||
|
||||
itemCountClass: function() {
|
||||
return 'item-count-'+this.get('items.length');
|
||||
}.property('items.length'),
|
||||
|
||||
actions: {
|
||||
buttonClick: function() {
|
||||
this.sendAction('buttonClick');
|
||||
}
|
||||
}
|
||||
});
|
@@ -1,28 +0,0 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
items: [],
|
||||
layoutName: 'components/ui/controls/dropdown-select',
|
||||
classNames: ['dropdown', 'dropdown-select', 'btn-group'],
|
||||
classNameBindings: ['itemCountClass', 'class'],
|
||||
|
||||
buttonClass: 'btn btn-default',
|
||||
menuClass: '',
|
||||
icon: 'ellipsis-v',
|
||||
|
||||
mainButtonClass: function() {
|
||||
return 'btn '+this.get('buttonClass');
|
||||
}.property('buttonClass'),
|
||||
|
||||
dropdownMenuClass: function() {
|
||||
return 'dropdown-menu '+this.get('menuClass');
|
||||
}.property('menuClass'),
|
||||
|
||||
itemCountClass: function() {
|
||||
return 'item-count-'+this.get('items.length');
|
||||
}.property('items.length'),
|
||||
|
||||
activeItem: function() {
|
||||
return this.get('menu.childViews').findBy('active');
|
||||
}.property('menu.childViews.@each.active')
|
||||
});
|
@@ -1,15 +0,0 @@
|
||||
import DropdownButton from './dropdown-button';
|
||||
|
||||
export default DropdownButton.extend({
|
||||
layoutName: 'components/ui/controls/dropdown-split',
|
||||
classNames: ['dropdown', 'dropdown-split', 'btn-group'],
|
||||
menuClass: 'pull-right',
|
||||
|
||||
mainButtonClass: function() {
|
||||
return 'btn '+this.get('buttonClass');
|
||||
}.property('buttonClass'),
|
||||
|
||||
firstItem: function() {
|
||||
return this.get('items').objectAt(0);
|
||||
}.property('items.[]')
|
||||
});
|
@@ -1,22 +0,0 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
import ComponentItem from '../items/component-item';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
tagName: 'ul',
|
||||
layoutName: 'components/ui/controls/item-list',
|
||||
|
||||
listItems: function() {
|
||||
if (!Ember.isArray(this.get('items'))) {
|
||||
return [];
|
||||
}
|
||||
var listItems = [];
|
||||
this.get('items').forEach(function(item) {
|
||||
if (item.get('tagName') !== 'li') {
|
||||
item = ComponentItem.extend({component: item});
|
||||
}
|
||||
listItems.push(item);
|
||||
});
|
||||
return listItems;
|
||||
}.property('items.[]')
|
||||
});
|
@@ -1,14 +0,0 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: ['loading-indicator'],
|
||||
|
||||
layout: Ember.Handlebars.compile(' '),
|
||||
size: 'small',
|
||||
|
||||
didInsertElement: function() {
|
||||
var size = this.get('size');
|
||||
Ember.$.fn.spin.presets[size].zIndex = 'auto';
|
||||
this.$().spin(size);
|
||||
}
|
||||
});
|
@@ -1,40 +0,0 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
classNames: ['search-input'],
|
||||
classNameBindings: ['active', 'value:clearable'],
|
||||
|
||||
layoutName: 'components/ui/controls/search-input',
|
||||
|
||||
didInsertElement: function() {
|
||||
var self = this;
|
||||
this.$().find('input').on('keydown', function(e) {
|
||||
if (e.which === 27) {
|
||||
self.clear();
|
||||
}
|
||||
});
|
||||
this.$().find('.clear').on('mousedown', function(e) {
|
||||
e.preventDefault();
|
||||
}).on('click', function(e) {
|
||||
e.preventDefault();
|
||||
self.clear();
|
||||
});
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
this.set('value', '');
|
||||
this.send('search');
|
||||
this.$().find('input').focus();
|
||||
},
|
||||
|
||||
willDestroyElement: function() {
|
||||
this.$().find('input').off('keydown');
|
||||
this.$().find('.clear').off('mousedown click');
|
||||
},
|
||||
|
||||
actions: {
|
||||
search: function() {
|
||||
this.get('action')(this.get('value'));
|
||||
}
|
||||
}
|
||||
});
|
@@ -1,9 +0,0 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
tagName: 'span',
|
||||
classNames: ['select-input'],
|
||||
optionValuePath: 'content',
|
||||
optionLabelPath: 'content',
|
||||
layout: Ember.Handlebars.compile('{{view "select" content=view.content optionValuePath=view.optionValuePath optionLabelPath=view.optionLabelPath value=view.value class="form-control"}} {{fa-icon "sort"}}')
|
||||
});
|
@@ -1,39 +0,0 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
import TaggedArray from '../../../utils/tagged-array';
|
||||
import ActionButton from './action-button';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
disabled: false,
|
||||
|
||||
classNames: ['text-editor'],
|
||||
|
||||
didInsertElement: function() {
|
||||
var controlItems = TaggedArray.create();
|
||||
this.trigger('populateControls', controlItems);
|
||||
this.set('controlItems', controlItems);
|
||||
|
||||
var component = this;
|
||||
this.$('textarea').bind('keydown', 'meta+return', function() {
|
||||
component.send('submit');
|
||||
});
|
||||
},
|
||||
|
||||
populateControls: function(controls) {
|
||||
var component = this;
|
||||
var submit = ActionButton.create({
|
||||
label: this.get('submitLabel'),
|
||||
className: 'btn btn-primary',
|
||||
action: function() {
|
||||
component.send('submit');
|
||||
}
|
||||
});
|
||||
controls.pushObjectWithTag(submit, 'submit');
|
||||
},
|
||||
|
||||
actions: {
|
||||
submit: function() {
|
||||
this.sendAction('submit', this.get('value'));
|
||||
}
|
||||
}
|
||||
});
|
@@ -1,18 +0,0 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.TextField.extend({
|
||||
didInsertElement: function() {
|
||||
var component = this;
|
||||
this.$().on('input', function() {
|
||||
var empty = !$(this).val();
|
||||
if (empty) {
|
||||
$(this).val(component.get('placeholder'));
|
||||
}
|
||||
$(this).css('width', 0);
|
||||
$(this).width($(this)[0].scrollWidth);
|
||||
if (empty) {
|
||||
$(this).val('');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
30
ember/app/components/ui/dropdown-button.js
Normal file
30
ember/app/components/ui/dropdown-button.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
/**
|
||||
Button which has an attached dropdown menu containing an item list.
|
||||
*/
|
||||
export default Ember.Component.extend({
|
||||
layoutName: 'components/ui/dropdown-button',
|
||||
classNames: ['dropdown', 'btn-group'],
|
||||
classNameBindings: ['itemCountClass', 'class'],
|
||||
|
||||
label: 'Controls',
|
||||
icon: 'ellipsis-v',
|
||||
buttonClass: 'btn btn-default',
|
||||
menuClass: '',
|
||||
items: null,
|
||||
|
||||
dropdownMenuClass: Ember.computed('menuClass', function() {
|
||||
return 'dropdown-menu '+this.get('menuClass');
|
||||
}),
|
||||
|
||||
itemCountClass: Ember.computed('items.length', function() {
|
||||
return 'item-count-'+this.get('items.length');
|
||||
}),
|
||||
|
||||
actions: {
|
||||
buttonClick: function() {
|
||||
this.sendAction('buttonClick');
|
||||
}
|
||||
}
|
||||
});
|
32
ember/app/components/ui/dropdown-select.js
Normal file
32
ember/app/components/ui/dropdown-select.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
/**
|
||||
Button which has an attached dropdown menu containing an item list. The
|
||||
currently-active item's label is displayed as the label of the button.
|
||||
*/
|
||||
export default Ember.Component.extend({
|
||||
layoutName: 'components/ui/dropdown-select',
|
||||
classNames: ['dropdown', 'dropdown-select', 'btn-group'],
|
||||
classNameBindings: ['itemCountClass', 'class'],
|
||||
|
||||
buttonClass: 'btn btn-default',
|
||||
menuClass: '',
|
||||
icon: 'ellipsis-v',
|
||||
items: [],
|
||||
|
||||
mainButtonClass: Ember.computed('buttonClass', function() {
|
||||
return 'btn '+this.get('buttonClass');
|
||||
}),
|
||||
|
||||
dropdownMenuClass: Ember.computed('menuClass', function() {
|
||||
return 'dropdown-menu '+this.get('menuClass');
|
||||
}),
|
||||
|
||||
itemCountClass: Ember.computed('items.length', function() {
|
||||
return 'item-count-'+this.get('items.length');
|
||||
}),
|
||||
|
||||
activeItem: Ember.computed('menu.childViews.@each.active', function() {
|
||||
return this.get('menu.childViews').findBy('active');
|
||||
})
|
||||
});
|
22
ember/app/components/ui/dropdown-split.js
Normal file
22
ember/app/components/ui/dropdown-split.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
import DropdownButton from 'flarum/components/ui/dropdown-button';
|
||||
|
||||
/**
|
||||
Given a list of items, this component displays a split button: the left side
|
||||
is the first item in the list, while the right side is a dropdown-toggle
|
||||
which shows a dropdown menu containing all of the items.
|
||||
*/
|
||||
export default DropdownButton.extend({
|
||||
layoutName: 'components/ui/dropdown-split',
|
||||
classNames: ['dropdown', 'dropdown-split', 'btn-group'],
|
||||
menuClass: 'pull-right',
|
||||
|
||||
mainButtonClass: Ember.computed('buttonClass', function() {
|
||||
return 'btn '+this.get('buttonClass');
|
||||
}),
|
||||
|
||||
firstItem: Ember.computed('items.[]', function() {
|
||||
return this.get('items').objectAt(0);
|
||||
})
|
||||
});
|
21
ember/app/components/ui/item-list.js
Normal file
21
ember/app/components/ui/item-list.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
/**
|
||||
Output a list of components within a <ul>, making sure each one is contained
|
||||
in an <li> element.
|
||||
*/
|
||||
export default Ember.Component.extend({
|
||||
layoutName: 'components/ui/item-list',
|
||||
tagName: 'ul',
|
||||
|
||||
listItems: Ember.computed('items.[]', function() {
|
||||
var items = this.get('items');
|
||||
if (!Ember.isArray(items)) {
|
||||
return [];
|
||||
}
|
||||
items.forEach(function(item) {
|
||||
item.set('isListItem', item.get('tagName') === 'li');
|
||||
});
|
||||
return items;
|
||||
})
|
||||
});
|
@@ -1,6 +0,0 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
tagName: 'li',
|
||||
layoutName: 'components/ui/items/component-item'
|
||||
});
|
@@ -1,37 +0,0 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
icon: '',
|
||||
label: '',
|
||||
action: null,
|
||||
badge: '',
|
||||
|
||||
tagName: 'li',
|
||||
classNameBindings: ['active'],
|
||||
active: function() {
|
||||
return !! this.get('childViews').anyBy('active');
|
||||
}.property('childViews.@each.active'),
|
||||
|
||||
// init: function() {
|
||||
// var params = this.params;
|
||||
// if (params[params.length - 1].queryParams) {
|
||||
// this.queryParamsObject = {values: params.pop().queryParams};
|
||||
// }
|
||||
|
||||
// this._super();
|
||||
// },
|
||||
|
||||
layout: function() {
|
||||
return Ember.Handlebars.compile('{{#link-to '+this.get('linkTo')+'}}'+this.get('iconTemplate')+' {{label}} <span class="count">{{badge}}</span>{{/link-to}}');
|
||||
}.property('linkTo', 'iconTemplate'),
|
||||
|
||||
iconTemplate: function() {
|
||||
return '{{fa-icon icon}}';
|
||||
}.property(),
|
||||
|
||||
actions: {
|
||||
main: function() {
|
||||
this.get('action')();
|
||||
}
|
||||
}
|
||||
});
|
@@ -1,6 +0,0 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
tagName: 'li',
|
||||
classNames: ['divider']
|
||||
});
|
19
ember/app/components/ui/loading-indicator.js
Normal file
19
ember/app/components/ui/loading-indicator.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
var precompileTemplate = Ember.Handlebars.compile;
|
||||
|
||||
/**
|
||||
Loading spinner.
|
||||
*/
|
||||
export default Ember.Component.extend({
|
||||
classNames: ['loading-indicator'],
|
||||
|
||||
layout: precompileTemplate(' '),
|
||||
size: 'small',
|
||||
|
||||
didInsertElement: function() {
|
||||
var size = this.get('size');
|
||||
Ember.$.fn.spin.presets[size].zIndex = 'auto';
|
||||
this.$().spin(size);
|
||||
}
|
||||
});
|
22
ember/app/components/ui/nav-item.js
Normal file
22
ember/app/components/ui/nav-item.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
var precompileTemplate = Ember.Handlebars.compile;
|
||||
|
||||
/**
|
||||
A list item which contains a navigation link. The list item's `active`
|
||||
property reflects whether or not the link is active.
|
||||
*/
|
||||
export default Ember.Component.extend({
|
||||
layout: precompileTemplate('{{#link-to routeName}}{{fa-icon icon}} {{label}} <span class="count">{{badge}}</span>{{/link-to}}'),
|
||||
tagName: 'li',
|
||||
classNameBindings: ['active'],
|
||||
|
||||
icon: '',
|
||||
label: '',
|
||||
badge: '',
|
||||
routeName: '',
|
||||
|
||||
active: Ember.computed('childViews.@each.active', function() {
|
||||
return !!this.get('childViews').anyBy('active');
|
||||
})
|
||||
});
|
36
ember/app/components/ui/search-input.js
Normal file
36
ember/app/components/ui/search-input.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
/**
|
||||
A basic search input. Comes with the ability to be cleared by pressing
|
||||
escape or with a button. Sends an action when enter is pressed.
|
||||
*/
|
||||
export default Ember.Component.extend({
|
||||
layoutName: 'components/ui/search-input',
|
||||
classNames: ['search-input'],
|
||||
classNameBindings: ['active', 'value:clearable'],
|
||||
|
||||
didInsertElement: function() {
|
||||
this.$('input').on('keydown', 'esc', function(e) {
|
||||
self.clear();
|
||||
});
|
||||
|
||||
var self = this;
|
||||
this.$('.clear').on('mousedown click', function(e) {
|
||||
e.preventDefault();
|
||||
}).on('click', function(e) {
|
||||
self.clear();
|
||||
});
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
this.set('value', '');
|
||||
this.send('search');
|
||||
this.$().find('input').focus();
|
||||
},
|
||||
|
||||
actions: {
|
||||
search: function() {
|
||||
this.get('action')(this.get('value'));
|
||||
}
|
||||
}
|
||||
});
|
16
ember/app/components/ui/select-input.js
Normal file
16
ember/app/components/ui/select-input.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
var precompileTemplate = Ember.Handlebars.compile;
|
||||
|
||||
/**
|
||||
A basic select input. Wraps Ember's select component with a span/icon so
|
||||
that we can style it more fancily.
|
||||
*/
|
||||
export default Ember.Component.extend({
|
||||
layout: precompileTemplate('{{view "select" content=view.content optionValuePath=view.optionValuePath optionLabelPath=view.optionLabelPath value=view.value class="form-control"}} {{fa-icon "sort"}}'),
|
||||
tagName: 'span',
|
||||
classNames: ['select-input'],
|
||||
|
||||
optionValuePath: 'content',
|
||||
optionLabelPath: 'content'
|
||||
});
|
9
ember/app/components/ui/separator-item.js
Normal file
9
ember/app/components/ui/separator-item.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
/**
|
||||
A simple separator list item for use in menus.
|
||||
*/
|
||||
export default Ember.Component.extend({
|
||||
tagName: 'li',
|
||||
classNames: ['divider']
|
||||
});
|
33
ember/app/components/ui/text-editor.js
Normal file
33
ember/app/components/ui/text-editor.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
import HasItemLists from 'flarum/mixins/has-item-lists';
|
||||
import ActionButton from 'flarum/components/ui/action-button';
|
||||
|
||||
/**
|
||||
A text editor. Contains a textarea and an item list of `controls`, including
|
||||
a submit button.
|
||||
*/
|
||||
export default Ember.Component.extend(HasItemLists, {
|
||||
classNames: ['text-editor'],
|
||||
itemLists: ['controls'],
|
||||
|
||||
value: '',
|
||||
disabled: false,
|
||||
|
||||
didInsertElement: function() {
|
||||
var component = this;
|
||||
this.$('textarea').bind('keydown', 'meta+return', function() {
|
||||
component.send('submit');
|
||||
});
|
||||
},
|
||||
|
||||
populateControls: function(items) {
|
||||
this.addActionItem(items, 'submit', this.get('submitLabel')).set('className', 'btn btn-primary');
|
||||
},
|
||||
|
||||
actions: {
|
||||
submit: function() {
|
||||
this.sendAction('submit', this.get('value'));
|
||||
}
|
||||
}
|
||||
});
|
26
ember/app/components/ui/text-input.js
Normal file
26
ember/app/components/ui/text-input.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
/**
|
||||
An extension of Ember's text field with an option to set up an auto-growing
|
||||
text input.
|
||||
*/
|
||||
export default Ember.TextField.extend({
|
||||
autoGrow: false,
|
||||
|
||||
didInsertElement: function() {
|
||||
if (this.get('autoGrow')) {
|
||||
var component = this;
|
||||
this.$().on('input', function() {
|
||||
var empty = !$(this).val();
|
||||
if (empty) {
|
||||
$(this).val(component.get('placeholder'));
|
||||
}
|
||||
$(this).css('width', 0);
|
||||
$(this).width($(this)[0].scrollWidth);
|
||||
if (empty) {
|
||||
$(this).val('');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
Reference in New Issue
Block a user