neo.mjs 6.8.2 → 6.9.0

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.
Files changed (66) hide show
  1. package/.github/PULL_REQUEST_TEMPLATE.md +1 -1
  2. package/apps/ServiceWorker.mjs +2 -2
  3. package/apps/learnneo/app.mjs +6 -0
  4. package/apps/learnneo/index.html +11 -0
  5. package/apps/learnneo/model/Content.mjs +44 -0
  6. package/apps/learnneo/neo-config.json +6 -0
  7. package/apps/learnneo/store/Content.mjs +24 -0
  8. package/apps/learnneo/view/Viewport.mjs +34 -0
  9. package/apps/learnneo/view/ViewportController.mjs +19 -0
  10. package/apps/learnneo/view/home/ContentTreeList.mjs +41 -0
  11. package/apps/learnneo/view/home/MainContainer.mjs +51 -0
  12. package/apps/learnneo/view/home/MainContainerController.mjs +50 -0
  13. package/apps/route/app.mjs +6 -0
  14. package/apps/route/index.html +11 -0
  15. package/apps/route/neo-config.json +6 -0
  16. package/apps/route/view/ButtonBar.mjs +57 -0
  17. package/apps/route/view/CenterContainer.mjs +37 -0
  18. package/apps/route/view/FooterContainer.mjs +47 -0
  19. package/apps/route/view/HeaderContainer.mjs +47 -0
  20. package/apps/route/view/MainView.mjs +66 -0
  21. package/apps/route/view/MainViewController.mjs +210 -0
  22. package/apps/route/view/MetaContainer.mjs +52 -0
  23. package/apps/route/view/Viewport.mjs +15 -0
  24. package/apps/route/view/center/CardAdministration.mjs +36 -0
  25. package/apps/route/view/center/CardAdministrationDenied.mjs +26 -0
  26. package/apps/route/view/center/CardContact.mjs +29 -0
  27. package/apps/route/view/center/CardHome.mjs +26 -0
  28. package/apps/route/view/center/CardSection1.mjs +26 -0
  29. package/apps/route/view/center/CardSection2.mjs +27 -0
  30. package/examples/ConfigurationViewport.mjs +1 -1
  31. package/examples/ServiceWorker.mjs +2 -2
  32. package/examples/form/field/select/MainContainer.mjs +7 -2
  33. package/examples/table/container/MainContainer.mjs +4 -2
  34. package/examples/table/container/MainModel.mjs +3 -0
  35. package/examples/table/container/MainStore.mjs +10 -10
  36. package/examples/todoList/version1/MainComponent.mjs +5 -5
  37. package/examples/toolbar/paging/view/MainContainer.mjs +31 -3
  38. package/package.json +1 -1
  39. package/resources/data/learnneo/content.json +27 -0
  40. package/resources/data/learnneo/pages/whyneo.md +76 -0
  41. package/resources/scss/src/apps/route/CenterContainer.scss +29 -0
  42. package/resources/scss/src/apps/route/HeaderContainer.scss +122 -0
  43. package/resources/scss/src/apps/route/MainView.scss +3 -0
  44. package/resources/scss/src/apps/route/MetaContainer.scss +44 -0
  45. package/resources/scss/src/apps/route/_all.scss +1 -0
  46. package/resources/scss/src/form/field/Picker.scss +0 -1
  47. package/src/DefaultConfig.mjs +2 -2
  48. package/src/Neo.mjs +15 -14
  49. package/src/button/Base.mjs +2 -2
  50. package/src/component/Base.mjs +41 -50
  51. package/src/container/Base.mjs +59 -2
  52. package/src/controller/Base.mjs +84 -4
  53. package/src/controller/Component.mjs +22 -7
  54. package/src/core/Observable.mjs +50 -9
  55. package/src/dialog/Base.mjs +1 -4
  56. package/src/form/field/FileUpload.mjs +11 -0
  57. package/src/form/field/Picker.mjs +0 -17
  58. package/src/form/field/Range.mjs +8 -0
  59. package/src/form/field/Text.mjs +29 -0
  60. package/src/form/field/trigger/Picker.mjs +7 -0
  61. package/src/main/DomEvents.mjs +9 -3
  62. package/src/manager/DomEvent.mjs +3 -0
  63. package/src/menu/List.mjs +1 -1
  64. package/src/table/View.mjs +78 -53
  65. package/src/toolbar/Paging.mjs +68 -76
  66. package/src/tooltip/Base.mjs +111 -11
@@ -21,6 +21,11 @@ class View extends Component {
21
21
  * @member {String[]} baseCls=['neo-table-view']
22
22
  */
23
23
  baseCls: ['neo-table-view'],
24
+ /**
25
+ * Define which model field contains the value of colspan definitions
26
+ * @member {String} colspanField='colspan'
27
+ */
28
+ colspanField: 'colspan',
24
29
  /**
25
30
  * @member {String|null} containerId=null
26
31
  * @protected
@@ -46,16 +51,19 @@ class View extends Component {
46
51
  }
47
52
 
48
53
  /**
49
- * @param {String} cellId
50
- * @param {Object} column
51
- * @param {Object} record
52
- * @param {Number} index
53
- * @param {Neo.table.Container} tableContainer
54
+ * @param {Object} data
55
+ * @param {String} [data.cellId]
56
+ * @param {Object} data.column
57
+ * @param {Object} data.record
58
+ * @param {Number} data.index
59
+ * @param {Neo.table.Container} data.tableContainer
54
60
  * @returns {Object}
55
61
  */
56
- applyRendererOutput(cellId, column, record, index, tableContainer) {
57
- let me = this,
62
+ applyRendererOutput(data) {
63
+ let {cellId, column, record, index, tableContainer} = data,
64
+ me = this,
58
65
  cellCls = ['neo-table-cell'],
66
+ colspan = record[me.colspanField],
59
67
  dataField = column.dataField,
60
68
  fieldValue = record[dataField],
61
69
  hasStore = tableContainer.store?.model, // todo: remove as soon as all tables use stores (examples table)
@@ -77,8 +85,8 @@ class View extends Component {
77
85
 
78
86
  switch (Neo.typeOf(rendererOutput)) {
79
87
  case 'Object': {
80
- if (rendererOutput.cls && rendererOutput.html) {
81
- cellCls.push(...rendererOutput.cls);
88
+ if (rendererOutput.html) {
89
+ rendererOutput.cls && cellCls.push(...rendererOutput.cls);
82
90
  } else {
83
91
  rendererOutput = [rendererOutput];
84
92
  }
@@ -107,7 +115,7 @@ class View extends Component {
107
115
  if (hasStore) {
108
116
  cellId = me.getCellId(record, column.dataField)
109
117
  } else {
110
- cellId = vdom.cn[i]?.cn[j]?.id || Neo.getId('td')
118
+ cellId = vdom.cn[index]?.cn[me.getColumn(column.dataField, true)]?.id || Neo.getId('td')
111
119
  }
112
120
  }
113
121
 
@@ -119,6 +127,10 @@ class View extends Component {
119
127
  tabIndex: '-1'
120
128
  };
121
129
 
130
+ if (colspan && Object.keys(colspan).includes(dataField)) {
131
+ cellConfig.colspan = colspan[dataField]
132
+ }
133
+
122
134
  if (Neo.typeOf(rendererOutput) === 'Object') {
123
135
  cellConfig.innerHTML = rendererOutput.html || ''
124
136
  } else {
@@ -129,29 +141,28 @@ class View extends Component {
129
141
  }
130
142
 
131
143
  /**
132
- * @param {Array} inputData
144
+ * @param {Object[]} inputData
133
145
  */
134
146
  createViewData(inputData) {
135
- let me = this,
136
- amountRows = inputData.length,
137
- container = me.parent,
138
- columns = container.items[0].items,
139
- colCount = columns.length,
140
- data = [],
141
- i = 0,
142
- vdom = me.vdom,
143
- config, column, dockLeftMargin, dockRightMargin, id, index, j,
144
- record, selectedRows, trCls;
145
-
146
- me.recordVnodeMap = {}; // remove old data
147
-
148
- if (container.selectionModel.ntype === 'selection-table-rowmodel') {
149
- selectedRows = container.selectionModel.items || [];
147
+ let me = this,
148
+ amountRows = inputData.length,
149
+ tableContainer = me.parent,
150
+ columns = tableContainer.items[0].items,
151
+ colCount = columns.length,
152
+ data = [],
153
+ i = 0,
154
+ vdom = me.vdom,
155
+ config, colspan, colspanKeys, column, dockLeftMargin, dockRightMargin, id, index, j, record, selectedRows, trCls;
156
+
157
+ if (tableContainer.selectionModel.ntype === 'selection-table-rowmodel') {
158
+ selectedRows = tableContainer.selectionModel.items || [];
150
159
  }
151
160
 
152
161
  for (; i < amountRows; i++) {
153
- record = inputData[i];
154
- id = me.getRowId(record, i);
162
+ record = inputData[i];
163
+ colspan = record[me.colspanField];
164
+ colspanKeys = colspan && Object.keys(colspan);
165
+ id = me.getRowId(record, i);
155
166
 
156
167
  me.recordVnodeMap[id] = i;
157
168
 
@@ -180,7 +191,7 @@ class View extends Component {
180
191
 
181
192
  for (; j < colCount; j++) {
182
193
  column = columns[j];
183
- config = me.applyRendererOutput(null, column, record, i, container);
194
+ config = me.applyRendererOutput({column, record, index: i, tableContainer});
184
195
 
185
196
  if (column.dock) {
186
197
  config.cls = ['neo-locked', ...config.cls || []];
@@ -196,6 +207,10 @@ class View extends Component {
196
207
  }
197
208
 
198
209
  data[i].cn.push(config);
210
+
211
+ if (colspanKeys?.includes(column.dataField)) {
212
+ j += (colspan[column.dataField] - 1)
213
+ }
199
214
  }
200
215
 
201
216
  j = 0;
@@ -208,13 +223,16 @@ class View extends Component {
208
223
  data[i].cn[index].style.right = dockRightMargin + 'px';
209
224
  dockRightMargin += (column.width + 1); // todo: borders fix
210
225
  }
226
+
227
+ if (colspanKeys?.includes(column.dataField)) {
228
+ j += (colspan[column.dataField] - 1)
229
+ }
211
230
  }
212
231
  }
213
232
 
214
233
  vdom.cn = data;
215
234
 
216
- container.dockLeftMargin = dockLeftMargin;
217
- container.dockRightMargin = dockRightMargin;
235
+ Object.assign(tableContainer, {dockLeftMargin, dockRightMargin});
218
236
 
219
237
  me.promiseUpdate().then(() => {
220
238
  if (selectedRows?.length > 0) {
@@ -243,11 +261,12 @@ class View extends Component {
243
261
  }
244
262
 
245
263
  /**
246
- * Get a table column by a given field name
264
+ * Get a table column or column index by a given field name
247
265
  * @param {String} field
248
- * @returns {Object|null}
266
+ * @param {Boolean} returnIndex=false
267
+ * @returns {Object|Number|null}
249
268
  */
250
- getColumn(field) {
269
+ getColumn(field, returnIndex=false) {
251
270
  let container = this.parent,
252
271
  columns = container.items[0].items, // todo: we need a shortcut for accessing the header toolbar
253
272
  i = 0,
@@ -258,7 +277,7 @@ class View extends Component {
258
277
  column = columns[i];
259
278
 
260
279
  if (column.dataField === field) {
261
- return column
280
+ return returnIndex ? i : column
262
281
  }
263
282
  }
264
283
 
@@ -336,26 +355,32 @@ class View extends Component {
336
355
  * @param {Object} opts.record
337
356
  */
338
357
  onStoreRecordChange(opts) {
339
- let me = this,
340
- container = me.parent,
341
- needsUpdate = false,
342
- vdom = me.vdom,
358
+ let me = this,
359
+ fieldNames = opts.fields.map(field => field.name),
360
+ needsUpdate = false,
361
+ tableContainer = me.parent,
362
+ vdom = me.vdom,
343
363
  cellId, cellNode, column, index, scope;
344
364
 
345
- opts.fields.forEach(field => {
346
- cellId = me.getCellId(opts.record, field.name);
347
- cellNode = VDomUtil.findVdomChild(vdom, cellId);
348
-
349
- // the vdom might not exist yet => nothing to do in this case
350
- if (cellNode?.vdom) {
351
- column = me.getColumn(field.name);
352
- index = cellNode.index;
353
- needsUpdate = true;
354
- scope = column.rendererScope || container;
355
-
356
- cellNode.parentNode.cn[index] = me.applyRendererOutput(cellId, column, opts.record, index, container)
357
- }
358
- });
365
+ if (fieldNames.includes(me.colspanField)) {
366
+ // we should narrow it down to only update the current row
367
+ me.createViewData(me.store.items)
368
+ } else {
369
+ opts.fields.forEach(field => {
370
+ cellId = me.getCellId(opts.record, field.name);
371
+ cellNode = VDomUtil.findVdomChild(vdom, cellId);
372
+
373
+ // the vdom might not exist yet => nothing to do in this case
374
+ if (cellNode?.vdom) {
375
+ column = me.getColumn(field.name);
376
+ index = cellNode.index;
377
+ needsUpdate = true;
378
+ scope = column.rendererScope || tableContainer;
379
+
380
+ cellNode.parentNode.cn[index] = me.applyRendererOutput({cellId, column, record: opts.record, index, tableContainer})
381
+ }
382
+ })
383
+ }
359
384
 
360
385
  needsUpdate && me.update()
361
386
  }
@@ -41,15 +41,75 @@ class Paging extends Toolbar {
41
41
  /**
42
42
  * @member {Function} totalText_=count=>`Total: ${count} records`
43
43
  */
44
- totalText_: count => `Total: ${count} rows`
45
- }
44
+ totalText_: count => `Total: ${count} rows`,
45
+ /**
46
+ * @member {Object|Object[]} items
47
+ */
48
+ items: {
49
+ 'nav-button-first': {
50
+ handler : 'up.onFirstPageButtonClick',
51
+ iconCls : 'fa fa-angles-left'
52
+ },
53
+ 'nav-button-prev': {
54
+ handler : 'up.onPrevPageButtonClick',
55
+ iconCls : 'fa fa-angle-left',
56
+ style : {marginLeft: '2px'}
57
+ },
58
+ 'pages-text': {
59
+ ntype : 'label',
60
+ style : {marginLeft: '10px'}
61
+ },
62
+ 'nav-button-next': {
63
+ handler : 'up.onNextPageButtonClick',
64
+ iconCls : 'fa fa-angle-right',
65
+ style : {marginLeft: '10px'}
66
+ },
67
+ 'nav-button-last': {
68
+ handler : 'up.onLastPageButtonClick',
69
+ iconCls : 'fa fa-angles-right',
70
+ style : {marginLeft: '2px'}
71
+ },
72
+ label: {
73
+ ntype: 'label',
74
+ style: {marginLeft: '50px'},
75
+ text : 'Rows per page:'
76
+ },
77
+ rowsPerPage: {
78
+ module : SelectField,
79
+ clearable : false,
80
+ hideLabel : true,
81
+ listConfig : {highlightFilterValue: false},
82
+ listeners : {change: 'up.onPageSizeFieldChange'},
83
+ style : {margin: 0},
84
+ triggerAction: 'all',
85
+ useFilter : false,
86
+ value : 30,
87
+ width : 70,
46
88
 
47
- /**
48
- * @param config
49
- */
50
- construct(config) {
51
- super.construct(config);
52
- this.createToolbarItems();
89
+ store: {
90
+ model: {
91
+ fields: [
92
+ {name: 'id', type: 'Integer'},
93
+ {name: 'name', type: 'Integer'}
94
+ ]
95
+ },
96
+ data: [
97
+ {id: 1, name: 10},
98
+ {id: 2, name: 20},
99
+ {id: 3, name: 30},
100
+ {id: 4, name: 50},
101
+ {id: 5, name: 100}
102
+ ]
103
+ }
104
+ },
105
+ spacer: {
106
+ ntype: 'component',
107
+ flex : 1
108
+ },
109
+ 'total-text': {
110
+ ntype: 'label'
111
+ }
112
+ }
53
113
  }
54
114
 
55
115
  /**
@@ -115,74 +175,6 @@ class Paging extends Toolbar {
115
175
  return ClassSystemUtil.beforeSetInstance(value, null, {listeners});
116
176
  }
117
177
 
118
- /**
119
- *
120
- */
121
- createToolbarItems() {
122
- let me = this;
123
-
124
- me.items = [{
125
- handler : me.onFirstPageButtonClick.bind(me),
126
- iconCls : 'fa fa-angles-left',
127
- reference: 'nav-button-first'
128
- }, {
129
- handler : me.onPrevPageButtonClick.bind(me),
130
- iconCls : 'fa fa-angle-left',
131
- reference: 'nav-button-prev',
132
- style : {marginLeft: '2px'}
133
- }, {
134
- ntype : 'label',
135
- reference: 'pages-text',
136
- style : {marginLeft: '10px'},
137
- text : me.pagesText(me)
138
- }, {
139
- handler : me.onNextPageButtonClick.bind(me),
140
- iconCls : 'fa fa-angle-right',
141
- reference: 'nav-button-next',
142
- style : {marginLeft: '10px'}
143
- }, {
144
- handler : me.onLastPageButtonClick.bind(me),
145
- iconCls : 'fa fa-angles-right',
146
- reference: 'nav-button-last',
147
- style : {marginLeft: '2px'}
148
- }, {
149
- ntype: 'label',
150
- style: {marginLeft: '50px'},
151
- text : 'Rows per page:'
152
- }, {
153
- module : SelectField,
154
- clearable : false,
155
- hideLabel : true,
156
- listConfig : {highlightFilterValue: false},
157
- listeners : {change: me.onPageSizeFieldChange.bind(me)},
158
- style : {margin: 0},
159
- triggerAction: 'all',
160
- useFilter : false,
161
- value : 30,
162
- width : 70,
163
-
164
- store: {
165
- model: {
166
- fields: [
167
- {name: 'id', type: 'Integer'},
168
- {name: 'name', type: 'Integer'}
169
- ]
170
- },
171
- data: [
172
- {id: 1, name: 10},
173
- {id: 2, name: 20},
174
- {id: 3, name: 30},
175
- {id: 4, name: 50},
176
- {id: 5, name: 100}
177
- ]
178
- }
179
- }, '->', {
180
- ntype : 'label',
181
- reference: 'total-text',
182
- text : me.totalText(me.store.totalCount)
183
- }];
184
- }
185
-
186
178
  /**
187
179
  * @returns {Number}
188
180
  */
@@ -1,6 +1,8 @@
1
1
  import Container from '../container/Base.mjs';
2
2
  import Label from '../component/Label.mjs';
3
3
 
4
+ let singletons = {};
5
+
4
6
  /**
5
7
  * Base class for component tooltips
6
8
  * @class Neo.tooltip.Base
@@ -44,6 +46,10 @@ class Base extends Container {
44
46
  * @protected
45
47
  */
46
48
  dismissDelayTaskId: null,
49
+ /**
50
+ * @member {Boolean} floating=true
51
+ */
52
+ floating: true,
47
53
  /**
48
54
  * The delay in ms before the tooltip gets shown
49
55
  * @member {Number|null} hideDelay=400
@@ -78,6 +84,18 @@ class Base extends Container {
78
84
  text_: null
79
85
  }
80
86
 
87
+ /**
88
+ * @param {String} id
89
+ * @param {Function} callback
90
+ * @param {Number} delay
91
+ */
92
+ addTimeout(id, callback, delay) {
93
+ id += 'DelayTaskId';
94
+
95
+ this.clearTimeout(this[id]);
96
+ this[id] = setTimeout(callback, delay);
97
+ }
98
+
81
99
  /**
82
100
  * Triggered after the componentId config got changed
83
101
  * @param {String} value
@@ -93,8 +111,8 @@ class Base extends Container {
93
111
  let me = this;
94
112
 
95
113
  Neo.getComponent(value).addDomListeners({
96
- mouseenter: me.showDelayed,
97
- mouseleave: me.hideDelayed,
114
+ mouseenter: me.onDelegateMouseEnter,
115
+ mouseleave: me.onDelegateMouseLeave,
98
116
  delegate : me.delegate,
99
117
  scope : me
100
118
  })
@@ -137,12 +155,10 @@ class Base extends Container {
137
155
  if (item?.ntype === 'label') {
138
156
  item.text = value;
139
157
  } else {
140
- items.push({
158
+ me.add({
141
159
  module: Label,
142
160
  text : value
143
161
  });
144
-
145
- me.items = items;
146
162
  }
147
163
  }
148
164
  }
@@ -169,11 +185,48 @@ class Base extends Container {
169
185
  });
170
186
  }
171
187
 
188
+ /**
189
+ * @param {Neo.controller.Application} app
190
+ * @returns {Neo.tooltip.Base}
191
+ */
192
+ static createSingleton(app) {
193
+ if (!singletons[app.name]) {
194
+ singletons[app.name] = Neo.create('Neo.tooltip.Base', {
195
+ appName : app.name,
196
+ componentId : app.mainView.id,
197
+ resetCfg : {},
198
+ isShared : true,
199
+ delegate : '.neo-uses-shared-tooltip',
200
+ listeners : {
201
+ // Reconfigure on over a target
202
+ async targetOver({ target }) {
203
+ // Revert last pointerOver config set to initial setting.
204
+ this.set(this.resetCfg);
205
+ this.resetCfg = {};
206
+
207
+ // Use the tooltip config block that the target was configured with
208
+ // to reconfogure tis instance
209
+ const config = target?._tooltip;
210
+
211
+ // Cache things we have to reset
212
+ for (const key in config) {
213
+ this.resetCfg[key] = this[key];
214
+ }
215
+
216
+ // Set ourself up as the target wants
217
+ this.set(config);
218
+ }
219
+ }
220
+ });
221
+ }
222
+
223
+ return singletons[app.name];
224
+ }
225
+
172
226
  /**
173
227
  * Instantly hides the tooltip
174
- * @param {Object|null} data
175
228
  */
176
- hide(data) {
229
+ hide() {
177
230
  let me = this;
178
231
 
179
232
  me.clearTimeout(['dismiss', 'hide', 'show']);
@@ -188,12 +241,59 @@ class Base extends Container {
188
241
  let me = this;
189
242
 
190
243
  if (me.hideDelay) {
191
- me.hideDelayTaskId = setTimeout(me.hide.bind(me), me.hideDelay, data);
244
+ me.addTimeout('hide', me.hide.bind(me), me.hideDelay);
192
245
  } else {
193
246
  me.hide(data)
194
247
  }
195
248
  }
196
249
 
250
+ /**
251
+ * @param {Object} data
252
+ */
253
+ onDelegateMouseEnter(data) {
254
+ const
255
+ me = this,
256
+ {
257
+ currentTarget
258
+ } = data;
259
+
260
+ // If it's an internal move within the delegate, do nothing
261
+ if (currentTarget !== me.activeTarget?.id) {
262
+ me.activeTarget = Neo.get(currentTarget);
263
+ me.align.target = currentTarget;
264
+ me.align.targetMargin = 10;
265
+
266
+ me.fire('targetOver', {
267
+ target : me.activeTarget
268
+ });
269
+
270
+ // Still visible, just realign
271
+ if (me.mounted) {
272
+ me.show();
273
+ me.alignTo();
274
+ }
275
+ else {
276
+ me.showDelayed(data);
277
+ }
278
+ }
279
+ }
280
+
281
+ /**
282
+ * @param {Object} data
283
+ */
284
+ onDelegateMouseLeave(data) {
285
+ const me = this;
286
+
287
+ // If it's an internal move within the delegate, do nothing
288
+ if (data.currentTarget === me.activeTarget?.id) {
289
+ me.fire('targetOut', {
290
+ target : this.activeTarget
291
+ });
292
+ me.activeTarget = null;
293
+ me.hideDelayed(data);
294
+ }
295
+ }
296
+
197
297
  /**
198
298
  * mouseenter event listener for the tooltip element
199
299
  * @param {Object} data
@@ -227,10 +327,10 @@ class Base extends Container {
227
327
 
228
328
  me.showDelayTaskId = null;
229
329
 
230
- me.clearTimeout('hide');
330
+ me.clearTimeout(['hide', 'dismiss']);
231
331
 
232
332
  if (me.dismissDelay) {
233
- me.dismissDelayTaskId = setTimeout(me.hide.bind(me), me.dismissDelay, data);
333
+ me.addTimeout('dismiss', me.hide.bind(me), me.dismissDelay, data);
234
334
  }
235
335
 
236
336
  !me.mounted && me.render(true)
@@ -244,7 +344,7 @@ class Base extends Container {
244
344
  let me = this;
245
345
 
246
346
  if (me.showDelay) {
247
- me.showDelayTaskId = setTimeout(me.show.bind(me), me.showDelay, data)
347
+ me.addTimeout('show', me.show.bind(me), me.showDelay)
248
348
  } else {
249
349
  me.show(data)
250
350
  }