Final set of backwards compatible fixes for Ember 1.13

This commit is contained in:
Robin Ward 2016-10-28 15:51:19 -04:00
parent 8c9d390cac
commit a319cfe77a
26 changed files with 103 additions and 175 deletions

View File

@ -81,7 +81,11 @@ export default Ember.Component.extend(bufferedRender({
} }
this.set('value', val); this.set('value', val);
}); });
$elem.trigger('change'); Ember.run.scheduleOnce('afterRender', this, this._triggerChange);
},
_triggerChange() {
this.$().trigger('change');
}, },
@on('willDestroyElement') @on('willDestroyElement')

View File

@ -1,14 +1,11 @@
import { get } from 'discourse-common/lib/raw-handlebars'; 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 // `Ember.Helper` is only available in versions after 1.12
export function htmlHelper(fn) { export function htmlHelper(fn) {
if (Ember.Helper) { if (Ember.Helper) {
return Ember.Helper.helper(function(...args) { 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 { } else {
return Ember.Handlebars.makeBoundHelper(function() { return Ember.Handlebars.makeBoundHelper(function() {

View File

@ -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'));
}
});

View File

@ -1,30 +1,9 @@
import DiscourseContainerView from 'discourse/views/container'; export default Ember.Component.extend({
export default DiscourseContainerView.extend({
classNames: 'colors-container', classNames: 'colors-container',
_createButtons: function() { actions: {
var colors = this.get('colors'), selectColor(color) {
isUsed, usedColors = this.get('usedColors') || []; this.set('value', color);
}
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')
});

View File

@ -15,12 +15,12 @@ export default Ember.Component.extend({
didInsertElement() { didInsertElement() {
this._super(); this._super();
this.reset();
this.appEvents.on('composer:typed-reply', this, this._typedReply); this.appEvents.on('composer:typed-reply', this, this._typedReply);
this.appEvents.on('composer:opened', this, this._findMessages); this.appEvents.on('composer:opened', this, this._findMessages);
this.appEvents.on('composer:find-similar', this, this._findSimilar); this.appEvents.on('composer:find-similar', this, this._findSimilar);
this.appEvents.on('composer-messages:close', this, this._closeTop); this.appEvents.on('composer-messages:close', this, this._closeTop);
this.appEvents.on('composer-messages:create', this, this._create); this.appEvents.on('composer-messages:create', this, this._create);
Ember.run.scheduleOnce('afterRender', this, this.reset);
}, },
willDestroyElement() { willDestroyElement() {

View File

@ -201,18 +201,23 @@ export default Ember.Component.extend({
return null; return null;
}, },
@on('didInsertElement') _readyNow() {
_startUp() { this.set('ready', true);
},
didInsertElement() {
this._super();
const container = this.get('container'), const container = this.get('container'),
$editorInput = this.$('.d-editor-input'); $editorInput = this.$('.d-editor-input');
this._applyEmojiAutocomplete(container, $editorInput); this._applyEmojiAutocomplete(container, $editorInput);
this._applyCategoryHashtagAutocomplete(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 mouseTrap = Mousetrap(this.$('.d-editor-input')[0]);
const shortcuts = this.get('toolbar.shortcuts'); const shortcuts = this.get('toolbar.shortcuts');
Object.keys(shortcuts).forEach(sc => { Object.keys(shortcuts).forEach(sc => {
const button = shortcuts[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:insert-text', text => this._addText(this._getSelected(), text));
this.appEvents.on('composer:replace-text', (oldVal, newVal) => this._replaceText(oldVal, newVal)); this.appEvents.on('composer:replace-text', (oldVal, newVal) => this._replaceText(oldVal, newVal));
this._mouseTrap = mouseTrap; this._mouseTrap = mouseTrap;
}, },
@ -263,11 +267,10 @@ export default Ember.Component.extend({
markdownOptions.siteSettings = this.siteSettings; markdownOptions.siteSettings = this.siteSettings;
this.set('preview', cook(value)); this.set('preview', cook(value));
Ember.run.scheduleOnce('afterRender', () => { Ember.run.next(() => {
if (this._state !== "inDOM") { return; } if (this._state !== "inDOM") { return; }
const $preview = this.$('.d-editor-preview'); const $preview = this.$('.d-editor-preview');
if ($preview.length === 0) return; if ($preview.length === 0) return;
this.sendAction('previewUpdated', $preview); this.sendAction('previewUpdated', $preview);
}); });
}, },

View File

@ -14,9 +14,14 @@ export default Em.Component.extend({
return I18n.t('category.' + this.get('tab').replace('-', '_')); return I18n.t('category.' + this.get('tab').replace('-', '_'));
}.property('tab'), }.property('tab'),
didInsertElement() {
this._super();
Ember.run.scheduleOnce('afterRender', this, this._addToCollection);
},
_addToCollection: function() { _addToCollection: function() {
this.get('panels').addObject(this.get('tabClassName')); this.get('panels').addObject(this.get('tabClassName'));
}.on('didInsertElement'), },
actions: { actions: {
select: function() { select: function() {

View File

@ -6,7 +6,7 @@ export default Em.Component.extend(UploadMixin, {
@computed('imageUrl') @computed('imageUrl')
backgroundStyle(imageUrl) { backgroundStyle(imageUrl) {
if (Em.isNone(imageUrl)) { return; } if (Em.isNone(imageUrl)) { return "".htmlSafe(); }
return `background-image: url(${imageUrl})`.htmlSafe(); return `background-image: url(${imageUrl})`.htmlSafe();
}, },

View File

@ -5,6 +5,8 @@ export default Ember.Component.extend({
info: Em.Object.create(), info: Em.Object.create(),
_checkSize() { _checkSize() {
if (!this.element || this.isDestroying || this.isDestroyed) { return; }
let info = this.get('info'); let info = this.get('info');
if (info.get('topicProgressExpanded')) { if (info.get('topicProgressExpanded')) {
@ -110,7 +112,7 @@ export default Ember.Component.extend({
$('#reply-control').on('div-resized.discourse-topic-navigation', () => this._checkSize()); $('#reply-control').on('div-resized.discourse-topic-navigation', () => this._checkSize());
} }
this._checkSize(); Ember.run.scheduleOnce('afterRender', this, this._checkSize);
}, },
willDestroyElement() { willDestroyElement() {

View File

@ -1,8 +1,12 @@
import { registerHelper } from 'discourse-common/lib/helpers';
// Note: Later versions of ember include `hash` // Note: Later versions of ember include `hash`
export default function hashHelper(params) { registerHelper('as-hash', function(_, params) {
if (Ember.Helper) { return params; }
const hash = {}; const hash = {};
Object.keys(params.hash).forEach(k => { Object.keys(params.hash).forEach(k => {
hash[k] = params.data.view.getStream(params.hash[k]).value(); hash[k] = params.data.view.getStream(params.hash[k]).value();
}); });
return hash; return hash;
} });

View File

@ -144,6 +144,8 @@ registerHelper('plugin-outlet', function([connectionName], hash, options, env) {
// just shove it in. // just shove it in.
const viewClass = (childViews.length > 1) ? Ember.ContainerView : childViews[0]; const viewClass = (childViews.length > 1) ? Ember.ContainerView : childViews[0];
// TODO: Figure out how to do this without a container view
if (env) {
const newHash = $.extend({}, viewInjections(env.data.view.container)); const newHash = $.extend({}, viewInjections(env.data.view.container));
if (hash.tagName) { newHash.tagName = hash.tagName; } if (hash.tagName) { newHash.tagName = hash.tagName; }
@ -162,6 +164,7 @@ registerHelper('plugin-outlet', function([connectionName], hash, options, env) {
} }
} }
} }
}
}); });
// No longer used // No longer used

View File

@ -9,7 +9,7 @@ export default Post.extend({
} }
}.on("init"), }.on("init"),
presentName: Em.computed.any('name', 'username'), presentName: Ember.computed.or('name', 'username'),
sameUser: function() { sameUser: function() {
return this.get("username") === Discourse.User.currentProp("username"); return this.get("username") === Discourse.User.currentProp("username");

View File

@ -76,9 +76,9 @@ const UserAction = RestModel.extend({
return targetUsername === Discourse.User.currentProp('username'); return targetUsername === Discourse.User.currentProp('username');
}, },
presentName: Em.computed.any('name', 'username'), presentName: Ember.computed.or('name', 'username'),
targetDisplayName: Em.computed.any('target_name', 'target_username'), targetDisplayName: Ember.computed.or('target_name', 'target_username'),
actingDisplayName: Em.computed.any('acting_name', 'acting_username'), actingDisplayName: Ember.computed.or('acting_name', 'acting_username'),
targetUserUrl: url('target_username', '/users/%@'), targetUserUrl: url('target_username', '/users/%@'),
@computed("username") @computed("username")

View File

@ -64,7 +64,7 @@ const User = RestModel.extend({
@computed('profile_background') @computed('profile_background')
profileBackground(bgUrl) { 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(); return ('background-image: url(' + Discourse.getURLWithCDN(bgUrl) + ')').htmlSafe();
}, },
@ -322,7 +322,7 @@ const User = RestModel.extend({
@computed("stats.@each.isPM") @computed("stats.@each.isPM")
statsExcludingPms() { statsExcludingPms() {
if (Ember.isEmpty(this.get('stats'))) return []; if (Ember.isEmpty(this.get('stats'))) return [];
return this.get('stats').rejectProperty('isPM'); return this.get('stats').rejectBy('isPM');
}, },
findDetails(options) { findDetails(options) {
@ -530,7 +530,7 @@ User.reopenClass(Singleton, {
}); });
const result = Em.A(); const result = Em.A();
result.pushObjects(stats.rejectProperty('isResponse')); result.pushObjects(stats.rejectBy('isResponse'));
let insertAt = 0; let insertAt = 0;
result.forEach((item, index) => { result.forEach((item, index) => {

View File

@ -0,0 +1 @@
{{#each colors as |c|}}{{color-picker-choice color=c usedColors=usedColors selectColor="selectColor"}}{{/each}}

View File

@ -1,5 +1,5 @@
{{#each model.categories as |c|}} {{#each model.categories as |c|}}
<div class='category-list-item category' style="border-color: #{{unbound c.color}}"> <div class='category-list-item category' style={{border-color c.color}}>
<table class='topic-list'> <table class='topic-list'>
<tr> <tr>
<th class="main-link"> <th class="main-link">

View File

@ -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);
}
});

View File

@ -7,10 +7,12 @@ export default Ember.View.extend({
_setupModal() { _setupModal() {
$('#modal-alert').hide(); $('#modal-alert').hide();
$('#discourse-modal').modal('show'); $('#discourse-modal').modal('show');
Ember.run.scheduleOnce('afterRender', this, this._afterFirstRender);
},
// Focus on first element _afterFirstRender() {
if (!this.site.mobileView && this.get('focusInput')) { if (!this.site.mobileView && this.get('focusInput')) {
Em.run.schedule('afterRender', () => this.$('input:first').focus()); this.$('input:first').focus();
} }
const title = this.get('title'); const title = this.get('title');

View File

@ -1,3 +1,4 @@
import ScrollTop from 'discourse/mixins/scroll-top'; import ScrollTop from 'discourse/mixins/scroll-top';
export default Ember.View.extend(ScrollTop); export default Ember.View.extend(ScrollTop, {
});

View File

@ -71,7 +71,7 @@ export default createWidget('search-menu', {
const contextEnabled = searchData.contextEnabled; const contextEnabled = searchData.contextEnabled;
const ctx = contextEnabled ? this.searchContext() : null; const ctx = contextEnabled ? this.searchContext() : null;
const type = Ember.get(ctx, 'type'); const type = ctx ? Ember.get(ctx, 'type') : null;
if (contextEnabled && type === 'topic') { if (contextEnabled && type === 'topic') {
return; return;

View File

@ -57,7 +57,6 @@
//= require ./discourse/models/user-badge //= require ./discourse/models/user-badge
//= require ./discourse/controllers/discovery-sortable //= require ./discourse/controllers/discovery-sortable
//= require ./discourse/controllers/navigation/default //= require ./discourse/controllers/navigation/default
//= require ./discourse/views/container
//= require ./discourse/views/modal-body //= require ./discourse/views/modal-body
//= require ./discourse/views/flag //= require ./discourse/views/flag
//= require ./discourse/components/edit-category-panel //= require ./discourse/components/edit-category-panel

View File

@ -4,7 +4,7 @@ export function componentTest(name, opts) {
opts = opts || {}; opts = opts || {};
test(name, function(assert) { test(name, function(assert) {
initializer.initialize(); initializer.initialize(this.container, this.registry);
if (opts.setup) { if (opts.setup) {
opts.setup.call(this); opts.setup.call(this);

View File

@ -8,7 +8,7 @@ export default function() {
Ember.run(() => app = Wizard.create({ rootElement: '#ember-testing' })); Ember.run(() => app = Wizard.create({ rootElement: '#ember-testing' }));
if (!started) { if (!started) {
initializer.initialize(); initializer.initialize(app.__container__, app.registry);
app.start(); app.start();
started = true; started = true;
} }

View File

@ -9,7 +9,7 @@ export default Ember.Application.extend({
if (/\/initializers\//.test(key)) { if (/\/initializers\//.test(key)) {
const module = require(key, null, null, true); const module = require(key, null, null, true);
if (!module) { throw new Error(key + ' must export an initializer.'); } if (!module) { throw new Error(key + ' must export an initializer.'); }
this.instanceInitializer(module.default); this.initializer(module.default);
} }
}); });
} }

View File

@ -21,7 +21,7 @@ export default function(name, opts) {
this.siteSettings = Discourse.SiteSettings; this.siteSettings = Discourse.SiteSettings;
autoLoadModules(); autoLoadModules(this.container, this.registry);
const store = createStore(); const store = createStore();
if (!opts.anonymous) { if (!opts.anonymous) {

View File

@ -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);
});