|
Lines 83-92
Link Here
|
| 83 |
|
83 |
|
| 84 |
_readyDeferred: null, |
84 |
_readyDeferred: null, |
| 85 |
|
85 |
|
|
|
86 |
_allWidgetsBuiltDeferred: null, |
| 87 |
|
| 86 |
_startupDeferred: null, |
88 |
_startupDeferred: null, |
| 87 |
|
89 |
|
| 88 |
_blockChangeEvents: false, |
90 |
_blockChangeEvents: false, |
| 89 |
|
91 |
|
|
|
92 |
_hasSubtypeLabel: false, |
| 93 |
|
| 90 |
_createHandler: function(ifunc) { |
94 |
_createHandler: function(ifunc) { |
| 91 |
// This handler will be called by all subwidgets of the MultiInput widget. |
95 |
// This handler will be called by all subwidgets of the MultiInput widget. |
| 92 |
// When the first request comes in, we will execute the function to compute |
96 |
// When the first request comes in, we will execute the function to compute |
|
Lines 126-136
Link Here
|
| 126 |
this._readyDeferred = new Deferred(); |
130 |
this._readyDeferred = new Deferred(); |
| 127 |
|
131 |
|
| 128 |
this._startupDeferred = new Deferred(); |
132 |
this._startupDeferred = new Deferred(); |
|
|
133 |
this._allWidgetsBuiltDeferred = new Deferred(); |
| 129 |
|
134 |
|
| 130 |
// check the property 'subtypes' |
135 |
// check the property 'subtypes' |
| 131 |
tools.assert(this.subtypes instanceof Array, |
136 |
tools.assert(this.subtypes instanceof Array, |
| 132 |
'umc/widgets/ContainerWidget: The property subtypes needs to be a string or an array of strings: ' + this.subtypes); |
137 |
'umc/widgets/ContainerWidget: The property subtypes needs to be a string or an array of strings: ' + this.subtypes); |
| 133 |
|
138 |
|
|
|
139 |
this._hasSubtypeLabel = array.some(this.subtypes, function(iwidget) { |
| 140 |
return iwidget.label; |
| 141 |
}); |
| 142 |
|
| 134 |
// initiate other properties |
143 |
// initiate other properties |
| 135 |
this._rowContainers = []; |
144 |
this._rowContainers = []; |
| 136 |
this._widgets = []; |
145 |
this._widgets = []; |
|
Lines 171-177
Link Here
|
| 171 |
this.inherited(arguments); |
180 |
this.inherited(arguments); |
| 172 |
|
181 |
|
| 173 |
// add empty element |
182 |
// add empty element |
| 174 |
this._appendElements(1); |
183 |
this._appendRows(); |
| 175 |
}, |
184 |
}, |
| 176 |
|
185 |
|
| 177 |
_loadValues: function(depends) { |
186 |
_loadValues: function(depends) { |
|
Lines 179-185
Link Here
|
| 179 |
this._lastDepends = depends; |
188 |
this._lastDepends = depends; |
| 180 |
array.forEach(this._widgets, function(iwidgets) { |
189 |
array.forEach(this._widgets, function(iwidgets) { |
| 181 |
array.forEach(iwidgets, function(jwidget) { |
190 |
array.forEach(iwidgets, function(jwidget) { |
| 182 |
if ('_loadValues' in jwidget) { |
191 |
if (jwidget && '_loadValues' in jwidget) { |
| 183 |
jwidget._loadValues(depends); |
192 |
jwidget._loadValues(depends); |
| 184 |
} |
193 |
} |
| 185 |
}); |
194 |
}); |
|
Lines 187-192
Link Here
|
| 187 |
}, |
196 |
}, |
| 188 |
|
197 |
|
| 189 |
_setAllValues: function(_valList) { |
198 |
_setAllValues: function(_valList) { |
|
|
199 |
var _valList = lang.clone(_valList); |
| 190 |
this._blockChangeEvents = true; |
200 |
this._blockChangeEvents = true; |
| 191 |
var valList = _valList; |
201 |
var valList = _valList; |
| 192 |
if (!(valList instanceof Array)) { |
202 |
if (!(valList instanceof Array)) { |
|
Lines 196-240
Link Here
|
| 196 |
// adjust the number of rows |
206 |
// adjust the number of rows |
| 197 |
var diff = valList.length - this._nRenderedElements; |
207 |
var diff = valList.length - this._nRenderedElements; |
| 198 |
if (diff > 0) { |
208 |
if (diff > 0) { |
| 199 |
this._appendElements(diff); |
209 |
this._appendRows(diff); |
| 200 |
} |
210 |
} |
| 201 |
else if (diff < 0) { |
211 |
else if (diff < 0) { |
| 202 |
this._popElements(-diff); |
212 |
this._popElements(-diff); |
| 203 |
} |
213 |
} |
| 204 |
|
214 |
|
| 205 |
// set all values |
215 |
this._allWidgetsBuiltDeferred.then(lang.hitch(this, function() { |
| 206 |
array.forEach(valList, function(ival, irow) { |
216 |
// set all values |
| 207 |
if (irow >= this._widgets.length) { |
217 |
array.forEach(valList, function(ival, irow) { |
| 208 |
// break |
218 |
if (irow >= this._widgets.length) { |
| 209 |
return false; |
219 |
return; |
| 210 |
} |
220 |
} |
| 211 |
|
221 |
|
| 212 |
var rowVals = []; |
222 |
var rowVals = []; |
| 213 |
if (typeof ival == "string") { |
223 |
if (typeof ival == "string") { |
| 214 |
// entry is string .. we need to parse it if we have a delimiter |
224 |
// entry is string .. we need to parse it if we have a delimiter |
| 215 |
if (this.delimiter) { |
225 |
if (this.delimiter) { |
| 216 |
rowVals = ival.split(this.delimiter); |
226 |
rowVals = ival.split(this.delimiter); |
|
|
227 |
} |
| 228 |
else { |
| 229 |
rowVals = [ ival ]; |
| 230 |
} |
| 217 |
} |
231 |
} |
| 218 |
else { |
232 |
else if (ival instanceof Array) { |
| 219 |
rowVals = [ ival ]; |
233 |
rowVals = ival; |
| 220 |
} |
234 |
} |
| 221 |
} |
|
|
| 222 |
else if (ival instanceof Array) { |
| 223 |
rowVals = ival; |
| 224 |
} |
| 225 |
|
235 |
|
| 226 |
// set values |
236 |
// set values |
| 227 |
for (var j = 0; j < this.subtypes.length; ++j) { |
237 |
for (var j = 0; j < this.subtypes.length; ++j) { |
| 228 |
var val = j >= rowVals.length ? '' : rowVals[j]; |
238 |
var val = j >= rowVals.length ? '' : rowVals[j]; |
| 229 |
this._widgets[irow][j].set('value', val); |
239 |
this._widgets[irow][j].set('value', val); |
| 230 |
|
240 |
|
| 231 |
// for dynamic combo boxes, we need to save the value as "initial value" |
241 |
// for dynamic combo boxes, we need to save the value as "initial value" |
| 232 |
if (this._widgets[irow][j].setInitialValue) { |
242 |
if (this._widgets[irow][j].setInitialValue) { |
| 233 |
this._widgets[irow][j].setInitialValue(val, false); |
243 |
this._widgets[irow][j].setInitialValue(val, false); |
|
|
244 |
} |
| 234 |
} |
245 |
} |
| 235 |
} |
246 |
}, this); |
| 236 |
}, this); |
247 |
this._blockChangeEvents = false; |
| 237 |
this._blockChangeEvents = false; |
248 |
})); |
| 238 |
}, |
249 |
}, |
| 239 |
|
250 |
|
| 240 |
_setValueAttr: function(_vals) { |
251 |
_setValueAttr: function(_vals) { |
|
Lines 252-273
Link Here
|
| 252 |
}, |
263 |
}, |
| 253 |
|
264 |
|
| 254 |
_setDisabledAttr: function ( value ) { |
265 |
_setDisabledAttr: function ( value ) { |
| 255 |
var i; |
266 |
this._allWidgetsBuiltDeferred.then(lang.hitch(this, function() { |
| 256 |
for ( i = 0; i < this._rowContainers.length; ++i) { |
267 |
var i; |
| 257 |
array.forEach( this._rowContainers[ i ].getChildren(), function( widget ) { |
268 |
for ( i = 0; i < this._rowContainers.length; ++i) { |
| 258 |
widget.set( 'disabled', value ); |
269 |
var irow = this._rowContainers[i]; |
| 259 |
} ); |
270 |
array.forEach( irow ? irow.getChildren() : [], function( widget ) { |
| 260 |
} |
271 |
widget.set('disabled', value); |
| 261 |
this.disabled = value; |
272 |
} ); |
|
|
273 |
} |
| 274 |
})); |
| 275 |
this._set('disabled', value); |
| 262 |
}, |
276 |
}, |
| 263 |
|
277 |
|
| 264 |
_getAllValues: function() { |
278 |
_getAllValues: function() { |
| 265 |
var i, j, val, isSet, vals = [], rowVals = []; |
279 |
var i, j, jwidget, val, isSet, vals = [], rowVals = []; |
| 266 |
for (i = 0; i < this._widgets.length; ++i) { |
280 |
for (i = 0; i < this._widgets.length; ++i) { |
| 267 |
rowVals = []; |
281 |
rowVals = []; |
| 268 |
isSet = false; |
282 |
isSet = false; |
| 269 |
for (j = 0; j < this._widgets[i].length; ++j) { |
283 |
for (j = 0; j < this._widgets[i].length; ++j) { |
| 270 |
val = this._widgets[i][j].get('value'); |
284 |
jwidget = this._widgets[i][j]; |
|
|
285 |
if (!jwidget) { |
| 286 |
continue; |
| 287 |
} |
| 288 |
val = jwidget.get('value'); |
| 271 |
isSet = isSet || ('' !== val); |
289 |
isSet = isSet || ('' !== val); |
| 272 |
if (!tools.inheritsFrom(this._widgets[i][j], 'umc.widgets.Button')) { |
290 |
if (!tools.inheritsFrom(this._widgets[i][j], 'umc.widgets.Button')) { |
| 273 |
rowVals.push(val); |
291 |
rowVals.push(val); |
|
Lines 315-475
Link Here
|
| 315 |
return; |
333 |
return; |
| 316 |
} |
334 |
} |
| 317 |
|
335 |
|
| 318 |
// verify whether label information for subtypes are given |
|
|
| 319 |
var hasSubTypeLabels = false; |
| 320 |
array.forEach(this.subtypes, function(iwidget) { |
| 321 |
hasSubTypeLabels = hasSubTypeLabels || iwidget.label; |
| 322 |
}); |
| 323 |
|
| 324 |
// create 'new' button |
336 |
// create 'new' button |
| 325 |
var btn = this.own(new Button({ |
337 |
var btn = this.own(new Button({ |
| 326 |
disabled: this.disabled, |
338 |
disabled: this.disabled, |
| 327 |
iconClass: 'umcIconAdd', |
339 |
iconClass: 'umcIconAdd', |
| 328 |
onClick: lang.hitch(this, '_appendElements', 1), |
340 |
onClick: lang.hitch(this, '_appendRows'), |
| 329 |
'class': 'umcMultiInputAddButton' |
341 |
'class': 'umcMultiInputAddButton' |
| 330 |
}))[0]; |
342 |
}))[0]; |
| 331 |
|
343 |
|
| 332 |
// wrap a button with a LabelPane |
344 |
// wrap a button with a LabelPane |
| 333 |
this._newButton = this.own(new LabelPane({ |
345 |
this._newButton = this.own(new LabelPane({ |
| 334 |
content: btn, |
346 |
content: btn, |
| 335 |
label: this._nRenderedElements === 1 && hasSubTypeLabels ? ' ' : '' // only keep the label for the first row |
347 |
label: this._nRenderedElements === 1 && this._hasSubtypeLabel ? ' ' : '' // only keep the label for the first row |
| 336 |
}))[0]; |
348 |
}))[0]; |
| 337 |
|
349 |
|
| 338 |
// add button to last row |
350 |
// add button to last row |
| 339 |
this._rowContainers[this._rowContainers.length - 1].addChild(this._newButton); |
351 |
this._rowContainers[this._rowContainers.length - 1].addChild(this._newButton); |
| 340 |
}, |
352 |
}, |
| 341 |
|
353 |
|
| 342 |
_appendElements: function(n) { |
354 |
_updateReadyDeferred: function() { |
| 343 |
if (n < 1) { |
355 |
// check all current elements whether they are ready |
| 344 |
return; |
356 |
var nReady = 0; |
|
|
357 |
var nElements = 0; |
| 358 |
var nBuiltElements = 0; |
| 359 |
var i, j; |
| 360 |
for (i = 0; i < this._widgets.length; ++i) { |
| 361 |
for (j = 0; j < this._widgets[i].length; ++j, ++nElements) { |
| 362 |
//console.log(lang.replace('### MultiInput: widget[{0}][{1}]: waiting -> ', [i, j]), this._widgets[i][j].ready()); |
| 363 |
var jwidget = this._widgets[i][j]; |
| 364 |
nBuiltElements += jwidget ? 1 : 0; |
| 365 |
var jreadyDeferred = jwidget && jwidget.ready ? jwidget.ready() : null; |
| 366 |
if (!jreadyDeferred) { |
| 367 |
++nReady; |
| 368 |
} |
| 369 |
else if (jreadyDeferred.isFulfilled()) { |
| 370 |
++nReady; |
| 371 |
} |
| 372 |
} |
| 345 |
} |
373 |
} |
| 346 |
|
374 |
|
| 347 |
// initiate a new Deferred object in case there is none already pending |
375 |
if (nReady < nElements) { |
| 348 |
if (this._readyDeferred.isFulfilled()) { |
376 |
if (this._readyDeferred.isFulfilled()) { |
| 349 |
this._readyDeferred = new Deferred(); |
377 |
// initiate a new Deferred object if none is pending |
|
|
378 |
this._readyDeferred = new Deferred(); |
| 379 |
} |
| 380 |
|
| 381 |
// update progress |
| 382 |
this._readyDeferred.progress({ |
| 383 |
max: nElements, |
| 384 |
current: nReady, |
| 385 |
percentage: 100 * nReady / nElements |
| 386 |
}); |
| 350 |
} |
387 |
} |
| 351 |
|
388 |
|
| 352 |
// remove the 'new' button |
389 |
if (nReady == nElements && !this._readyDeferred.isFulfilled()) { |
| 353 |
this._removeNewButton(); |
390 |
// all elements are ready |
|
|
391 |
this._readyDeferred.resolve(); |
| 392 |
this.onValuesLoaded(); |
| 393 |
} |
| 354 |
|
394 |
|
| 355 |
var nFinal = this._nRenderedElements + n; |
395 |
if (nBuiltElements < nElements && this._allWidgetsBuiltDeferred.isFulfilled()) { |
| 356 |
for (var irow = this._nRenderedElements; irow < nFinal && irow < this.max; ++irow, ++this._nRenderedElements) { |
396 |
// initiate a new Deferred object |
| 357 |
// add all other elements with '__' such that they will be ignored by umc/widgets/Form |
397 |
this._allWidgetsBuiltDeferred = new Deferred(); |
| 358 |
var order = [], widgetConfs = []; |
398 |
} |
| 359 |
array.forEach(this.subtypes, function(iwidget, i) { |
|
|
| 360 |
// add the widget configuration dict to the list of widgets |
| 361 |
var iname = '__' + this.name + '-' + irow + '-' + i; |
| 362 |
var iconf = lang.mixin({}, iwidget, { |
| 363 |
disabled: this.disabled, |
| 364 |
threshold: this.threshold, // for UDM-threshold |
| 365 |
name: iname, |
| 366 |
value: '', |
| 367 |
dynamicValues: lang.partial(iwidget.dynamicValues, iname) |
| 368 |
}); |
| 369 |
if (iwidget.dynamicValuesInfo) { |
| 370 |
iconf.dynamicValuesInfo = lang.partial(iwidget.dynamicValuesInfo, iname); |
| 371 |
} |
| 372 |
widgetConfs.push(iconf); |
| 373 |
|
399 |
|
| 374 |
// add the name of the widget to the list of widget names |
400 |
if (nBuiltElements == nElements && !this._allWidgetsBuiltDeferred.isFulfilled()) { |
| 375 |
order.push(iname); |
401 |
// all elements have been built |
| 376 |
}, this); |
402 |
this._allWidgetsBuiltDeferred.resolve(); |
|
|
403 |
} |
| 404 |
}, |
| 377 |
|
405 |
|
|
|
406 |
__appendRow: function(irow) { |
| 407 |
var order = [], widgetConfs = []; |
| 408 |
array.forEach(this.subtypes, function(iwidget, i) { |
| 409 |
// add the widget configuration dict to the list of widgets |
| 410 |
var iname = '__' + this.name + '-' + irow + '-' + i; |
| 411 |
var iconf = lang.mixin({}, iwidget, { |
| 412 |
disabled: this.disabled, |
| 413 |
threshold: this.threshold, // for UDM-threshold |
| 414 |
name: iname, |
| 415 |
value: '', |
| 416 |
dynamicValues: lang.partial(iwidget.dynamicValues, iname) |
| 417 |
}); |
| 418 |
if (iwidget.dynamicValuesInfo) { |
| 419 |
iconf.dynamicValuesInfo = lang.partial(iwidget.dynamicValuesInfo, iname); |
| 420 |
} |
| 421 |
widgetConfs.push(iconf); |
| 378 |
|
422 |
|
| 379 |
// render the widgets |
423 |
// add the name of the widget to the list of widget names |
| 380 |
var widgets = render.widgets(widgetConfs, this); |
424 |
order.push(iname); |
|
|
425 |
}, this); |
| 381 |
|
426 |
|
| 382 |
// if we have a button, we need to pass the value and index if the |
|
|
| 383 |
// current element |
| 384 |
tools.forIn(widgets, function(ikey, iwidget) { |
| 385 |
var myrow = irow; |
| 386 |
if (tools.inheritsFrom(iwidget, 'umc.widgets.Button') && typeof iwidget.callback == "function") { |
| 387 |
var callbackOrg = iwidget.callback; |
| 388 |
iwidget.callback = lang.hitch(this, function() { |
| 389 |
callbackOrg(this.get('value')[myrow], myrow); |
| 390 |
}); |
| 391 |
} |
| 392 |
}, this); |
| 393 |
|
427 |
|
| 394 |
// find out whether all items do have a label |
428 |
// render the widgets |
| 395 |
var hasSubTypeLabels = array.filter(this.subtypes, function(iwidget) { |
429 |
var widgets = render.widgets(widgetConfs, this); |
| 396 |
return iwidget.label; |
|
|
| 397 |
}).length > 0; |
| 398 |
|
430 |
|
| 399 |
// layout widgets |
431 |
// if we have a button, we need to pass the value and index of the |
| 400 |
var visibleWidgets = array.map(order, function(iname) { |
432 |
// current element |
| 401 |
return widgets[iname]; |
433 |
tools.forIn(widgets, function(ikey, iwidget) { |
| 402 |
}); |
434 |
var myrow = irow; |
| 403 |
var rowContainer = this.own(new ContainerWidget({}))[0]; |
435 |
if (tools.inheritsFrom(iwidget, 'umc.widgets.Button') && typeof iwidget.callback == "function") { |
| 404 |
array.forEach(order, function(iname) { |
436 |
var callbackOrg = iwidget.callback; |
| 405 |
// add widget to row container (wrapped by a LabelPane) |
437 |
iwidget.callback = lang.hitch(this, function() { |
| 406 |
// only keep the label for the first row |
438 |
callbackOrg(this.get('value')[myrow], myrow); |
| 407 |
var iwidget = widgets[iname]; |
439 |
}); |
| 408 |
var label = irow !== 0 ? '' : iwidget.label; |
440 |
} |
| 409 |
if (tools.inheritsFrom(iwidget, 'umc.widgets.Button')) { |
441 |
}, this); |
| 410 |
label = irow !== 0 ? '' : ' '; |
|
|
| 411 |
} |
| 412 |
rowContainer.addChild(new LabelPane({ |
| 413 |
disabled: this.disabled, |
| 414 |
content: iwidget, |
| 415 |
label: label |
| 416 |
})); |
| 417 |
|
442 |
|
| 418 |
// register to value changes |
443 |
// layout widgets |
| 419 |
this.own(iwidget.watch('value', lang.hitch(this, function() { |
444 |
var visibleWidgets = array.map(order, function(iname) { |
| 420 |
if (!this._blockChangeEvents) { |
445 |
return widgets[iname]; |
| 421 |
this._set('value', this.get('value')); |
446 |
}); |
| 422 |
} |
447 |
var rowContainer = this.own(new ContainerWidget({}))[0]; |
| 423 |
}))); |
448 |
array.forEach(order, function(iname) { |
| 424 |
}, this); |
449 |
// add widget to row container (wrapped by a LabelPane) |
| 425 |
|
450 |
// only keep the label for the first row |
| 426 |
// add a 'remove' button at the end of the row |
451 |
var iwidget = widgets[iname]; |
| 427 |
var button = this.own(new Button({ |
452 |
var label = irow !== 0 ? '' : iwidget.label; |
|
|
453 |
if (tools.inheritsFrom(iwidget, 'umc.widgets.Button')) { |
| 454 |
label = irow !== 0 ? '' : ' '; |
| 455 |
} |
| 456 |
rowContainer.addChild(new LabelPane({ |
| 428 |
disabled: this.disabled, |
457 |
disabled: this.disabled, |
| 429 |
iconClass: 'umcIconDelete', |
458 |
content: iwidget, |
| 430 |
onClick: lang.hitch(this, '_removeElement', irow), |
459 |
label: label |
| 431 |
'class': 'umcMultiInputRemoveButton' |
|
|
| 432 |
}))[0]; |
| 433 |
rowContainer.addChild(new LabelPane({ |
| 434 |
content: button, |
| 435 |
label: irow === 0 && hasSubTypeLabels ? ' ' : '' // only keep the label for the first row |
| 436 |
})); |
460 |
})); |
| 437 |
|
461 |
|
| 438 |
// add row |
462 |
// register to value changes |
| 439 |
this._widgets.push(visibleWidgets); |
463 |
this.own(iwidget.watch('value', lang.hitch(this, function() { |
| 440 |
this._rowContainers.push(rowContainer); |
464 |
if (!this._blockChangeEvents) { |
| 441 |
this._startupDeferred.then(lang.hitch(rowContainer, 'startup')); |
465 |
this._set('value', this.get('value')); |
| 442 |
this.addChild(rowContainer); |
466 |
} |
|
|
467 |
}))); |
| 468 |
}, this); |
| 443 |
|
469 |
|
| 444 |
// call the _loadValues method by hand |
470 |
// add a 'remove' button at the end of the row |
| 445 |
array.forEach(order, function(iname) { |
471 |
var button = this.own(new Button({ |
| 446 |
var iwidget = widgets[iname]; |
472 |
disabled: this.disabled, |
| 447 |
if ('_loadValues' in iwidget) { |
473 |
iconClass: 'umcIconDelete', |
| 448 |
iwidget._loadValues(this._lastDepends); |
474 |
onClick: lang.hitch(this, '_removeElement', irow), |
| 449 |
} |
475 |
'class': 'umcMultiInputRemoveButton' |
| 450 |
}, this); |
476 |
}))[0]; |
| 451 |
//this._readyDeferred.progress(_('%(i)s / %(len)s values built', {i: irow, len: nFinal})); |
477 |
rowContainer.addChild(new LabelPane({ |
|
|
478 |
content: button, |
| 479 |
label: irow === 0 && this._hasSubtypeLabel ? ' ' : '' // only keep the label for the first row |
| 480 |
})); |
| 481 |
|
| 482 |
// add row |
| 483 |
this._widgets[irow] = visibleWidgets; |
| 484 |
this._rowContainers[irow] = rowContainer; |
| 485 |
this._startupDeferred.then(lang.hitch(rowContainer, 'startup')); |
| 486 |
this.addChild(rowContainer); |
| 487 |
|
| 488 |
// call the _loadValues method by hand |
| 489 |
array.forEach(order, function(iname) { |
| 490 |
var iwidget = widgets[iname]; |
| 491 |
if ('_loadValues' in iwidget) { |
| 492 |
iwidget._loadValues(this._lastDepends); |
| 493 |
} |
| 494 |
}, this); |
| 495 |
|
| 496 |
// update the ready deferred know and when the widget itself is ready |
| 497 |
this._updateReadyDeferred(); |
| 498 |
var allReady = []; |
| 499 |
tools.forIn(widgets, function(ikey, iwidget) { |
| 500 |
allReady.push(iwidget.ready ? iwidget.ready() : null); |
| 501 |
}); |
| 502 |
all(allReady).then(lang.hitch(this, '_updateReadyDeferred')); |
| 503 |
}, |
| 504 |
|
| 505 |
_appendRows: function(n) { |
| 506 |
n = n || 1; |
| 507 |
if (n < 1) { |
| 508 |
return; |
| 452 |
} |
509 |
} |
| 453 |
|
510 |
|
| 454 |
// wait for all widgets to be ready |
511 |
// remove the 'new' button |
| 455 |
var allReady = []; |
512 |
this._removeNewButton(); |
| 456 |
var i, j; |
513 |
|
| 457 |
for (i = 0; i < this._widgets.length; ++i) { |
514 |
var nFinal = this._nRenderedElements + n; |
| 458 |
for (j = 0; j < this._widgets[i].length; ++j) { |
515 |
var newRows = []; |
| 459 |
//console.log(lang.replace('### MultiInput: widget[{0}][{1}]: waiting -> ', [i, j]), this._widgets[i][j].ready()); |
516 |
for (var irow = this._nRenderedElements; irow < nFinal && irow < this.max; ++irow, ++this._nRenderedElements) { |
| 460 |
allReady.push(this._widgets[i][j].ready ? this._widgets[i][j].ready() : null); |
517 |
newRows.push(irow); |
|
|
518 |
|
| 519 |
// allocate indeces in 2D array _widget this allows _updateReadyDeferred() |
| 520 |
// to know how many entries there will be at the end |
| 521 |
this._rowContainers[irow] = null; |
| 522 |
this._widgets[irow] = []; |
| 523 |
for (var jsubWidget = 0; jsubWidget < this.subtypes.length; ++jsubWidget) { |
| 524 |
this._widgets[irow][jsubWidget] = null; |
| 461 |
} |
525 |
} |
| 462 |
} |
526 |
} |
| 463 |
all(allReady).then(lang.hitch(this, function() { |
527 |
|
| 464 |
//console.log('### MultiInput: all resolved'); |
528 |
// force the ready deferred to be updated |
| 465 |
this._readyDeferred.resolve(); |
529 |
this._updateReadyDeferred(); |
| 466 |
this.onValuesLoaded(); |
530 |
|
|
|
531 |
// perform adding rows asynchronously |
| 532 |
tools.forEachAsync(newRows, lang.hitch(this, '__appendRow')).then(lang.hitch(this, function() { |
| 533 |
// all elements have been added to the DOM |
| 534 |
// add the new button |
| 535 |
if (this._nRenderedElements < this.max) { |
| 536 |
this._addNewButton(); |
| 537 |
} |
| 538 |
this._updateReadyDeferred(); |
| 467 |
})); |
539 |
})); |
| 468 |
|
|
|
| 469 |
// add the new button |
| 470 |
if (this._nRenderedElements < this.max) { |
| 471 |
this._addNewButton(); |
| 472 |
} |
| 473 |
}, |
540 |
}, |
| 474 |
|
541 |
|
| 475 |
_popElements: function(n) { |
542 |
_popElements: function(n) { |
|
Lines 492-497
Link Here
|
| 492 |
// update the number of render elements |
559 |
// update the number of render elements |
| 493 |
this._nRenderedElements -= n; |
560 |
this._nRenderedElements -= n; |
| 494 |
|
561 |
|
|
|
562 |
|
| 495 |
// add the new button |
563 |
// add the new button |
| 496 |
this._addNewButton(); |
564 |
this._addNewButton(); |
| 497 |
}, |
565 |
}, |