neo.mjs 3.0.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/examples/list/animate/List.mjs +8 -6
- package/examples/list/animate/MainContainer.mjs +34 -9
- package/package.json +1 -1
- package/resources/scss/src/examples/list/animate/List.scss +1 -1
- package/src/collection/Base.mjs +21 -4
- package/src/core/Observable.mjs +4 -0
- package/src/list/Base.mjs +3 -3
- package/src/list/plugin/Animate.mjs +102 -23
|
@@ -32,13 +32,15 @@ class List extends BaseList {
|
|
|
32
32
|
* @returns {Object|Object[]|String} Either a config object to assign to the item, a vdom cn array or a html string
|
|
33
33
|
*/
|
|
34
34
|
createItemContent(record, index) {
|
|
35
|
+
let id = this.getItemId(record.id);
|
|
36
|
+
|
|
35
37
|
return [
|
|
36
|
-
{cls: ['neo-list-item-content'], cn: [
|
|
37
|
-
{tag: 'img', src: `../../../resources/examples/${record.image}`},
|
|
38
|
-
{cls: ['neo-list-item-text'], cn: [
|
|
39
|
-
{html: record.firstname},
|
|
40
|
-
{cls: ['neo-lastname'], html: record.lastname},
|
|
41
|
-
{cls: ['neo-is-online'], removeDom: !record.isOnline}
|
|
38
|
+
{cls: ['neo-list-item-content'], id: `${id}__content`, cn: [
|
|
39
|
+
{tag: 'img', id: `${id}__image`, src: `../../../resources/examples/${record.image}`},
|
|
40
|
+
{cls: ['neo-list-item-text'], id: `${id}__content_wrapper`, cn: [
|
|
41
|
+
{html: record.firstname, id: `${id}__firstname`},
|
|
42
|
+
{cls: ['neo-lastname'], id: `${id}__lastname`, html: record.lastname},
|
|
43
|
+
{cls: ['neo-is-online'], id: `${id}__isonline`, removeDom: !record.isOnline}
|
|
42
44
|
]}
|
|
43
45
|
]}
|
|
44
46
|
];
|
|
@@ -12,7 +12,8 @@ class MainContainer extends Viewport {
|
|
|
12
12
|
static getConfig() {return {
|
|
13
13
|
className: 'Neo.examples.list.animate.MainContainer',
|
|
14
14
|
autoMount: true,
|
|
15
|
-
layout : {ntype: 'vbox', align: 'stretch'}
|
|
15
|
+
layout : {ntype: 'vbox', align: 'stretch'},
|
|
16
|
+
sortBy : 'firstname'
|
|
16
17
|
}}
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -36,11 +37,16 @@ class MainContainer extends Viewport {
|
|
|
36
37
|
ntype: 'label',
|
|
37
38
|
text : 'Sort by'
|
|
38
39
|
}, {
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
field : 'firstname',
|
|
41
|
+
handler : me.changeSorting.bind(me, 'firstname'),
|
|
42
|
+
iconCls : 'fas fa-arrow-circle-up',
|
|
43
|
+
iconPosition: 'right',
|
|
44
|
+
text : 'Firstname'
|
|
41
45
|
}, {
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
field : 'lastname',
|
|
47
|
+
handler : me.changeSorting.bind(me, 'lastname'),
|
|
48
|
+
iconPosition: 'right',
|
|
49
|
+
text : 'Lastname'
|
|
44
50
|
}, {
|
|
45
51
|
module : CheckBox,
|
|
46
52
|
labelText : 'Is online',
|
|
@@ -64,13 +70,32 @@ class MainContainer extends Viewport {
|
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
/**
|
|
67
|
-
* @param {String}
|
|
73
|
+
* @param {String} property
|
|
68
74
|
* @param {Object} data
|
|
69
75
|
*/
|
|
70
|
-
changeSorting(
|
|
71
|
-
let
|
|
76
|
+
changeSorting(property, data) {
|
|
77
|
+
let me = this,
|
|
78
|
+
buttonFirstName = me.down({field: 'firstname'}),
|
|
79
|
+
buttonLastName = me.down({field: 'lastname'}),
|
|
80
|
+
direction = 'ASC',
|
|
81
|
+
store = me.down({module: List}).store,
|
|
82
|
+
sorter = store.sorters[0],
|
|
83
|
+
button;
|
|
84
|
+
|
|
85
|
+
button = property === 'firstname' ? buttonFirstName : buttonLastName;
|
|
86
|
+
|
|
87
|
+
if (property === me.sortBy) {
|
|
88
|
+
direction = sorter.direction === 'ASC' ? 'DESC' : 'ASC';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
button.iconCls = `fas fa-arrow-circle-${direction === 'ASC' ? 'up' : 'down'}`;
|
|
92
|
+
|
|
93
|
+
button = button === buttonFirstName ? buttonLastName : buttonFirstName;
|
|
94
|
+
button.iconCls = null;
|
|
95
|
+
|
|
96
|
+
sorter.set({direction, property});
|
|
72
97
|
|
|
73
|
-
|
|
98
|
+
me.sortBy = property;
|
|
74
99
|
}
|
|
75
100
|
}
|
|
76
101
|
|
package/package.json
CHANGED
package/src/collection/Base.mjs
CHANGED
|
@@ -469,11 +469,13 @@ class Base extends CoreBase {
|
|
|
469
469
|
}
|
|
470
470
|
|
|
471
471
|
/**
|
|
472
|
+
*
|
|
473
|
+
* @param {Object[]} items=this._items
|
|
474
|
+
* @param {Boolean} silent=false
|
|
472
475
|
* @protected
|
|
473
476
|
*/
|
|
474
|
-
doSort() {
|
|
477
|
+
doSort(items=this._items, silent=false) {
|
|
475
478
|
let me = this,
|
|
476
|
-
items = me._items,
|
|
477
479
|
previousItems = [...items],
|
|
478
480
|
sorters = me.sorters,
|
|
479
481
|
sortDirections = me.sortDirections,
|
|
@@ -558,7 +560,7 @@ class Base extends CoreBase {
|
|
|
558
560
|
|
|
559
561
|
me[isSorted] = countSorters > 0;
|
|
560
562
|
|
|
561
|
-
if (me[updatingIndex] === 0) {
|
|
563
|
+
if (!silent && me[updatingIndex] === 0) {
|
|
562
564
|
me.fire('sort', {
|
|
563
565
|
items: me._items,
|
|
564
566
|
previousItems,
|
|
@@ -607,6 +609,8 @@ class Base extends CoreBase {
|
|
|
607
609
|
i = 0,
|
|
608
610
|
countItems = items.length,
|
|
609
611
|
filteredItems = [],
|
|
612
|
+
needsSorting = false,
|
|
613
|
+
oldItems = [...me._items],
|
|
610
614
|
config, isIncluded, item, j, tmpItems;
|
|
611
615
|
|
|
612
616
|
for (; i < countAllFilters; i++) {
|
|
@@ -616,6 +620,10 @@ class Base extends CoreBase {
|
|
|
616
620
|
}
|
|
617
621
|
|
|
618
622
|
if (countFilters === 0 && me.allItems) {
|
|
623
|
+
if (me.sorters.length > 0) {
|
|
624
|
+
needsSorting = true;
|
|
625
|
+
}
|
|
626
|
+
|
|
619
627
|
me.clear();
|
|
620
628
|
|
|
621
629
|
me.items = [...me.allItems._items];
|
|
@@ -682,7 +690,16 @@ class Base extends CoreBase {
|
|
|
682
690
|
|
|
683
691
|
me[isFiltered] = countFilters !== 0;
|
|
684
692
|
|
|
685
|
-
|
|
693
|
+
if (needsSorting) {
|
|
694
|
+
me.doSort(me.items, true);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
me.fire('filter', {
|
|
698
|
+
isFiltered: me[isFiltered],
|
|
699
|
+
items : me.items,
|
|
700
|
+
oldItems,
|
|
701
|
+
scope : me
|
|
702
|
+
});
|
|
686
703
|
}
|
|
687
704
|
|
|
688
705
|
/**
|
package/src/core/Observable.mjs
CHANGED
|
@@ -107,6 +107,10 @@ class Observable extends Base {
|
|
|
107
107
|
for (i = 0; i < len; i++) {
|
|
108
108
|
eventConfig = events[i];
|
|
109
109
|
|
|
110
|
+
if (!Neo.isFunction(eventConfig.fn)) {
|
|
111
|
+
eventConfig.fn = eventConfig.scope[eventConfig.fn];
|
|
112
|
+
}
|
|
113
|
+
|
|
110
114
|
eventConfig.fn.apply(eventConfig.scope || me, eventConfig.data ? args.concat(eventConfig.data) : args);
|
|
111
115
|
}
|
|
112
116
|
}
|
package/src/list/Base.mjs
CHANGED
|
@@ -191,9 +191,9 @@ class Base extends Component {
|
|
|
191
191
|
let me = this;
|
|
192
192
|
|
|
193
193
|
value?.on({
|
|
194
|
-
filter :
|
|
195
|
-
load :
|
|
196
|
-
recordChange:
|
|
194
|
+
filter : 'onStoreFilter',
|
|
195
|
+
load : 'onStoreLoad',
|
|
196
|
+
recordChange: 'onStoreRecordChange',
|
|
197
197
|
scope : me
|
|
198
198
|
});
|
|
199
199
|
|
|
@@ -39,7 +39,12 @@ class Animate extends Base {
|
|
|
39
39
|
* Read only
|
|
40
40
|
* @member {Number|null} rows=null
|
|
41
41
|
*/
|
|
42
|
-
rows: null
|
|
42
|
+
rows: null,
|
|
43
|
+
/**
|
|
44
|
+
* Time in ms. Please ensure to match the CSS based value, in case you change the default.
|
|
45
|
+
* @member {Number} transitionDuration=500
|
|
46
|
+
*/
|
|
47
|
+
transitionDuration: 500
|
|
43
48
|
}}
|
|
44
49
|
|
|
45
50
|
/**
|
|
@@ -48,14 +53,16 @@ class Animate extends Base {
|
|
|
48
53
|
construct(config) {
|
|
49
54
|
super.construct(config);
|
|
50
55
|
|
|
51
|
-
let me
|
|
56
|
+
let me = this,
|
|
57
|
+
owner = me.owner;
|
|
52
58
|
|
|
53
59
|
me.adjustCreateItem();
|
|
54
60
|
|
|
55
|
-
me.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
owner.onStoreFilter = me.onStoreFilter.bind(me);
|
|
62
|
+
|
|
63
|
+
owner.store.on({
|
|
64
|
+
sort : me.onSort,
|
|
65
|
+
scope: me
|
|
59
66
|
});
|
|
60
67
|
}
|
|
61
68
|
|
|
@@ -77,27 +84,19 @@ class Animate extends Base {
|
|
|
77
84
|
* @returns {Object}
|
|
78
85
|
*/
|
|
79
86
|
createItem(me, record, index) {
|
|
80
|
-
let item
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
margin = me.itemMargin,
|
|
84
|
-
style = item.style || {},
|
|
85
|
-
column, row, x, y;
|
|
87
|
+
let item = me.ownerCreateItem(record, index),
|
|
88
|
+
position = me.getItemPosition(record, index),
|
|
89
|
+
style = item.style || {};
|
|
86
90
|
|
|
87
91
|
if (!me.ownerRect) {
|
|
88
92
|
return null;
|
|
89
93
|
}
|
|
90
94
|
|
|
91
|
-
column = index % me.columns;
|
|
92
|
-
row = Math.floor(index / me.columns);
|
|
93
|
-
x = column * (margin + itemWidth) + margin;
|
|
94
|
-
y = row * (margin + itemHeight) + margin;
|
|
95
|
-
|
|
96
95
|
Object.assign(style, {
|
|
97
|
-
height : `${itemHeight}px`,
|
|
96
|
+
height : `${me.itemHeight}px`,
|
|
98
97
|
position : 'absolute',
|
|
99
|
-
transform: `translate(${x}px, ${y}px)`,
|
|
100
|
-
width : `${itemWidth}px`
|
|
98
|
+
transform: `translate(${position.x}px, ${position.y}px)`,
|
|
99
|
+
width : `${me.itemWidth}px`
|
|
101
100
|
});
|
|
102
101
|
|
|
103
102
|
item.style = style;
|
|
@@ -106,10 +105,20 @@ class Animate extends Base {
|
|
|
106
105
|
}
|
|
107
106
|
|
|
108
107
|
/**
|
|
109
|
-
*
|
|
108
|
+
*
|
|
109
|
+
* @param {Object} record
|
|
110
|
+
* @param {Number} index
|
|
111
|
+
* @returns {{x: Number, y: Number}}
|
|
110
112
|
*/
|
|
111
|
-
|
|
112
|
-
|
|
113
|
+
getItemPosition(record, index) {
|
|
114
|
+
let me = this,
|
|
115
|
+
column = index % me.columns,
|
|
116
|
+
margin = me.itemMargin,
|
|
117
|
+
row = Math.floor(index / me.columns),
|
|
118
|
+
x = column * (margin + me.itemWidth) + margin,
|
|
119
|
+
y = row * (margin + me.itemHeight) + margin;
|
|
120
|
+
|
|
121
|
+
return {x, y};
|
|
113
122
|
}
|
|
114
123
|
|
|
115
124
|
/**
|
|
@@ -167,6 +176,76 @@ class Animate extends Base {
|
|
|
167
176
|
}
|
|
168
177
|
}
|
|
169
178
|
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* @param {Object} data
|
|
182
|
+
* @param {Boolean} data.isFiltered
|
|
183
|
+
* @param {Object[]} data.items
|
|
184
|
+
* @param {Object[]} data.oldItems
|
|
185
|
+
* @param {Neo.data.Store} data.scope
|
|
186
|
+
*/
|
|
187
|
+
onStoreFilter(data) {
|
|
188
|
+
let me = this,
|
|
189
|
+
owner = me.owner,
|
|
190
|
+
addedItems = [],
|
|
191
|
+
movedItems = [],
|
|
192
|
+
removedItems = [],
|
|
193
|
+
vdom = owner.vdom,
|
|
194
|
+
index, map, position;
|
|
195
|
+
|
|
196
|
+
data.items.forEach((record, index) => {
|
|
197
|
+
if (!data.oldItems.includes(record)) {
|
|
198
|
+
addedItems.push({index, record});
|
|
199
|
+
} else {
|
|
200
|
+
movedItems.push({index, record});
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
data.oldItems.forEach((record, index) => {
|
|
205
|
+
if (!data.items.includes(record)) {
|
|
206
|
+
removedItems.push({index, record});
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
addedItems.forEach(obj => {
|
|
211
|
+
vdom.cn.splice(obj.index, 0, me.createItem(me, obj.record, obj.index));
|
|
212
|
+
|
|
213
|
+
obj.item = vdom.cn[obj.index];
|
|
214
|
+
obj.item.style.opacity = 0;
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
owner.vdom = vdom;
|
|
218
|
+
|
|
219
|
+
// ensure to get into the next animation frame
|
|
220
|
+
setTimeout(() => {
|
|
221
|
+
vdom = owner.vdom;
|
|
222
|
+
|
|
223
|
+
addedItems.forEach(obj => {
|
|
224
|
+
vdom.cn[obj.index].style.opacity = 1;
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
// new items are already added into the vdom, while old items are not yet removed
|
|
228
|
+
// => we need a map to ensure getting the correct index
|
|
229
|
+
map = vdom.cn.map(e => e.id);
|
|
230
|
+
|
|
231
|
+
movedItems.forEach(obj => {
|
|
232
|
+
index = map.indexOf(owner.getItemId(obj.record[owner.store.keyProperty]));
|
|
233
|
+
position = me.getItemPosition(obj.record, obj.index);
|
|
234
|
+
vdom.cn[index].style.transform = `translate(${position.x}px, ${position.y}px)`;
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
removedItems.forEach(obj => {
|
|
238
|
+
obj.item = vdom.cn[obj.index];
|
|
239
|
+
obj.item.style.opacity = 0;
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
owner.vdom = vdom;
|
|
243
|
+
|
|
244
|
+
setTimeout(() => {
|
|
245
|
+
owner.createItems();
|
|
246
|
+
}, me.transitionDuration);
|
|
247
|
+
}, 50);
|
|
248
|
+
}
|
|
170
249
|
}
|
|
171
250
|
|
|
172
251
|
Neo.applyClassConfig(Animate);
|