ui: Switch out WithResizingMixin for on-window helper (#8130)

* ui: Add ember-on-helper

* Switch out WithResizingMixin for {{on-window}} helper
This commit is contained in:
John Cowen 2020-06-17 14:26:50 +01:00 committed by GitHub
parent 49ec61e523
commit 2344ed1505
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 135 additions and 184 deletions

View File

@ -1,3 +1,4 @@
{{on-window 'resize' (action "resize") }}
<EmberNativeScrollable @tagName="ul" @content-size={{_contentSize}} @scroll-left={{_scrollLeft}} @scroll-top={{_scrollTop}} @scrollChange={{action "scrollChange"}} @clientSizeChange={{action "clientSizeChange"}}>
<li></li>
{{~#each _cells as |cell|~}}

View File

@ -3,9 +3,8 @@ import { computed, get, set } from '@ember/object';
import Component from 'ember-collection/components/ember-collection';
import PercentageColumns from 'ember-collection/layouts/percentage-columns';
import style from 'ember-computed-style';
import WithResizing from 'consul-ui/mixins/with-resizing';
export default Component.extend(WithResizing, {
export default Component.extend({
dom: service('dom'),
tagName: 'div',
attributeBindings: ['style'],
@ -17,6 +16,10 @@ export default Component.extend(WithResizing, {
this._super(...arguments);
this.columns = [25, 25, 25, 25];
},
didInsertElement: function() {
this._super(...arguments);
this.actions.resize.apply(this, [{ target: this.dom.viewport() }]);
},
didReceiveAttrs: function() {
this._super(...arguments);
this._cellLayout = this['cell-layout'] = new PercentageColumns(
@ -30,49 +33,51 @@ export default Component.extend(WithResizing, {
height: get(this, 'height'),
};
}),
resize: function(e) {
// TODO: This top part is very similar to resize in tabular-collection
// see if it make sense to DRY out
const dom = get(this, 'dom');
const $appContent = dom.element('main > div');
if ($appContent) {
const rect = this.element.getBoundingClientRect();
const $footer = dom.element('footer[role="contentinfo"]');
const space = rect.top + $footer.clientHeight;
const height = e.detail.height - space;
this.set('height', Math.max(0, height));
this.updateItems();
this.updateScrollPosition();
}
const width = e.detail.width;
const len = get(this, 'columns.length');
switch (true) {
case width > 1013:
if (len != 4) {
set(this, 'columns', [25, 25, 25, 25]);
}
break;
case width > 744:
if (len != 3) {
set(this, 'columns', [33, 33, 34]);
}
break;
case width > 487:
if (len != 2) {
set(this, 'columns', [50, 50]);
}
break;
case width < 488:
if (len != 1) {
set(this, 'columns', [100]);
}
}
if (len !== get(this, 'columns.length')) {
this._cellLayout = this['cell-layout'] = new PercentageColumns(
get(this, 'items.length'),
get(this, 'columns'),
get(this, 'cellHeight')
);
}
actions: {
resize: function(e) {
// TODO: This top part is very similar to resize in tabular-collection
// see if it make sense to DRY out
const dom = get(this, 'dom');
const $appContent = dom.element('main > div');
if ($appContent) {
const rect = this.element.getBoundingClientRect();
const $footer = dom.element('footer[role="contentinfo"]');
const space = rect.top + $footer.clientHeight;
const height = e.target.innerHeight - space;
this.set('height', Math.max(0, height));
this.updateItems();
this.updateScrollPosition();
}
const width = e.target.innerWidth;
const len = get(this, 'columns.length');
switch (true) {
case width > 1013:
if (len != 4) {
set(this, 'columns', [25, 25, 25, 25]);
}
break;
case width > 744:
if (len != 3) {
set(this, 'columns', [33, 33, 34]);
}
break;
case width > 487:
if (len != 2) {
set(this, 'columns', [50, 50]);
}
break;
case width < 488:
if (len != 1) {
set(this, 'columns', [100]);
}
}
if (len !== get(this, 'columns.length')) {
this._cellLayout = this['cell-layout'] = new PercentageColumns(
get(this, 'items.length'),
get(this, 'columns'),
get(this, 'cellHeight')
);
}
},
},
});

View File

@ -1,3 +1,4 @@
{{on-window 'resize' (action "resize") }}
{{yield}}
<EmberNativeScrollable
@tagName="ul"

View File

@ -4,10 +4,10 @@ import Component from 'ember-collection/components/ember-collection';
import PercentageColumns from 'ember-collection/layouts/percentage-columns';
import style from 'ember-computed-style';
import Slotted from 'block-slots';
import WithResizing from 'consul-ui/mixins/with-resizing';
const formatItemStyle = PercentageColumns.prototype.formatItemStyle;
export default Component.extend(Slotted, WithResizing, {
export default Component.extend(Slotted, {
dom: service('dom'),
tagName: 'div',
attributeBindings: ['style'],
@ -20,6 +20,10 @@ export default Component.extend(Slotted, WithResizing, {
this._super(...arguments);
this.columns = [100];
},
didInsertElement: function() {
this._super(...arguments);
this.actions.resize.apply(this, [{ target: this.dom.viewport() }]);
},
didReceiveAttrs: function() {
this._super(...arguments);
this._cellLayout = this['cell-layout'] = new PercentageColumns(
@ -41,23 +45,23 @@ export default Component.extend(Slotted, WithResizing, {
height: get(this, 'height'),
};
}),
resize: function(e) {
// TODO: This top part is very similar to resize in tabular-collection
// see if it make sense to DRY out
const dom = get(this, 'dom');
const $appContent = dom.element('main > div');
if ($appContent) {
const border = 1;
const rect = this.element.getBoundingClientRect();
const $footer = dom.element('footer[role="contentinfo"]');
const space = rect.top + $footer.clientHeight + border;
const height = e.detail.height - space;
this.set('height', Math.max(0, height));
this.updateItems();
this.updateScrollPosition();
}
},
actions: {
resize: function(e) {
// TODO: This top part is very similar to resize in tabular-collection
// see if it make sense to DRY out
const dom = get(this, 'dom');
const $appContent = dom.element('main > div');
if ($appContent) {
const border = 1;
const rect = this.element.getBoundingClientRect();
const $footer = dom.element('footer[role="contentinfo"]');
const space = rect.top + $footer.clientHeight + border;
const height = e.target.innerHeight - space;
this.set('height', Math.max(0, height));
this.updateItems();
this.updateScrollPosition();
}
},
click: function(e) {
return this.dom.clickFirstAnchor(e, '.list-collection > ul > li');
},

View File

@ -1,3 +1,4 @@
{{on-window 'resize' (action "resize") }}
{{yield}}
<input id={{name}} type="radio" name="modal" data-checked="{{checked}}" checked={{checked}} onchange={{action 'change'}} />
<div role="dialog" aria-modal="true">

View File

@ -1,11 +1,10 @@
import { get, set } from '@ember/object';
import { inject as service } from '@ember/service';
import DomBufferComponent from 'consul-ui/components/dom-buffer';
import SlotsMixin from 'block-slots';
import WithResizing from 'consul-ui/mixins/with-resizing';
import Slotted from 'block-slots';
import templatize from 'consul-ui/utils/templatize';
export default DomBufferComponent.extend(SlotsMixin, WithResizing, {
export default DomBufferComponent.extend(Slotted, {
dom: service('dom'),
checked: true,
height: null,
@ -69,6 +68,7 @@ export default DomBufferComponent.extend(SlotsMixin, WithResizing, {
},
didInsertElement: function() {
this._super(...arguments);
this.actions.resize.apply(this, [{ target: this.dom.viewport() }]);
if (this.checked) {
// TODO: probably need an event here
// possibly this.element for the target
@ -80,26 +80,26 @@ export default DomBufferComponent.extend(SlotsMixin, WithResizing, {
this._super(...arguments);
this.dom.root().classList.remove(...templatize(['with-modal']));
},
resize: function(e) {
if (this.checked) {
const height = this.height;
if (height !== null) {
const dialogPanel = this.dialog;
const overflowing = this.overflowingClass;
if (height > e.detail.height) {
if (!dialogPanel.classList.contains(overflowing)) {
dialogPanel.classList.add(overflowing);
}
return;
} else {
if (dialogPanel.classList.contains(overflowing)) {
dialogPanel.classList.remove(overflowing);
actions: {
resize: function(e) {
if (this.checked) {
const height = this.height;
if (height !== null) {
const dialogPanel = this.dialog;
const overflowing = this.overflowingClass;
if (height > e.target.innerHeight) {
if (!dialogPanel.classList.contains(overflowing)) {
dialogPanel.classList.add(overflowing);
}
return;
} else {
if (dialogPanel.classList.contains(overflowing)) {
dialogPanel.classList.remove(overflowing);
}
}
}
}
}
},
actions: {
},
change: function(e) {
if (get(e, 'target.checked')) {
this._open(e);

View File

@ -1,3 +1,4 @@
{{on-window 'resize' (action "resize") }}
{{yield}}
{{#if hasCaption}}
<caption><YieldSlot @name="caption">{{yield}}</YieldSlot></caption>

View File

@ -4,12 +4,11 @@ import CollectionComponent from 'ember-collection/components/ember-collection';
import needsRevalidate from 'ember-collection/utils/needs-revalidate';
import Grid from 'ember-collection/layouts/grid';
import style from 'ember-computed-style';
import SlotsMixin from 'block-slots';
import WithResizing from 'consul-ui/mixins/with-resizing';
import Slotted from 'block-slots';
const formatItemStyle = Grid.prototype.formatItemStyle;
export default CollectionComponent.extend(SlotsMixin, WithResizing, {
export default CollectionComponent.extend(Slotted, {
tagName: 'table',
classNames: ['dom-recycling'],
classNameBindings: ['hasActions'],
@ -34,6 +33,10 @@ export default CollectionComponent.extend(SlotsMixin, WithResizing, {
return style;
};
},
didInsertElement: function() {
this._super(...arguments);
this.actions.resize.apply(this, [{ target: this.dom.viewport() }]);
},
getStyle: computed('rowHeight', '_items', 'maxRows', 'maxHeight', function() {
const maxRows = get(this, 'rows');
let height = get(this, 'maxHeight');
@ -46,30 +49,6 @@ export default CollectionComponent.extend(SlotsMixin, WithResizing, {
height: height,
};
}),
resize: function(e) {
const $tbody = this.element;
const $appContent = this.dom.element('main > div');
if ($appContent) {
const border = 1;
const rect = $tbody.getBoundingClientRect();
const $footer = this.dom.element('footer[role="contentinfo"]');
const space = rect.top + $footer.clientHeight + border;
const height = e.detail.height - space;
this.set('maxHeight', Math.max(0, height));
// TODO: The row height should auto calculate properly from the CSS
this['cell-layout'] = new Grid($appContent.clientWidth, get(this, 'rowHeight'));
const o = this;
this['cell-layout'].formatItemStyle = function(itemIndex) {
let style = formatItemStyle.apply(this, arguments);
if (o.checked === itemIndex) {
style = `${style};z-index: 1`;
}
return style;
};
this.updateItems();
this.updateScrollPosition();
}
},
willRender: function() {
this._super(...arguments);
set(this, 'hasCaption', this._isRegistered('caption'));
@ -88,6 +67,30 @@ export default CollectionComponent.extend(SlotsMixin, WithResizing, {
}
},
actions: {
resize: function(e) {
const $tbody = this.element;
const $appContent = this.dom.element('main > div');
if ($appContent) {
const border = 1;
const rect = $tbody.getBoundingClientRect();
const $footer = this.dom.element('footer[role="contentinfo"]');
const space = rect.top + $footer.clientHeight + border;
const height = e.target.innerHeight - space;
this.set('maxHeight', Math.max(0, height));
// TODO: The row height should auto calculate properly from the CSS
this['cell-layout'] = new Grid($appContent.clientWidth, get(this, 'rowHeight'));
const o = this;
this['cell-layout'].formatItemStyle = function(itemIndex) {
let style = formatItemStyle.apply(this, arguments);
if (o.checked === itemIndex) {
style = `${style};z-index: 1`;
}
return style;
};
this.updateItems();
this.updateScrollPosition();
}
},
click: function(e) {
return this.dom.clickFirstAnchor(e);
},

View File

@ -1,30 +0,0 @@
import Mixin from '@ember/object/mixin';
import { inject as service } from '@ember/service';
import { assert } from '@ember/debug';
export default Mixin.create({
dom: service('dom'),
resize: function(e) {
assert('with-resizing.resize needs to be overridden', false);
},
init: function() {
this._super(...arguments);
this.handler = e => {
const win = e.target;
this.resize({
detail: { width: win.innerWidth, height: win.innerHeight },
});
};
},
didInsertElement: function() {
this._super(...arguments);
this.dom.viewport().addEventListener('resize', this.handler, false);
this.didAppear();
},
didAppear: function() {
this.handler({ target: this.dom.viewport() });
},
willDestroyElement: function() {
this.dom.viewport().removeEventListener('resize', this.handler, false);
this._super(...arguments);
},
});

View File

@ -98,6 +98,7 @@
"ember-load-initializers": "^2.1.1",
"ember-math-helpers": "^2.4.0",
"ember-maybe-import-regenerator": "^0.1.6",
"ember-on-helper": "^0.1.0",
"ember-page-title": "^5.1.0",
"ember-power-select": "^3.0.6",
"ember-power-select-with-create": "^0.7.0",

View File

@ -1,31 +0,0 @@
import { module } from 'qunit';
import test from 'ember-sinon-qunit/test-support/test';
import { setupTest } from 'ember-qunit';
import EmberObject from '@ember/object';
import Mixin from 'consul-ui/mixins/with-resizing';
module('Integration | Mixin | with-resizing', function(hooks) {
setupTest(hooks);
test('window.addEventListener, resize and window.removeEventListener are called once each through the entire lifecycle', function(assert) {
const win = {
innerWidth: 0,
innerHeight: 0,
addEventListener: this.stub(),
removeEventListener: this.stub(),
};
const dom = {
viewport: function() {
return win;
},
};
const subject = EmberObject.extend(Mixin, {
dom: dom,
}).create();
const resize = this.stub(subject, 'resize');
subject.didInsertElement();
subject.willDestroyElement();
assert.ok(win.addEventListener.calledOnce);
assert.ok(resize.calledOnce);
assert.ok(resize.calledWith({ detail: { width: 0, height: 0 } }));
assert.ok(win.removeEventListener.calledOnce);
});
});

View File

@ -1,12 +0,0 @@
import EmberObject from '@ember/object';
import WithResizingMixin from 'consul-ui/mixins/with-resizing';
import { module, test } from 'qunit';
module('Unit | Mixin | with resizing', function() {
// Replace this with your real tests.
test('it works', function(assert) {
let WithResizingObject = EmberObject.extend(WithResizingMixin);
let subject = WithResizingObject.create();
assert.ok(subject);
});
});

View File

@ -5789,6 +5789,13 @@ ember-native-dom-helpers@^0.6.3:
broccoli-funnel "^1.1.0"
ember-cli-babel "^6.6.0"
ember-on-helper@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/ember-on-helper/-/ember-on-helper-0.1.0.tgz#c8b1fef9173fc8546c4933b57ecd7ffbcebad99e"
integrity sha512-jjafBnWfoA4VSSje476ft5G+urlvvuSDddwAJjKDCjKY9mbe3hAEsJiMBAaPObJRMm1FOglCuKjQZfwDDls6MQ==
dependencies:
ember-cli-babel "^7.7.3"
ember-page-title@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/ember-page-title/-/ember-page-title-5.1.0.tgz#baf9fc00f95faf638f8493740a1f80daaa5007e9"