netzke-basepack 0.5.2 → 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/CHANGELOG.rdoc +197 -183
- data/LICENSE +1 -3
- data/README.rdoc +10 -6
- data/TODO.rdoc +5 -2
- data/VERSION +1 -1
- data/javascripts/basepack.js +20 -10
- data/lib/app/models/netzke_auto_column.rb +1 -1
- data/lib/netzke/basic_app.rb +16 -2
- data/lib/netzke/basic_app_extras/statusbar_ext.js +8 -0
- data/lib/netzke/border_layout_panel.rb +1 -1
- data/lib/netzke/ext.rb +1 -0
- data/lib/netzke/fields_configurator.rb +3 -5
- data/lib/netzke/form_panel.rb +15 -11
- data/lib/netzke/form_panel_js.rb +1 -8
- data/lib/netzke/grid_panel.rb +61 -61
- data/lib/netzke/grid_panel_api.rb +2 -2
- data/lib/netzke/grid_panel_js.rb +200 -177
- data/lib/netzke/plugins/configuration_tool.rb +2 -2
- data/lib/netzke/property_editor.rb +22 -18
- data/lib/netzke/tree_panel.rb +6 -54
- data/stylesheets/basepack.css +5 -0
- data/test/unit/helper_model_test.rb +1 -1
- metadata +3 -4
- data/lib/netzke/grid_panel_extras/javascripts/check-column.js +0 -33
- data/netzke-basepack.gemspec +0 -170
data/lib/netzke/grid_panel_js.rb
CHANGED
@@ -79,22 +79,23 @@ module Netzke
|
|
79
79
|
}
|
80
80
|
|
81
81
|
// collect filters
|
82
|
-
|
83
|
-
|
84
|
-
}
|
82
|
+
// Not compatible with Ext 3.0
|
83
|
+
//if (c.withFilters){
|
84
|
+
// filters.push({type:Ext.netzke.filterMap[c.editor.xtype], dataIndex:c.name});
|
85
|
+
//}
|
85
86
|
|
86
87
|
if (c.editor && c.editor.xtype == 'checkbox') {
|
87
88
|
// Special case of checkbox column
|
88
|
-
var plugin = new Ext.grid.CheckColumn(c);
|
89
|
+
var plugin = new Ext.ux.grid.CheckColumn(c);
|
89
90
|
this.plugins.push(plugin);
|
90
91
|
cmConfig.push(plugin);
|
91
92
|
} else {
|
92
|
-
// "normal" column, not a plugin
|
93
|
+
// a "normal" column, not a plugin
|
93
94
|
if (!c.readOnly && !this.prohibitUpdate) {
|
94
95
|
// c.editor contains complete config of the editor
|
95
96
|
var xtype = c.editor.xtype;
|
96
97
|
c.editor = Ext.ComponentMgr.create(Ext.apply({
|
97
|
-
parentId:this.id,
|
98
|
+
parentId: this.id,
|
98
99
|
name: c.name,
|
99
100
|
selectOnFocus:true
|
100
101
|
}, c.editor));
|
@@ -103,7 +104,8 @@ module Netzke
|
|
103
104
|
}
|
104
105
|
|
105
106
|
// set the renderer
|
106
|
-
|
107
|
+
var renderer = Ext.netzke.normalizedRenderer(c.renderer);
|
108
|
+
if (renderer != null) c.renderer = renderer;
|
107
109
|
|
108
110
|
// add to the list
|
109
111
|
cmConfig.push(c);
|
@@ -113,14 +115,17 @@ module Netzke
|
|
113
115
|
|
114
116
|
// Finally, create the ColumnModel based on processed columns
|
115
117
|
this.cm = new Ext.grid.ColumnModel(cmConfig);
|
116
|
-
|
118
|
+
|
119
|
+
// Hidden change event
|
120
|
+
if (this.persistentConfig) {this.cm.on('hiddenchange', this.onColumnHiddenChange, this);}
|
117
121
|
|
118
122
|
/* ... and done with columns */
|
119
123
|
|
120
124
|
// Filters
|
121
|
-
|
122
|
-
|
123
|
-
}
|
125
|
+
// Not compatible with Ext 3.0
|
126
|
+
// if (this.enableColumnFilters) {
|
127
|
+
// this.plugins.push(new Ext.grid.GridFilters({filters:filters}));
|
128
|
+
// }
|
124
129
|
|
125
130
|
// Create Ext.data.Record constructor specific for our particular column configuration
|
126
131
|
this.recordConfig = [];
|
@@ -196,9 +201,11 @@ module Netzke
|
|
196
201
|
// Original initComponent
|
197
202
|
Ext.netzke.cache.GridPanel.superclass.initComponent.call(this);
|
198
203
|
|
199
|
-
//
|
200
|
-
|
201
|
-
|
204
|
+
// Inform the server part about column operations
|
205
|
+
if (this.persistentConfig) {
|
206
|
+
this.on('columnresize', this.onColumnResize, this);
|
207
|
+
this.on('columnmove', this.onColumnMove, this);
|
208
|
+
}
|
202
209
|
|
203
210
|
// Context menu
|
204
211
|
if (this.enableContextMenu) {
|
@@ -246,7 +253,7 @@ module Netzke
|
|
246
253
|
def js_extend_properties
|
247
254
|
res = super
|
248
255
|
|
249
|
-
#
|
256
|
+
# Generic (non-optional) functionality
|
250
257
|
res.merge!(
|
251
258
|
{
|
252
259
|
:track_mouse_over => true,
|
@@ -257,6 +264,166 @@ module Netzke
|
|
257
264
|
|
258
265
|
:init_component => js_init_component.l,
|
259
266
|
|
267
|
+
# Handlers for actions
|
268
|
+
#
|
269
|
+
|
270
|
+
:on_add => <<-END_OF_JAVASCRIPT.l,
|
271
|
+
function(){
|
272
|
+
var rowConfig = {};
|
273
|
+
var r = new this.Row(rowConfig); // TODO: add default values
|
274
|
+
r.isNew = true; // to distinguish new records
|
275
|
+
r.set('id', r.id); // otherwise later r.get('id') returns empty string
|
276
|
+
this.stopEditing();
|
277
|
+
this.store.add(r);
|
278
|
+
this.tryStartEditing(this.store.indexOf(r));
|
279
|
+
}
|
280
|
+
END_OF_JAVASCRIPT
|
281
|
+
|
282
|
+
:on_edit => <<-END_OF_JAVASCRIPT.l,
|
283
|
+
function(){
|
284
|
+
var row = this.getSelectionModel().getSelected();
|
285
|
+
if (row){
|
286
|
+
this.tryStartEditing(this.store.indexOf(row));
|
287
|
+
}
|
288
|
+
}
|
289
|
+
END_OF_JAVASCRIPT
|
290
|
+
|
291
|
+
:on_del => <<-END_OF_JAVASCRIPT.l,
|
292
|
+
function() {
|
293
|
+
Ext.Msg.confirm('Confirm', 'Are you sure?', function(btn){
|
294
|
+
if (btn == 'yes') {
|
295
|
+
var records = [];
|
296
|
+
this.getSelectionModel().each(function(r){
|
297
|
+
if (r.isNew) {
|
298
|
+
// this record is not know to server - simply remove from store
|
299
|
+
this.store.remove(r);
|
300
|
+
} else {
|
301
|
+
records.push(r.get('id'));
|
302
|
+
}
|
303
|
+
}, this);
|
304
|
+
|
305
|
+
if (records.length > 0){
|
306
|
+
// call API
|
307
|
+
this.deleteData({records: Ext.encode(records)});
|
308
|
+
}
|
309
|
+
}
|
310
|
+
}, this);
|
311
|
+
}
|
312
|
+
END_OF_JAVASCRIPT
|
313
|
+
|
314
|
+
:on_apply => <<-END_OF_JAVASCRIPT.l,
|
315
|
+
function(){
|
316
|
+
var newRecords = [];
|
317
|
+
var updatedRecords = [];
|
318
|
+
|
319
|
+
Ext.each(this.store.getModifiedRecords(),
|
320
|
+
function(r) {
|
321
|
+
if (r.isNew) {
|
322
|
+
newRecords.push(Ext.apply(r.getChanges(), {id:r.get('id')}));
|
323
|
+
} else {
|
324
|
+
updatedRecords.push(Ext.apply(r.getChanges(), {id:r.get('id')}));
|
325
|
+
}
|
326
|
+
},
|
327
|
+
this);
|
328
|
+
|
329
|
+
if (newRecords.length > 0 || updatedRecords.length > 0) {
|
330
|
+
var params = {};
|
331
|
+
|
332
|
+
if (newRecords.length > 0) {
|
333
|
+
params.created_records = Ext.encode(newRecords);
|
334
|
+
}
|
335
|
+
|
336
|
+
if (updatedRecords.length > 0) {
|
337
|
+
params.updated_records = Ext.encode(updatedRecords);
|
338
|
+
}
|
339
|
+
|
340
|
+
if (this.store.baseParams !== {}) {
|
341
|
+
params.base_params = Ext.encode(this.store.baseParams);
|
342
|
+
}
|
343
|
+
|
344
|
+
this.postData(params);
|
345
|
+
}
|
346
|
+
|
347
|
+
}
|
348
|
+
END_OF_JAVASCRIPT
|
349
|
+
|
350
|
+
# Handlers for tools
|
351
|
+
#
|
352
|
+
|
353
|
+
:on_refresh => <<-END_OF_JAVASCRIPT.l,
|
354
|
+
function() {
|
355
|
+
if (this.fireEvent('refresh', this) !== false) {
|
356
|
+
this.store.reload();
|
357
|
+
}
|
358
|
+
}
|
359
|
+
END_OF_JAVASCRIPT
|
360
|
+
|
361
|
+
# Event handlers
|
362
|
+
#
|
363
|
+
|
364
|
+
:on_column_resize => <<-END_OF_JAVASCRIPT.l,
|
365
|
+
function(index, size){
|
366
|
+
this.resizeColumn({
|
367
|
+
index:index,
|
368
|
+
size:size
|
369
|
+
});
|
370
|
+
}
|
371
|
+
END_OF_JAVASCRIPT
|
372
|
+
|
373
|
+
:on_column_hidden_change => <<-END_OF_JAVASCRIPT.l,
|
374
|
+
function(cm, index, hidden){
|
375
|
+
this.hideColumn({
|
376
|
+
index:index,
|
377
|
+
hidden:hidden
|
378
|
+
});
|
379
|
+
}
|
380
|
+
END_OF_JAVASCRIPT
|
381
|
+
|
382
|
+
:on_column_move => <<-END_OF_JAVASCRIPT.l,
|
383
|
+
function(oldIndex, newIndex){
|
384
|
+
this.moveColumn({
|
385
|
+
old_index:oldIndex,
|
386
|
+
new_index:newIndex
|
387
|
+
});
|
388
|
+
|
389
|
+
var newRecordConfig = [];
|
390
|
+
Ext.each(this.getColumnModel().config, function(c){newRecordConfig.push({name: c.name})});
|
391
|
+
delete this.Row; // old record constructor
|
392
|
+
this.Row = Ext.data.Record.create(newRecordConfig);
|
393
|
+
this.getStore().reader.recordType = this.Row;
|
394
|
+
}
|
395
|
+
END_OF_JAVASCRIPT
|
396
|
+
|
397
|
+
:on_row_context_menu => <<-END_OF_JAVASCRIPT.l,
|
398
|
+
function(grid, rowIndex, e){
|
399
|
+
e.stopEvent();
|
400
|
+
var coords = e.getXY();
|
401
|
+
|
402
|
+
if (!grid.getSelectionModel().isSelected(rowIndex)) {
|
403
|
+
grid.getSelectionModel().selectRow(rowIndex);
|
404
|
+
}
|
405
|
+
|
406
|
+
var menu = new Ext.menu.Menu({
|
407
|
+
items: this.contextMenu
|
408
|
+
});
|
409
|
+
|
410
|
+
menu.showAt(coords);
|
411
|
+
}
|
412
|
+
END_OF_JAVASCRIPT
|
413
|
+
|
414
|
+
:on_after_row_move => <<-END_OF_JAVASCRIPT.l,
|
415
|
+
function(dt, oldIndex, newIndex, records){
|
416
|
+
var ids = [];
|
417
|
+
// collect records ids
|
418
|
+
Ext.each(records, function(r){ids.push(r.get('id'))});
|
419
|
+
// call GridPanel's API
|
420
|
+
this.moveRows({ids:Ext.encode(ids), new_index: newIndex});
|
421
|
+
}
|
422
|
+
END_OF_JAVASCRIPT
|
423
|
+
|
424
|
+
# Other methods
|
425
|
+
#
|
426
|
+
|
260
427
|
:load_exception_handler => <<-END_OF_JAVASCRIPT.l,
|
261
428
|
function(proxy, options, response, error){
|
262
429
|
if (response.status == 200 && (responseObject = Ext.decode(response.responseText)) && responseObject.flash){
|
@@ -285,63 +452,17 @@ module Netzke
|
|
285
452
|
}
|
286
453
|
END_OF_JAVASCRIPT
|
287
454
|
|
288
|
-
:add => <<-END_OF_JAVASCRIPT.l,
|
289
|
-
function(){
|
290
|
-
var rowConfig = {};
|
291
|
-
var r = new this.Row(rowConfig); // TODO: add default values
|
292
|
-
r.isNew = true; // to distinguish new records
|
293
|
-
r.set('id', r.id); // otherwise later r.get('id') returns empty string
|
294
|
-
this.stopEditing();
|
295
|
-
this.store.add(r);
|
296
|
-
this.tryStartEditing(this.store.indexOf(r));
|
297
|
-
}
|
298
|
-
END_OF_JAVASCRIPT
|
299
|
-
|
300
|
-
:edit => <<-END_OF_JAVASCRIPT.l,
|
301
|
-
function(){
|
302
|
-
var row = this.getSelectionModel().getSelected();
|
303
|
-
if (row){
|
304
|
-
this.tryStartEditing(this.store.indexOf(row));
|
305
|
-
}
|
306
|
-
}
|
307
|
-
END_OF_JAVASCRIPT
|
308
|
-
|
309
455
|
# try editing the first editable (i.e. not hidden, not read-only) sell
|
310
456
|
:try_start_editing => <<-END_OF_JAVASCRIPT.l,
|
311
457
|
function(row){
|
312
|
-
|
313
|
-
|
314
|
-
|
458
|
+
var editableIndex = 0;
|
459
|
+
Ext.each(this.getColumnModel().config, function(c){
|
460
|
+
if (!c.hidden && c.editor && (c.editor.xtype !== 'checkbox')) {
|
461
|
+
return false;
|
462
|
+
}
|
463
|
+
editableIndex++;
|
315
464
|
});
|
316
|
-
|
317
|
-
if (firstEditableColumn){
|
318
|
-
this.startEditing(row, firstEditableColumn.id);
|
319
|
-
}
|
320
|
-
}
|
321
|
-
END_OF_JAVASCRIPT
|
322
|
-
|
323
|
-
:del => <<-END_OF_JAVASCRIPT.l,
|
324
|
-
function() {
|
325
|
-
if (this.getSelectionModel().hasSelection()){
|
326
|
-
Ext.Msg.confirm('Confirm', 'Are you sure?', function(btn){
|
327
|
-
if (btn == 'yes') {
|
328
|
-
var records = [];
|
329
|
-
this.getSelectionModel().each(function(r){
|
330
|
-
if (r.isNew) {
|
331
|
-
// this record is not know to server - simply remove from store
|
332
|
-
this.store.remove(r);
|
333
|
-
} else {
|
334
|
-
records.push(r.get('id'));
|
335
|
-
}
|
336
|
-
}, this);
|
337
|
-
|
338
|
-
if (records.length > 0){
|
339
|
-
// call API
|
340
|
-
this.deleteData({records: Ext.encode(records)});
|
341
|
-
}
|
342
|
-
}
|
343
|
-
}, this);
|
344
|
-
}
|
465
|
+
if (editableIndex < this.getColumnModel().config.length) {this.startEditing(row, editableIndex);}
|
345
466
|
}
|
346
467
|
END_OF_JAVASCRIPT
|
347
468
|
|
@@ -417,42 +538,6 @@ module Netzke
|
|
417
538
|
}
|
418
539
|
END_OF_JAVASCRIPT
|
419
540
|
|
420
|
-
:apply => <<-END_OF_JAVASCRIPT.l,
|
421
|
-
function(){
|
422
|
-
var newRecords = [];
|
423
|
-
var updatedRecords = [];
|
424
|
-
|
425
|
-
Ext.each(this.store.getModifiedRecords(),
|
426
|
-
function(r) {
|
427
|
-
if (r.isNew) {
|
428
|
-
newRecords.push(Ext.apply(r.getChanges(), {id:r.get('id')}));
|
429
|
-
} else {
|
430
|
-
updatedRecords.push(Ext.apply(r.getChanges(), {id:r.get('id')}));
|
431
|
-
}
|
432
|
-
},
|
433
|
-
this);
|
434
|
-
|
435
|
-
if (newRecords.length > 0 || updatedRecords.length > 0) {
|
436
|
-
var params = {};
|
437
|
-
|
438
|
-
if (newRecords.length > 0) {
|
439
|
-
params.created_records = Ext.encode(newRecords);
|
440
|
-
}
|
441
|
-
|
442
|
-
if (updatedRecords.length > 0) {
|
443
|
-
params.updated_records = Ext.encode(updatedRecords);
|
444
|
-
}
|
445
|
-
|
446
|
-
if (this.store.baseParams !== {}) {
|
447
|
-
params.base_params = Ext.encode(this.store.baseParams);
|
448
|
-
}
|
449
|
-
|
450
|
-
this.postData(params);
|
451
|
-
}
|
452
|
-
|
453
|
-
}
|
454
|
-
END_OF_JAVASCRIPT
|
455
|
-
|
456
541
|
:select_first_row => <<-END_OF_JAVASCRIPT.l,
|
457
542
|
function(){
|
458
543
|
this.getSelectionModel().suspendEvents();
|
@@ -461,32 +546,6 @@ module Netzke
|
|
461
546
|
}
|
462
547
|
END_OF_JAVASCRIPT
|
463
548
|
|
464
|
-
:refresh => <<-END_OF_JAVASCRIPT.l,
|
465
|
-
function() {
|
466
|
-
if (this.fireEvent('refresh', this) !== false) {
|
467
|
-
this.store.reload();
|
468
|
-
}
|
469
|
-
}
|
470
|
-
END_OF_JAVASCRIPT
|
471
|
-
|
472
|
-
:on_column_resize => <<-END_OF_JAVASCRIPT.l,
|
473
|
-
function(index, size){
|
474
|
-
this.resizeColumn({
|
475
|
-
index:index,
|
476
|
-
size:size
|
477
|
-
});
|
478
|
-
}
|
479
|
-
END_OF_JAVASCRIPT
|
480
|
-
|
481
|
-
:on_column_hidden_change => <<-END_OF_JAVASCRIPT.l,
|
482
|
-
function(cm, index, hidden){
|
483
|
-
this.hideColumn({
|
484
|
-
index:index,
|
485
|
-
hidden:hidden
|
486
|
-
});
|
487
|
-
}
|
488
|
-
END_OF_JAVASCRIPT
|
489
|
-
|
490
549
|
# :reorder_columns => <<-END_OF_JAVASCRIPT.l,
|
491
550
|
# function(columns){
|
492
551
|
# columnsInNewShipment = [];
|
@@ -497,46 +556,10 @@ module Netzke
|
|
497
556
|
# this.store.reader.recordType = newRecordType; // yes, recordType is a protected property, but that's the only way we can do it, and it seems to work for now
|
498
557
|
# }
|
499
558
|
# END_OF_JAVASCRIPT
|
500
|
-
|
501
|
-
:on_column_move => <<-END_OF_JAVASCRIPT.l,
|
502
|
-
function(oldIndex, newIndex){
|
503
|
-
this.moveColumn({
|
504
|
-
old_index:oldIndex,
|
505
|
-
new_index:newIndex
|
506
|
-
});
|
507
|
-
}
|
508
|
-
END_OF_JAVASCRIPT
|
509
|
-
|
510
|
-
:on_row_context_menu => <<-END_OF_JAVASCRIPT.l,
|
511
|
-
function(grid, rowIndex, e){
|
512
|
-
e.stopEvent();
|
513
|
-
var coords = e.getXY();
|
514
|
-
|
515
|
-
if (!grid.getSelectionModel().isSelected(rowIndex)) {
|
516
|
-
grid.getSelectionModel().selectRow(rowIndex);
|
517
|
-
}
|
518
|
-
|
519
|
-
var menu = new Ext.menu.Menu({
|
520
|
-
items: this.contextMenu
|
521
|
-
});
|
522
|
-
|
523
|
-
menu.showAt(coords);
|
524
|
-
}
|
525
|
-
END_OF_JAVASCRIPT
|
526
|
-
|
527
|
-
:on_after_row_move => <<-END_OF_JAVASCRIPT.l,
|
528
|
-
function(dt, oldIndex, newIndex, records){
|
529
|
-
var ids = [];
|
530
|
-
// collect records ids
|
531
|
-
Ext.each(records, function(r){ids.push(r.get('id'))});
|
532
|
-
// call GridPanel's API
|
533
|
-
this.moveRows({ids:Ext.encode(ids), new_index: newIndex});
|
534
|
-
}
|
535
|
-
END_OF_JAVASCRIPT
|
536
559
|
}
|
537
560
|
)
|
538
561
|
|
539
|
-
#
|
562
|
+
# Optional edit in form functionality
|
540
563
|
res.merge!(
|
541
564
|
{
|
542
565
|
:on_successfull_record_creation => <<-END_OF_JAVASCRIPT.l,
|
@@ -554,7 +577,7 @@ module Netzke
|
|
554
577
|
}
|
555
578
|
END_OF_JAVASCRIPT
|
556
579
|
|
557
|
-
:
|
580
|
+
:on_edit_in_form => <<-END_OF_JAVASCRIPT.l,
|
558
581
|
function(){
|
559
582
|
// create the window
|
560
583
|
delete this.editFormWindow;
|
@@ -567,12 +590,12 @@ module Netzke
|
|
567
590
|
buttons:[{
|
568
591
|
text: 'OK',
|
569
592
|
handler: function(){
|
570
|
-
this.ownerCt.getWidget().
|
593
|
+
this.ownerCt.ownerCt.getWidget().onApply();
|
571
594
|
}
|
572
595
|
},{
|
573
596
|
text:'Cancel',
|
574
597
|
handler:function(){
|
575
|
-
this.ownerCt.close();
|
598
|
+
this.ownerCt.ownerCt.close();
|
576
599
|
}
|
577
600
|
}]
|
578
601
|
});
|
@@ -617,7 +640,7 @@ module Netzke
|
|
617
640
|
}
|
618
641
|
END_OF_JAVASCRIPT
|
619
642
|
|
620
|
-
:
|
643
|
+
:on_add_in_form => <<-END_OF_JAVASCRIPT.l,
|
621
644
|
function(){
|
622
645
|
if (!this.formWindow) {
|
623
646
|
this.formWindow = new Ext.Window({
|
@@ -630,12 +653,12 @@ module Netzke
|
|
630
653
|
buttons:[{
|
631
654
|
text: 'OK',
|
632
655
|
handler: function(){
|
633
|
-
this.ownerCt.getWidget().
|
656
|
+
this.ownerCt.ownerCt.getWidget().onApply();
|
634
657
|
}
|
635
658
|
},{
|
636
659
|
text:'Cancel',
|
637
660
|
handler:function(){
|
638
|
-
this.ownerCt.close();
|
661
|
+
this.ownerCt.ownerCt.close();
|
639
662
|
}
|
640
663
|
}]
|
641
664
|
});
|
@@ -654,10 +677,10 @@ module Netzke
|
|
654
677
|
}
|
655
678
|
) if config[:edit_in_form_available]
|
656
679
|
|
657
|
-
#
|
680
|
+
# Optional extended search functionality
|
658
681
|
res.merge!(
|
659
682
|
{
|
660
|
-
:
|
683
|
+
:on_search => <<-END_OF_JAVASCRIPT.l,
|
661
684
|
function(){
|
662
685
|
if (!this.searchWindow){
|
663
686
|
this.searchWindow = new Ext.Window({
|
@@ -670,12 +693,12 @@ module Netzke
|
|
670
693
|
buttons:[{
|
671
694
|
text: 'OK',
|
672
695
|
handler: function(){
|
673
|
-
this.ownerCt.closePositively();
|
696
|
+
this.ownerCt.ownerCt.closePositively();
|
674
697
|
}
|
675
698
|
},{
|
676
699
|
text:'Cancel',
|
677
700
|
handler:function(){
|
678
|
-
this.ownerCt.closeNegatively();
|
701
|
+
this.ownerCt.ownerCt.closeNegatively();
|
679
702
|
}
|
680
703
|
}],
|
681
704
|
closePositively : function(){
|