diff --git a/app/assets/javascripts/discourse-common/components/combo-box.js.es6 b/app/assets/javascripts/discourse-common/components/combo-box.js.es6 index 2325d8b14be..2a2c4e2ba77 100644 --- a/app/assets/javascripts/discourse-common/components/combo-box.js.es6 +++ b/app/assets/javascripts/discourse-common/components/combo-box.js.es6 @@ -81,7 +81,11 @@ export default Ember.Component.extend(bufferedRender({ } this.set('value', val); }); - $elem.trigger('change'); + Ember.run.scheduleOnce('afterRender', this, this._triggerChange); + }, + + _triggerChange() { + this.$().trigger('change'); }, @on('willDestroyElement') diff --git a/app/assets/javascripts/discourse-common/lib/helpers.js.es6 b/app/assets/javascripts/discourse-common/lib/helpers.js.es6 index 486e5b3ebdd..8960a57ed88 100644 --- a/app/assets/javascripts/discourse-common/lib/helpers.js.es6 +++ b/app/assets/javascripts/discourse-common/lib/helpers.js.es6 @@ -1,14 +1,11 @@ import { get } from 'discourse-common/lib/raw-handlebars'; -function fixArgs(args) { - return (args.length > 1) ? args[0].concat(args[args.length-1]) : args; -} - // `Ember.Helper` is only available in versions after 1.12 export function htmlHelper(fn) { if (Ember.Helper) { return Ember.Helper.helper(function(...args) { - return new Handlebars.SafeString(fn.apply(this, fixArgs(args)) || ''); + args = (args.length > 1) ? args[0].concat({ hash: args[args.length-1] }) : args; + return new Handlebars.SafeString(fn.apply(this, args) || ''); }); } else { return Ember.Handlebars.makeBoundHelper(function() { diff --git a/app/assets/javascripts/discourse/components/color-picker-choice.js.es6 b/app/assets/javascripts/discourse/components/color-picker-choice.js.es6 new file mode 100644 index 00000000000..78f444a1c12 --- /dev/null +++ b/app/assets/javascripts/discourse/components/color-picker-choice.js.es6 @@ -0,0 +1,27 @@ +import computed from 'ember-addons/ember-computed-decorators'; + +export default Ember.Component.extend({ + tagName: 'button', + attributeBindings: ['style', 'title'], + classNameBindings: [':colorpicker', 'isUsed:used-color:unused-color'], + + @computed('color', 'usedColors') + isUsed(color, usedColors) { + return (usedColors || []).indexOf(color.toUpperCase()) >= 0; + }, + + @computed('isUsed') + title(isUsed) { + return isUsed ? I18n.t("category.already_used") : null; + }, + + @computed('color') + style(color) { + return `background-color: #${color};`.htmlSafe(); + }, + + click(e) { + e.preventDefault(); + this.sendAction('selectColor', this.get('color')); + } +}); diff --git a/app/assets/javascripts/discourse/components/color-picker.js.es6 b/app/assets/javascripts/discourse/components/color-picker.js.es6 index d1acf7d8114..30c95f9ca21 100644 --- a/app/assets/javascripts/discourse/components/color-picker.js.es6 +++ b/app/assets/javascripts/discourse/components/color-picker.js.es6 @@ -1,30 +1,9 @@ -import DiscourseContainerView from 'discourse/views/container'; - -export default DiscourseContainerView.extend({ +export default Ember.Component.extend({ classNames: 'colors-container', - _createButtons: function() { - var colors = this.get('colors'), - isUsed, usedColors = this.get('usedColors') || []; - - if (!colors) return; - - var self = this; - colors.forEach(function(color) { - isUsed = usedColors.indexOf(color.toUpperCase()) >= 0; - - self.attachViewWithArgs({ - tagName: 'button', - attributeBindings: ['style', 'title'], - classNames: ['colorpicker'].concat( isUsed ? ['used-color'] : ['unused-color'] ), - style: ('background-color: #' + color + ';').htmlSafe(), - title: isUsed ? I18n.t("category.already_used") : null, - click: function() { - self.set("value", color); - return false; - } - }); - - }); - }.on('init') + actions: { + selectColor(color) { + this.set('value', color); + } + } }); diff --git a/app/assets/javascripts/discourse/components/composer-messages.js.es6 b/app/assets/javascripts/discourse/components/composer-messages.js.es6 index 52d1da32a65..59b3586dd32 100644 --- a/app/assets/javascripts/discourse/components/composer-messages.js.es6 +++ b/app/assets/javascripts/discourse/components/composer-messages.js.es6 @@ -15,12 +15,12 @@ export default Ember.Component.extend({ didInsertElement() { this._super(); - this.reset(); this.appEvents.on('composer:typed-reply', this, this._typedReply); this.appEvents.on('composer:opened', this, this._findMessages); this.appEvents.on('composer:find-similar', this, this._findSimilar); this.appEvents.on('composer-messages:close', this, this._closeTop); this.appEvents.on('composer-messages:create', this, this._create); + Ember.run.scheduleOnce('afterRender', this, this.reset); }, willDestroyElement() { diff --git a/app/assets/javascripts/discourse/components/d-editor.js.es6 b/app/assets/javascripts/discourse/components/d-editor.js.es6 index 30759cac150..0d6b37dcc90 100644 --- a/app/assets/javascripts/discourse/components/d-editor.js.es6 +++ b/app/assets/javascripts/discourse/components/d-editor.js.es6 @@ -201,18 +201,23 @@ export default Ember.Component.extend({ return null; }, - @on('didInsertElement') - _startUp() { + _readyNow() { + this.set('ready', true); + }, + + didInsertElement() { + this._super(); + const container = this.get('container'), $editorInput = this.$('.d-editor-input'); this._applyEmojiAutocomplete(container, $editorInput); this._applyCategoryHashtagAutocomplete(container, $editorInput); - this.set('ready', true); + + Ember.run.scheduleOnce('afterRender', this, this._readyNow); const mouseTrap = Mousetrap(this.$('.d-editor-input')[0]); - const shortcuts = this.get('toolbar.shortcuts'); Object.keys(shortcuts).forEach(sc => { const button = shortcuts[sc]; @@ -232,7 +237,6 @@ export default Ember.Component.extend({ this.appEvents.on('composer:insert-text', text => this._addText(this._getSelected(), text)); this.appEvents.on('composer:replace-text', (oldVal, newVal) => this._replaceText(oldVal, newVal)); - this._mouseTrap = mouseTrap; }, @@ -263,11 +267,10 @@ export default Ember.Component.extend({ markdownOptions.siteSettings = this.siteSettings; this.set('preview', cook(value)); - Ember.run.scheduleOnce('afterRender', () => { + Ember.run.next(() => { if (this._state !== "inDOM") { return; } const $preview = this.$('.d-editor-preview'); if ($preview.length === 0) return; - this.sendAction('previewUpdated', $preview); }); }, diff --git a/app/assets/javascripts/discourse/components/edit-category-tab.js.es6 b/app/assets/javascripts/discourse/components/edit-category-tab.js.es6 index 9e470660675..556e072ea15 100644 --- a/app/assets/javascripts/discourse/components/edit-category-tab.js.es6 +++ b/app/assets/javascripts/discourse/components/edit-category-tab.js.es6 @@ -14,9 +14,14 @@ export default Em.Component.extend({ return I18n.t('category.' + this.get('tab').replace('-', '_')); }.property('tab'), + didInsertElement() { + this._super(); + Ember.run.scheduleOnce('afterRender', this, this._addToCollection); + }, + _addToCollection: function() { this.get('panels').addObject(this.get('tabClassName')); - }.on('didInsertElement'), + }, actions: { select: function() { diff --git a/app/assets/javascripts/discourse/components/image-uploader.js.es6 b/app/assets/javascripts/discourse/components/image-uploader.js.es6 index 08359fa8695..8e7d0420c61 100644 --- a/app/assets/javascripts/discourse/components/image-uploader.js.es6 +++ b/app/assets/javascripts/discourse/components/image-uploader.js.es6 @@ -6,7 +6,7 @@ export default Em.Component.extend(UploadMixin, { @computed('imageUrl') backgroundStyle(imageUrl) { - if (Em.isNone(imageUrl)) { return; } + if (Em.isNone(imageUrl)) { return "".htmlSafe(); } return `background-image: url(${imageUrl})`.htmlSafe(); }, diff --git a/app/assets/javascripts/discourse/components/topic-navigation.js.es6 b/app/assets/javascripts/discourse/components/topic-navigation.js.es6 index c7b28ca17c0..5e72830c017 100644 --- a/app/assets/javascripts/discourse/components/topic-navigation.js.es6 +++ b/app/assets/javascripts/discourse/components/topic-navigation.js.es6 @@ -5,6 +5,8 @@ export default Ember.Component.extend({ info: Em.Object.create(), _checkSize() { + if (!this.element || this.isDestroying || this.isDestroyed) { return; } + let info = this.get('info'); if (info.get('topicProgressExpanded')) { @@ -110,7 +112,7 @@ export default Ember.Component.extend({ $('#reply-control').on('div-resized.discourse-topic-navigation', () => this._checkSize()); } - this._checkSize(); + Ember.run.scheduleOnce('afterRender', this, this._checkSize); }, willDestroyElement() { diff --git a/app/assets/javascripts/discourse/helpers/as-hash.js.es6 b/app/assets/javascripts/discourse/helpers/as-hash.js.es6 index c5c67a64e02..caf112d3567 100644 --- a/app/assets/javascripts/discourse/helpers/as-hash.js.es6 +++ b/app/assets/javascripts/discourse/helpers/as-hash.js.es6 @@ -1,8 +1,12 @@ +import { registerHelper } from 'discourse-common/lib/helpers'; + // Note: Later versions of ember include `hash` -export default function hashHelper(params) { +registerHelper('as-hash', function(_, params) { + if (Ember.Helper) { return params; } + const hash = {}; Object.keys(params.hash).forEach(k => { hash[k] = params.data.view.getStream(params.hash[k]).value(); }); return hash; -} +}); diff --git a/app/assets/javascripts/discourse/helpers/plugin-outlet.js.es6 b/app/assets/javascripts/discourse/helpers/plugin-outlet.js.es6 index 602426d2c6b..00a4307d7cb 100644 --- a/app/assets/javascripts/discourse/helpers/plugin-outlet.js.es6 +++ b/app/assets/javascripts/discourse/helpers/plugin-outlet.js.es6 @@ -144,21 +144,24 @@ registerHelper('plugin-outlet', function([connectionName], hash, options, env) { // just shove it in. const viewClass = (childViews.length > 1) ? Ember.ContainerView : childViews[0]; - const newHash = $.extend({}, viewInjections(env.data.view.container)); - if (hash.tagName) { newHash.tagName = hash.tagName; } + // TODO: Figure out how to do this without a container view + if (env) { + const newHash = $.extend({}, viewInjections(env.data.view.container)); + if (hash.tagName) { newHash.tagName = hash.tagName; } - // we don't need the default template since we have a connector - delete options.fn; - delete options.template; - env.helpers.view.helperFunction.call(this, [viewClass], newHash, options, env); + // we don't need the default template since we have a connector + delete options.fn; + delete options.template; + env.helpers.view.helperFunction.call(this, [viewClass], newHash, options, env); - const cvs = env.data.view._childViews; - if (childViews.length > 1 && cvs && cvs.length) { - const inserted = cvs[cvs.length-1]; - if (inserted) { - childViews.forEach(function(cv) { - inserted.pushObject(cv.create()); - }); + const cvs = env.data.view._childViews; + if (childViews.length > 1 && cvs && cvs.length) { + const inserted = cvs[cvs.length-1]; + if (inserted) { + childViews.forEach(function(cv) { + inserted.pushObject(cv.create()); + }); + } } } } diff --git a/app/assets/javascripts/discourse/models/admin-post.js.es6 b/app/assets/javascripts/discourse/models/admin-post.js.es6 index 4504fcbe24e..8de331ac955 100644 --- a/app/assets/javascripts/discourse/models/admin-post.js.es6 +++ b/app/assets/javascripts/discourse/models/admin-post.js.es6 @@ -9,7 +9,7 @@ export default Post.extend({ } }.on("init"), - presentName: Em.computed.any('name', 'username'), + presentName: Ember.computed.or('name', 'username'), sameUser: function() { return this.get("username") === Discourse.User.currentProp("username"); diff --git a/app/assets/javascripts/discourse/models/user-action.js.es6 b/app/assets/javascripts/discourse/models/user-action.js.es6 index 024089799ae..ebc4be7381b 100644 --- a/app/assets/javascripts/discourse/models/user-action.js.es6 +++ b/app/assets/javascripts/discourse/models/user-action.js.es6 @@ -76,9 +76,9 @@ const UserAction = RestModel.extend({ return targetUsername === Discourse.User.currentProp('username'); }, - presentName: Em.computed.any('name', 'username'), - targetDisplayName: Em.computed.any('target_name', 'target_username'), - actingDisplayName: Em.computed.any('acting_name', 'acting_username'), + presentName: Ember.computed.or('name', 'username'), + targetDisplayName: Ember.computed.or('target_name', 'target_username'), + actingDisplayName: Ember.computed.or('acting_name', 'acting_username'), targetUserUrl: url('target_username', '/users/%@'), @computed("username") diff --git a/app/assets/javascripts/discourse/models/user.js.es6 b/app/assets/javascripts/discourse/models/user.js.es6 index 6328ca9ca81..e4f92d6b340 100644 --- a/app/assets/javascripts/discourse/models/user.js.es6 +++ b/app/assets/javascripts/discourse/models/user.js.es6 @@ -64,7 +64,7 @@ const User = RestModel.extend({ @computed('profile_background') profileBackground(bgUrl) { - if (Em.isEmpty(bgUrl) || !Discourse.SiteSettings.allow_profile_backgrounds) { return; } + if (Em.isEmpty(bgUrl) || !Discourse.SiteSettings.allow_profile_backgrounds) { return "".htmlSafe(); } return ('background-image: url(' + Discourse.getURLWithCDN(bgUrl) + ')').htmlSafe(); }, @@ -322,7 +322,7 @@ const User = RestModel.extend({ @computed("stats.@each.isPM") statsExcludingPms() { if (Ember.isEmpty(this.get('stats'))) return []; - return this.get('stats').rejectProperty('isPM'); + return this.get('stats').rejectBy('isPM'); }, findDetails(options) { @@ -530,7 +530,7 @@ User.reopenClass(Singleton, { }); const result = Em.A(); - result.pushObjects(stats.rejectProperty('isResponse')); + result.pushObjects(stats.rejectBy('isResponse')); let insertAt = 0; result.forEach((item, index) => { diff --git a/app/assets/javascripts/discourse/templates/components/color-picker.hbs b/app/assets/javascripts/discourse/templates/components/color-picker.hbs new file mode 100644 index 00000000000..5842bf91512 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/color-picker.hbs @@ -0,0 +1 @@ +{{#each colors as |c|}}{{color-picker-choice color=c usedColors=usedColors selectColor="selectColor"}}{{/each}} diff --git a/app/assets/javascripts/discourse/templates/mobile/discovery/categories.hbs b/app/assets/javascripts/discourse/templates/mobile/discovery/categories.hbs index 2a5d9878891..2c93702e92f 100644 --- a/app/assets/javascripts/discourse/templates/mobile/discovery/categories.hbs +++ b/app/assets/javascripts/discourse/templates/mobile/discovery/categories.hbs @@ -1,5 +1,5 @@ {{#each model.categories as |c|}} -
diff --git a/app/assets/javascripts/discourse/views/container.js.es6 b/app/assets/javascripts/discourse/views/container.js.es6 deleted file mode 100644 index f7a474fc020..00000000000 --- a/app/assets/javascripts/discourse/views/container.js.es6 +++ /dev/null @@ -1,16 +0,0 @@ -export default Ember.ContainerView.extend({ - - attachViewWithArgs(viewArgs, viewClass) { - if (typeof viewClass === "string") { - viewClass = this.container.lookupFactory("view:" + viewClass) || - this.container.lookupFactory("component:" + viewClass); - } - - if (!viewClass) { viewClass = Ember.View.extend(); } - this.pushObject(this.createChildView(viewClass, viewArgs)); - }, - - attachViewClass(viewClass) { - this.attachViewWithArgs(null, viewClass); - } -}); diff --git a/app/assets/javascripts/discourse/views/modal-body.js.es6 b/app/assets/javascripts/discourse/views/modal-body.js.es6 index f3dfa7c937f..55ce0fca0ba 100644 --- a/app/assets/javascripts/discourse/views/modal-body.js.es6 +++ b/app/assets/javascripts/discourse/views/modal-body.js.es6 @@ -7,10 +7,12 @@ export default Ember.View.extend({ _setupModal() { $('#modal-alert').hide(); $('#discourse-modal').modal('show'); + Ember.run.scheduleOnce('afterRender', this, this._afterFirstRender); + }, - // Focus on first element + _afterFirstRender() { if (!this.site.mobileView && this.get('focusInput')) { - Em.run.schedule('afterRender', () => this.$('input:first').focus()); + this.$('input:first').focus(); } const title = this.get('title'); diff --git a/app/assets/javascripts/discourse/views/user.js.es6 b/app/assets/javascripts/discourse/views/user.js.es6 index f0b0ceb85d1..0b358f18eef 100644 --- a/app/assets/javascripts/discourse/views/user.js.es6 +++ b/app/assets/javascripts/discourse/views/user.js.es6 @@ -1,3 +1,4 @@ import ScrollTop from 'discourse/mixins/scroll-top'; -export default Ember.View.extend(ScrollTop); +export default Ember.View.extend(ScrollTop, { +}); diff --git a/app/assets/javascripts/discourse/widgets/search-menu.js.es6 b/app/assets/javascripts/discourse/widgets/search-menu.js.es6 index 23f86461b44..9ed3b8c7d4f 100644 --- a/app/assets/javascripts/discourse/widgets/search-menu.js.es6 +++ b/app/assets/javascripts/discourse/widgets/search-menu.js.es6 @@ -71,7 +71,7 @@ export default createWidget('search-menu', { const contextEnabled = searchData.contextEnabled; const ctx = contextEnabled ? this.searchContext() : null; - const type = Ember.get(ctx, 'type'); + const type = ctx ? Ember.get(ctx, 'type') : null; if (contextEnabled && type === 'topic') { return; diff --git a/app/assets/javascripts/main_include.js b/app/assets/javascripts/main_include.js index 19f20a2a09c..440edeee65f 100644 --- a/app/assets/javascripts/main_include.js +++ b/app/assets/javascripts/main_include.js @@ -57,7 +57,6 @@ //= require ./discourse/models/user-badge //= require ./discourse/controllers/discovery-sortable //= require ./discourse/controllers/navigation/default -//= require ./discourse/views/container //= require ./discourse/views/modal-body //= require ./discourse/views/flag //= require ./discourse/components/edit-category-panel diff --git a/app/assets/javascripts/wizard/test/helpers/component-test.js.es6 b/app/assets/javascripts/wizard/test/helpers/component-test.js.es6 index 806c9af8a0e..2a299d54571 100644 --- a/app/assets/javascripts/wizard/test/helpers/component-test.js.es6 +++ b/app/assets/javascripts/wizard/test/helpers/component-test.js.es6 @@ -4,7 +4,7 @@ export function componentTest(name, opts) { opts = opts || {}; test(name, function(assert) { - initializer.initialize(); + initializer.initialize(this.container, this.registry); if (opts.setup) { opts.setup.call(this); diff --git a/app/assets/javascripts/wizard/test/helpers/start-app.js.es6 b/app/assets/javascripts/wizard/test/helpers/start-app.js.es6 index 7d701562b38..0b8118ed007 100644 --- a/app/assets/javascripts/wizard/test/helpers/start-app.js.es6 +++ b/app/assets/javascripts/wizard/test/helpers/start-app.js.es6 @@ -8,7 +8,7 @@ export default function() { Ember.run(() => app = Wizard.create({ rootElement: '#ember-testing' })); if (!started) { - initializer.initialize(); + initializer.initialize(app.__container__, app.registry); app.start(); started = true; } diff --git a/app/assets/javascripts/wizard/wizard.js.es6 b/app/assets/javascripts/wizard/wizard.js.es6 index 5881ac473be..466b656d83c 100644 --- a/app/assets/javascripts/wizard/wizard.js.es6 +++ b/app/assets/javascripts/wizard/wizard.js.es6 @@ -9,7 +9,7 @@ export default Ember.Application.extend({ if (/\/initializers\//.test(key)) { const module = require(key, null, null, true); if (!module) { throw new Error(key + ' must export an initializer.'); } - this.instanceInitializer(module.default); + this.initializer(module.default); } }); } diff --git a/test/javascripts/helpers/component-test.js.es6 b/test/javascripts/helpers/component-test.js.es6 index 7e8fc08eeb7..f671adb8e48 100644 --- a/test/javascripts/helpers/component-test.js.es6 +++ b/test/javascripts/helpers/component-test.js.es6 @@ -21,7 +21,7 @@ export default function(name, opts) { this.siteSettings = Discourse.SiteSettings; - autoLoadModules(); + autoLoadModules(this.container, this.registry); const store = createStore(); if (!opts.anonymous) { diff --git a/test/javascripts/views/container-view-test.js.es6 b/test/javascripts/views/container-view-test.js.es6 deleted file mode 100644 index 0ebd5808d3b..00000000000 --- a/test/javascripts/views/container-view-test.js.es6 +++ /dev/null @@ -1,83 +0,0 @@ -var SomeViewClass = Ember.View.extend(); - -function containerHasOnlyOneChild(containerView, klass) { - equal(containerView.get('childViews').length, 1, "container has no other children than the one created by method"); - ok(containerView.objectAt(0) instanceof klass, "container's child created by method is an instance of a correct class"); -} - -function containerHasTwoChildren(containerView, klass1, klass2) { - equal(containerView.get('childViews').length, 2, "container has both already existing and newly created children"); - ok(containerView.objectAt(0) instanceof klass1, "already existing child's class is correct"); - ok(containerView.objectAt(1) instanceof klass2, "newly created child's class is correct"); -} - -function childHasProperty(containerView, name) { - equal(containerView.objectAt(0).get(name), name, "method passes properties to the container's child it creates"); -} - -moduleFor("view:container"); - -test("attachViewWithArgs: creates a view of a given class with given properties and appends it to the container", function() { - var containerView = this.subject(); - containerView.attachViewWithArgs({foo: "foo"}, SomeViewClass); - containerHasOnlyOneChild(containerView, SomeViewClass); - childHasProperty(containerView, "foo"); -}); - -test("attachViewWithArgs: creates a view of a given class without any properties and appends it to the container", function() { - - var containerView = this.subject(); - containerView.attachViewWithArgs(null, SomeViewClass); - containerHasOnlyOneChild(containerView, SomeViewClass); -}); - -test("attachViewWithArgs: creates a view without class specified (Ember.View is used by default) with given properties and appends it to the container", function() { - var containerView = this.subject(); - containerView.attachViewWithArgs({foo: "foo"}); - - containerHasOnlyOneChild(containerView, Ember.View); - childHasProperty(containerView, "foo"); -}); - -test("attachViewWithArgs: creates a view without class specified (Ember.View is used by default) without any properties and appends it to the container", function() { - var containerView = this.subject(); - containerView.attachViewWithArgs(); - - containerHasOnlyOneChild(containerView, Ember.View); -}); - -test("attachViewWithArgs: appends a view to a container already containing other views", function() { - var AlreadyContainedViewClass = Ember.View.extend(); - var alreadyContainedView = AlreadyContainedViewClass.create(); - var containerView = this.subject(); - containerView.pushObject(alreadyContainedView); - - containerView.attachViewWithArgs(null, SomeViewClass); - - containerHasTwoChildren(containerView, AlreadyContainedViewClass, SomeViewClass); -}); - -test("attachViewClass: creates a view of a given class without any properties and appends it to the container", function() { - var containerView = this.subject(); - containerView.attachViewClass(SomeViewClass); - - containerHasOnlyOneChild(containerView, SomeViewClass); -}); - -test("attachViewClass: creates a view without class specified (Ember.View is used by default) without any properties and appends it to the container", function() { - var containerView = this.subject(); - containerView.attachViewClass(); - - containerHasOnlyOneChild(containerView, Ember.View); -}); - -test("attachViewClass: appends a view to a container already containing other views", function() { - var AlreadyContainedViewClass = Ember.View.extend(); - var alreadyContainedView = AlreadyContainedViewClass.create(); - var containerView = this.subject(); - containerView.pushObject(alreadyContainedView); - - containerView.attachViewClass(SomeViewClass); - - containerHasTwoChildren(containerView, AlreadyContainedViewClass, SomeViewClass); -}); |
---|