forked from kyr0/extjs4spreadsheet-gpl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspread-all-debug.js
6293 lines (5114 loc) · 188 KB
/
spread-all-debug.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* @class Spread.overrides.Column
* @overrides Ext.grid.column.Column
* Overrides to the standard gird column to implement spreadsheet-specific features.
*/
Ext.define('Spread.overrides.Column', {
'override': 'Ext.grid.column.Column',
initialPanelEditModeStyling: false,
/**
* @cfg {Boolean} selectable
* If a column is configured as header column, the values aren't selectable nor focusable
*/
selectable: true,
/**
* @cfg {Boolean} editable
* If the column is editable, the edit fields gets active on key type-in or double-clicking
*/
editable: true,
/**
* @cfg {Boolean} autoCommit
* Auto-commit cell data changes on record automatically
* (otherwise the data change indicator will be shown and record needs to be commit()'ed manually!
*/
autoCommit: false,
/**
* @cfg {Function} cellwriter
* Pre-processor function for cell data write operations - if you want to modify cell data before record update.
* (e.g. when edit field gets blur()'ed and updates the record AND when selection paste (ctrl+v) happens,
* this function gets called, when it's defined. The return value of this function will be used as new data value.
*/
cellwriter: null,
/**
* @cfg {Function} cellreader
* Pre-processor function for cell read operations - if you want to modify cell data while reading from record.
* (e.g. when edit field gets active and loads cell data AND when selection copy (ctrl+c) happens,
* this function gets called, when it's defined. The return value of this function will be used.
*/
cellreader: null,
/**
* @cfg {Boolean} editModeStyling
* If you enable special styles for editable columns they will
* be displayed with a special background color and selection color.
*/
editModeStyling: true,
/**
* @cfg {Array} allowedEditKeys
* Specifies the allowed keys so that only these keys can be typed into the edit field
*/
allowedEditKeys: [],
// private
initComponent: function() {
// Handle UI stuff
this.initDynamicColumnTdCls();
// Call parent
this.callParent(arguments);
},
/**
* @private
* Handles cell <td> addition of CSS classes
* @return void
*/
initDynamicColumnTdCls: function() {
if (!this.selectable) {
// If not selectable, then editing is impossible
this.editable = false;
// Add unselectable class
this.tdCls = 'spreadsheet-cell-unselectable';
}
// Check for editable flag and for edit mode styling
if (this.editable && this.editModeStyling &&
this.initialPanelEditModeStyling) {
// Add editable class
this.tdCls += ' ' + 'spreadsheet-cell-editable';
}
}
});
/**
* @class Spread.command.Commander
*
* Class that implements a public command API for a more
* simple and interactive use of the spreads internal features.
* TODO: Check for out-of-bounds errors!
*/
Ext.define('Spread.command.Commander', {
/**
* @protected
* @property {Spread.grid.Panel} spreadPanel Spread panel reference
*/
spreadPanel: null,
// private
constructor: function(config) {
Ext.apply(this, config);
},
/**
* Simply redraws the edit mode styling.
* Call this method if you have changed some
* row/position/column edit mode styling settings using this API.
* @return void
*/
redrawEditModeStyling: function() {
var speadView = spreadPanel.getView();
speadView.editable.displayCellsEditing(speadView.editable.editModeStyling);
},
/**
* Returns a position to work on
* @param {Number} columnIndex Column index
* @param {Number} rowIndex Row index
* @return {Spread.selection.Position}
*/
getPosition: function(columnIndex, rowIndex) {
return new Spread.selection.Position(
this.spreadPanel.getView(),
columnIndex,
rowIndex
).validate();
},
/**
* Returns a range of positions of a row
* @param {Number} rowIndex Row's index
* @return {Spread.selection.Range}
*/
getRowRange: function(rowIndex) {
return Spread.selection.Range.fromSpreadRows(this.spreadPanel, [rowIndex]);
},
/**
* Returns a range of positions of many rows
* @param {Array} rowIndexes Row indexes e.g. [1, 2]
* @return {Spread.selection.Range}
*/
getRowsRange: function(rowIndexes) {
return Spread.selection.Range.fromSpreadRows(this.spreadPanel, rowIndexes);
},
/**
* Returns a range of positions of a column
* @param {Number} columnIndex Column's index
* @return {Spread.selection.Range}
*/
getColumnRange: function(columnIndex) {
return Spread.selection.Range.fromSpreadColumns(this.spreadPanel, [columnIndex]);
},
/**
* Returns a range of positions of many column
* @param {Array} columnIndexes Column indexes e.g. [1, 2]
* @return {Spread.selection.Range}
*/
getColumnsRange: function(columnIndexes) {
return Spread.selection.Range.fromSpreadColumns(this.spreadPanel, columnIndexes);
},
/**
* Selects a range of positions named by indexes
* @param {Number} positionIndexes Position indexes array like [{row: 0, column: 2}, ...]
* @param {Boolean} [virtual=false] Virtual selections do not update the view visually
* @return {Spread.command.Commander}
*/
select: function(positionIndexes, virtual) {
Spread.selection.Range.fromSpreadPositions(this.spreadPanel, positionIndexes).select(virtual);
return this;
},
/**
* Selects a row named by it's row index
* @param {Number} rowIndex Row to select
* @param {Boolean} [virtual=false] Virtual selections do not update the view visually
* @return {Spread.command.Commander}
*/
selectRow: function(rowIndex, virtual) {
return this.selectRows([rowIndex], virtual);
},
/**
* Selects rows named by it's row indexes
* @param {Array} rowIndexes Row indexes to select, e.g. [0, 1, 2]
* @param {Boolean} [virtual=false] Virtual selections do not update the view visually
* @return {Spread.command.Commander}
*/
selectRows: function(rowIndexes, virtual) {
Spread.selection.Range.fromSpreadRows(this.spreadPanel, rowIndexes).select(virtual);
return this;
},
/**
* Selects a column named by it's column index
* @param {Number} columnIndex Column to select
* @param {Boolean} [virtual=false] Virtual selections do not update the view visually
* @return {Spread.command.Commander}
*/
selectColumn: function(columnIndex, virtual) {
return this.selectColumns([columnIndex], virtual);
},
/**
* Selects columns named by it's column indexes
* @param {Array} columnIndexes Columns to select, e.g. [2, 3, 4]
* @param {Boolean} [virtual=false] Virtual selections do not update the view visually
* @return {Spread.command.Commander}
*/
selectColumns: function(columnIndexes, virtual) {
Spread.selection.Range.fromSpreadColumns(this.spreadPanel, columnIndexes).select(virtual);
return this;
},
/**
* De-Selects a range of positions named by indexes
* @param {Number} positionIndexes Position indexes array like [{row: 0, column: 2}, ...]
* @param {Boolean} [virtual=false] Virtual selections do not update the view visually
* @return {Spread.command.Commander}
*/
deselect: function(positionIndexes, virtual) {
Spread.selection.Range.fromSpreadPositions(this.spreadPanel, positionIndexes).deselect(virtual);
return this;
},
/**
* De-Selects a row named by it's row index
* @param {Number} rowIndex Row to select
* @param {Boolean} [virtual=false] Virtual selections do not update the view visually
* @return {Spread.command.Commander}
*/
deselectRow: function(rowIndex, virtual) {
return this.deselectRows([rowIndex], virtual);
},
/**
* De-Selects rows named by it's row indexes
* @param {Array} rowIndexes Row indexes to select, e.g. [0, 1, 2]
* @param {Boolean} [virtual=false] Virtual selections do not update the view visually
* @return {Spread.command.Commander}
*/
deselectRows: function(rowIndexes, virtual) {
Spread.selection.Range.fromSpreadRows(this.spreadPanel, rowIndexes).deselect(virtual);
return this;
},
/**
* De-Selects a column named by it's column index
* @param {Number} columnIndex Column to select
* @param {Boolean} [virtual=false] Virtual selections do not update the view visually
* @return {Spread.command.Commander}
*/
deselectColumn: function(columnIndex, virtual) {
return this.deselectColumns([columnIndex], virtual);
},
/**
* De-Selects columns named by it's column indexes
* @param {Array} columnIndexes Columns to select, e.g. [2, 3, 4]
* @param {Boolean} [virtual=false] Virtual selections do not update the view visually
* @return {Spread.command.Commander}
*/
deselectColumns: function(columnIndexes, virtual) {
Spread.selection.Range.fromSpreadColumns(this.spreadPanel, columnIndexes).deselect(virtual);
return this;
},
/**
* Focuses the named cell
* @param {Number} columnIndex Cell index
* @param {Number} rowIndex Row index
* @return {Spread.command.Commander}
*/
focusPosition: function(columnIndex, rowIndex) {
new Spread.selection.Position(
this.spreadPanel.getView(),
columnIndex,
rowIndex
).validate().focus();
},
/**
* Focuses & Starts editing a position
* @param {Number} columnIndex Cell index
* @param {Number} rowIndex Row index
* @param {Boolean} [noAutoFocus] Do not automatically focus the cell before starting edit mode
* @return {Spread.command.Commander}
*/
startEditPosition: function(columnIndex, rowIndex, noAutoFocus) {
if (!Ext.isDefined(noAutoFocus)) {
// Focus position
this.focusPosition(columnIndex, rowIndex);
}
new Spread.selection.Position(
this.spreadPanel.getView(),
columnIndex,
rowIndex
).validate().setEditing(true);
return this;
},
/**
* Stops editing a position
* @param {Number} columnIndex Cell index
* @param {Number} rowIndex Row index
* @return {Spread.command.Commander}
*/
stopEditPosition: function(columnIndex, rowIndex) {
new Spread.selection.Position(
this.spreadPanel.getView(),
columnIndex,
rowIndex
).validate().setEditing(false);
return this;
},
/**
* En/disable edit mode styling for positions
* @param {Number} positionIndexes Position indexes array like [{row: 0, column: 2}, ...]
* @param {Boolean} editModeStyling Activates/Deactivates edit mode styling
* @return {Spread.command.Commander}
*/
setEditModeStyling: function(positionIndexes, editModeStyling) {
Spread.selection.Range.fromSpreadPositions(this.spreadPanel, positionIndexes).setEditModeStyling(editModeStyling);
return this;
},
/**
* Sets the edit mode styling for a row
* @param {Number} rowIndex Row index to set edit mode styling for
* @param {Boolean} editModeStyling Activates/Deactivates edit mode styling
* @return {Spread.command.Commander}
*/
setRowEditModeStyling: function(rowIndex, editModeStyling) {
return this.setRowsEditModeStyling([rowIndex], editModeStyling);
},
/**
* Sets the edit mode styling for many rows
* @param {Array} rowIndexes Row indexes to set edit mode styling for
* @param {Boolean} editModeStyling Activates/Deactivates edit mode styling
* @return {Spread.command.Commander}
*/
setRowsEditModeStyling: function(rowIndexes, editModeStyling) {
Spread.selection.Range.fromSpreadRows(this.spreadPanel, rowIndexes).setEditModeStyling(editModeStyling);
return this;
},
/**
* Sets the edit mode styling for a column
* @param {Number} columnIndex Column index to set edit mode styling for
* @param {Boolean} editModeStyling Activates/Deactivates edit mode styling
* @return {Spread.command.Commander}
*/
setColumnEditModeStyling: function(columnIndex, editModeStyling) {
return this.setColumnsEditModeStyling([columnIndex], editModeStyling);
},
/**
* Sets the edit mode styling for many columns
* @param {Array} columnIndexes Column indexes to set edit mode styling for
* @param {Boolean} editModeStyling Activates/Deactivates edit mode styling
* @return {Spread.command.Commander}
*/
setColumnsEditModeStyling: function(columnIndexes, editModeStyling) {
Spread.selection.Range.fromSpreadColumns(this.spreadPanel, columnIndexes).setEditModeStyling(editModeStyling);
return this;
},
/**
* Sets the position editable
* @param {Number} columnIndex Cell index
* @param {Number} rowIndex Row index
* @param {Boolean} editable Shall the position be editable or not?
* @return {Spread.command.Commander}
*/
setPositionEditable: function(columnIndex, rowIndex, editable) {
new Spread.selection.Position(
this.spreadPanel.getView(),
columnIndex,
rowIndex
).validate().setEditable(editable);
return this;
},
/**
* Sets positions editable
* @param {Number} positionIndexes Position indexes array like [{row: 0, column: 2}, ...]
* @param {Boolean} editable Shall the position be editable or not?
* @return {Spread.command.Commander}
*/
setEditable: function(positionIndexes, editable) {
Spread.selection.Range.fromSpreadPositions(this.spreadPanel, positionIndexes).setEditable(editable);
return this;
},
/**
* Sets the row editable or not
* @param {Number} rowIndex Row index to allow editing for
* @param {Boolean} editable Activates/Deactivates edit mode
* @return {Spread.command.Commander}
*/
setRowEditable: function(rowIndex, editable) {
this.setRowsEditable([rowIndex], editable);
return this;
},
/**
* Sets many rows editable or not
* @param {Array} rowIndexes Row indexes to allow editing for
* @param {Boolean} editable Shall these rows editable or not?
* @return {Spread.command.Commander}
*/
setRowsEditable: function(rowIndexes, editable) {
Spread.selection.Range.fromSpreadRows(this.spreadPanel, rowIndexes).setEditable(editable);
return this;
},
/**
* Sets the column editable or not
* @param {Number} columnIndex Column index to set edit mode styling for
* @param {Boolean} editable Activates/Deactivates edit mode
* @return {Spread.command.Commander}
*/
setColumnEditable: function(columnIndex, editable) {
this.setColumnsEditable([columnIndex], editable);
return this;
},
/**
* Sets many columns editable or not
* @param {Array} columnIndexes Row indexes to allow editing for
* @param {Boolean} editable Shall these columns be editable or not?
* @return {Spread.command.Commander}
*/
setColumnsEditable: function(columnIndexes, editable) {
Spread.selection.Range.fromSpreadColumns(this.spreadPanel, columnIndexes).setEditable(editable);
return this;
},
/**
* Sets the position selectable
* @param {Number} columnIndex Cell index
* @param {Number} rowIndex Row index
* @param {Boolean} selectable Shall the position be selectable or not?
* @return {Spread.command.Commander}
*/
setPositionSelectable: function(columnIndex, rowIndex, selectable) {
new Spread.selection.Position(
this.spreadPanel.getView(),
columnIndex,
rowIndex
).validate().setSelectable(selectable);
return this;
},
/**
* Sets positions selectable
* @param {Number} positionIndexes Position indexes array like [{row: 0, column: 2}, ...]
* @param {Boolean} selectable Shall the position be selectable or not?
* @return {Spread.command.Commander}
*/
setSelectable: function(positionIndexes, selectable) {
Spread.selection.Range.fromSpreadPositions(this.spreadPanel, positionIndexes).setSelectable(selectable);
return this;
},
/**
* Sets the row selectable or not
* @param {Number} rowIndex Row index to set edit mode styling for
* @param {Boolean} selectable Shall the row be selectable or not?
* @return {Spread.command.Commander}
*/
setRowSelectable: function(rowIndex, selectable) {
this.setRowsSelectable([rowIndex], selectable);
return this;
},
/**
* Sets many rows selectable or not
* @param {Array} rowIndexes Row indexes to allow selecting for
* @param {Boolean} selectable Shall these rows selectable or not?
* @return {Spread.command.Commander}
*/
setRowsSelectable: function(rowIndexes, selectable) {
Spread.selection.Range.fromSpreadRows(this.spreadPanel, rowIndexes).setSelectable(selectable);
return this;
},
/**
* Sets the column selectable or not
* @param {Number} columnIndex Row index to set edit mode styling for
* @param {Boolean} selectable Shall this column be selectable or not?
* @return {Spread.command.Commander}
*/
setColumnSelectable: function(columnIndex, selectable) {
this.setColumnsSelectable([columnIndex], selectable);
return this;
},
/**
* Sets many column selectable or not
* @param {Array} columnIndexes Row indexes to allow selecting for
* @param {Boolean} selectable Shall these rows selectable or not?
* @return {Spread.command.Commander}
*/
setColumnsSelectable: function(columnIndexes, selectable) {
Spread.selection.Range.fromSpreadColumns(this.spreadPanel, columnIndexes).setSelectable(selectable);
return this;
}
});
/**
* @class Spread.grid.Panel
* @extends Ext.grid.Panel
*
* # Ext JS 4 SpreadSheet panels
*
* The grid panel class ist the most important class of Ext JS 4 Spreadsheet component.
* You can configure all features of a Spreadsheet through the configuration of an instance of Spread.grid.Panel.
*
* ## A Simple Spreadsheet
*
* A very simple Spreadsheet example is:
*
* <code>
* // Creating an instance of the Spreadsheet's grid panel
* var spreadPanel = new Spread.grid.Panel({
// Like all grids, a Spreadsheet grid also needs a store
store: dataStore,
// Configure visible grid columns
columns: [{
header: 'First name',
dataIndex: 'firstname',
// Lets disable selection for first column
selectable: false
}, {
header: 'Last name',
renderer: function(value) {
return '<b>' + value + '</b>';
},
dataIndex: 'lastname'
}]
});
* </code>
*
* ## Anatomy of a Spreadsheet
*
* A Spreadsheet itself consists of three main classes:
* <ul>
* <li>
* <u>The Panel:</u> <code>Spread.grid.Panel</code><br />
* <br />
* This is the master class of a Spreadsheet. All configuration belongs to this class.
* Except the View class, you don't need to know about the internals of the other classes
* nor their config options and events because every config option and every event is
* relayed to the grid panel class itself.<br />
* <br />
* Note: After instantiation of a grid, it's possible to access the View and Selection Model instances
* by calling <code>gridPanelInstance.getView()</code> and <code>gridPanelInstance.getSelectionModel()</code>.
* <br />
* <br />
* xtype: <code>spread</code>
* <br />
* <br />
* </li>
* <li>
* <u>The View:</u> <code>Spread.grid.View</code><br />
* <br />
* The view class extends a standard Ext.grid.View. It implements method to renders all spreadsheet-specific UI
* elements. It also handles all UI specific events for focusing and selecting cells.
*
* The view of a Spreadsheet comes with it's own plugin architecture.
* Features like Spread.grid.plugin.Editable, Spread.grid.plugin.Copyable and Spread.grid.plugin.Pasteable
* are loosely coupled with the view instance itself. By default, you never need to care about them, because:
* <br />
* - All config options of the grid view are available via the grid panel's <code>viewConfig</code> object too<br />
* - All view class events are available through the grid panel class too
* <br />
* <br />
* xtype: <code>spreadview</code>
* <br />
* <br />
* </li>
* <li>
* <u>The Selection Model:</u> <code>Spread.selection.RangeModel</code><br />
* <br />
* The selection model implements all the logic (key/mouse navigation, key/mouse selection) required for
* making focusing and selection feels like using a native spreadsheet application.
*
* By default, you never need to care about the selection model, because:<br />
* - All config options of this selection model are available through on the grid panel class too<br />
* - All selecton model events are available on the grid panel class too
* <br />
* <br />
* xtype: <code>range</code>
* <br />
* <br />
* </li>
* </ul>
*
* ## Grid view customization
*
* Like in any standard Ext JS grid you can customize the configuration of the grid's view using the <code>viewConfig</code>
* configuration option:
*
* <code>
...
// A config, relayed to Spread.grid.View.
// Shows
viewConfig: {
stripeRows: true
},
...
</code>
*
* ## Using the special header column <code>Spread.grid.column.Header</code>
*
* Next to all standard grid columns you can configure a spreadsheet to contain one or more spreadsheet header columns.
* Header columns are non-selectable and non-editable and belong to the dataIndex 'id' by default.
*
* Like any other grid column, add the spreadheadercolumn instance configuration(s) to the Grid panel's column-configuration:
*
* <code>
...
columns: [{
xtype: 'spreadheadercolumn',
header: 'ID',
dataIndex: 'id' // default value
}, ...],
...
</code>
*
* <br />
*
* xtype: <code>spreadheadercolumn</code>
*
* ## Customizing grid cell selection: <code>Spread.selection.RangeModel</code>
*
* The special Range Selection Model that comes with Ext JS 4 SpreadSheet is the heart of the SpreadSheet implementation.
* It implements the logic behind the native-like feeling when using the SpreadSheet grid. There are two configurations
* possible then configuring the selection model:
*
* <ul>
* <li><code>autoFocusRootPosition</code> (default: true) – Automatically focuses the top- and -left-most cell which is selectable after view rendering</li>
* <li><code>enableKeyNav</code> (default: true) – En-/disabled the navigation using arrow keys, shift key + arrow keys</li>
* </ul>
*
* You can simply set these both options on the grid panel instance.
*
* ### Disabling selection of cells of specific columns
*
* If you'd like to disable the cells of a column from being selected by the user, just set the <code>selectable</code> flag to <code>false</code>.
*
<code>
...
columns: [{
header: 'Firstname',
dataIndex: 'firstname',
selectable: false,
...
}, ...],
...
</code>
*
* <strong>Note: Instead of header columns, all columns in a spreadsheet grid are selectable by because of <code>Spread.grid.overrides.Column</code>.</strong>
*
* <br />
*
* xtype: <code>range</code>
*
* ## Editing of cells data using <code>Spread.grid.plugin.Editing</code>
*
* Cells of Ext JS 4 SpreadSheet can be edited like a standard Ext JS 4 grid. To gain a look and feel like using a
* native spreadsheet application, there is a special plaintext editor getting active when start typing or double-clicking
* on a grid cell. <strong>There is currently no support for Ext JS editor fields</strong> for the gain of being consistent
* with the native spreadsheet look & feel.
*
* ### En-/disabling grid cell editing of the whole grid
*
* You can enable or disable grid editing on configuration time by setting the <code>editable</code> config option:
*
* <code>
...
editable: false,
...
</code>
*
* After instantiation (at runtime), you can access the SpreadSheet grid panel instance (e.g. using <code>Ext.getCmp(...)</code>)
* and call the method <code>setEditable((Boolean) isEditable)</code> to en-/disable editing at runtime:
*
* <code>
Ext.getCmp('$gridPanelId').setEditable(false);
</code>
*
* <strong>Note: Disabling editing mode globally means that editing gets disabled on all columns, ignoring what you
* configured for the columns before. Enabling edit mode globally means that editing gets enabled only on those
* columns, editing was enabled by configuration.</strong>
*
* ### Disabling editing of cells of specific columns
*
* If you'd like to disable editing of cell data for a column, just set the <code>editable</code> flag to <code>false</code>.
*
<code>
...
columns: [{
header: 'Firstname',
dataIndex: 'firstname',
editable: false,
...
}, ...],
...
</code>
*
* <strong>Note: Instead of header columns, all columns in a spreadsheet grid are editable by default because of <code>Spread.grid.overrides.Column</code>.</strong>
*
* ### Colorization of editable cells
*
* Ext JS 4 SpreadSheet has a special feature to colorize the cell background of cells, which are editable.
* By default this color is light yellow (see "Special Styling (CSS)" section if you'd like to change this).
* You can en-/disable this feature by setting the <code>enableEditModeStyling</code> config
* option in grid panel configuration:
*
* <code>
...
enableEditModeStyling: true, // default value
...
</code>
*
* <strong>Note that <code>editModeStyling</code> can cause problems when using special cell background colors.</strong>
*
* ### Advanced editing configuration
*
* The editing plugin features several configuration options. If you'd like to change the editing behaviour, instantiate
* the grid panel with <strong>a configured instance</strong> of <code>Spread.grid.plugin.Editing</code> like shown below:
*
* <code>
...
editablePluginInstance: Ext.create('Spread.grid.plugin.Editable', {
editModeStyling: false, // disallows edit mode styling even if activated on columns
...
}),
...
</code>
*
* ## Cell data pre-processor functions
*
* Every column in a spreadsheet grid panel can be configured to use a custom getter and setter function
* to read data from the record to be displayed or copied (reader function) or to pre-process pasted data
* or edited values before getting written to a data record (writer function).
*
* ### Column based cell reader function
*
* Registering a cell data reader hook is easy. Simply set the <code>cellreader</code> property to a function:
*
* <code>
...
columns: [{
header: 'Firstname',
dataIndex: 'firstname',
cellreader: function(value, position) {
// transform cell data value here...
return value;
}
...
}, ...],
...
</code>
*
* As you can see, the reader function gets called with two arguments:
*
* <ul>
* <li> <code>value</code> – The data value read from cell data record field</li>
* <li> <code>position Spread.selection.Position</code> – The cell's position</li>
* </ul>
*
* <strong>The return value will be used for rendering cell data, value to be used in cell editor, copying cell data.</strong>
*
* ### Column based cell writer function
*
* If you configure a <code>cellwriter</code>-function for a column, the data which gets pasted or
* submitted after leaving the edit mode (the text input field) of a cell, will be processed by this function.
*
* The first argument contains the new value (String). The second argument holds a reference to the current
* focused cell position (Spread.selection.Position). The value you return in the <code>cellwriter</code> function
* is the value which gets written onto the data record.
*
* Simply set the <code>cellwriter</code> property to a function:
*
* <code>
...
columns: [{
header: 'Firstname',
dataIndex: 'firstname',
cellwriter: function(newValue, position) {
// pre-process new cell data value here before it's getting written to the data record...
return newValue;
}
...
}, ...],
...
</code>
*
* Attention: If you DONT SET a cellwriter, the spreadsheet tries to automatically cast the datatype
* of the incoming new value (String) into the data type defined in the model (type) - e.g. int -> parseInt,
* float -> parseFloat and so on. If you do not set a data type in the model or set the
* data type to 'auto' String values will be stored. Have a look at Spread.selection.Position#setValue for details.
*
* As you can see, the writer function gets called with two arguments:
*
* <ul>
* <li> <code>newValue</code> – The data value to be written to the cell data record field</li>
* <li> <code>position Spread.selection.Position</code> – The cell's position</li>
* </ul>
*
* <strong>The return value will be used to be written to the data record.
* The new value may be supplied by pasting data into the cell or field editor.</strong>
*
* ## Auto-Committing of cell data on edit/paste
*
* When cell data gets changed by editing or pasting data the underlaying grid row's store record can be automatically
* changed when auto-committing is enabled on the column and the grid panel. This prevents the red arrow dirty marker
* from being displayed.
*
* Auto-committing of cell data is disabled by default on the grid panel but enabled on each grid column by default.
* This means that you can enable auto-committing easily and globally by setting the <code>autoCommit</code> config
* option to <code>true</code> on the grid panel instance:
*
* <code>
...,
autoCommit: true,
...
</code>
*
* ### Disabling auto committing for specific columns
*
* To disable auto committing of cell data on the cells of specific columns simply set the <code>autoCommit</code> config
* option of a grid column to <code>false</code>:
*
* <code>
...,
columns: [{
header: 'Lastname',
dataIndex: 'lastname',
autoCommit: false
}, ...],
...
</code>
*
* ## Advanced: Event capturing
*
* In some special cases you may want to capture spreadsheet grid events to execute custom application code when needed.
* E.g. you want to execute special logic when a cell gets covered (selection of a cell happened and covering view element
* has been rendered and placed over the specific cell).
*
* For such purpose you may simply add an event listener to the specific grid event using the <code>listeners</code>
* configuration option, bind an event handler to the instance using Ext.getCmp(...).on('covercell', function() {...})
* or use the MVC's controller infrastructure to select a component and bind it's events:
*
<code>
...
listeners: {
// Simple listening to a View's event (relayed)
covercell: function() {
console.log('External listener to covercell', arguments);
}
},
...
</code>
*
* <strong> Note that any special spreadsheet event fired by sub-components of the grid panel: the grid's view,
* editable, pasteable and copyable plugin get relayed to the grid panel itself. So you don't need to care about these
* sub-component instances for event handling.
*
* To capture selection model events, call <code>grid.getSelectionModel().on('$selectionModelEventName', function() {...})</code>.
* </strong>
*
* ## Advanced: Custom styling
*
* Customizing the look of the spreadsheet grid can be accomplished by changing configuration options of the <code>viewConfig</code>
* configuration option (see above). But if that doesn't help you may want to override CSS rules to e.g. change the color of the
* background color when <code>editModeStyling</code> is enabled. Therefore you would just need to include your own
* CSS stylesheet file or append a <code>style</code>-tag to the <code>head</code>-section of your web page containing something like this:
*
* <code>
.x-grid-row .spreadsheet-cell-editable .x-grid-cell-inner {
background-color: #cfffff;
}
.x-grid-row .spreadsheet-cell-editable-dirty .x-grid-cell-inner {
background-color: #cfffff;
background-image: url("dirty.gif");
background-position: 0 0;
background-repeat: no-repeat;
}
</code>
*
* <strong>Just copy and paste the CSS selectors of resources/spread.css to change the style of your spreadsheet grid.
* Ensure to prepend your own styling rules.</strong>
*
* ## Advanced: Special copy & paste behaviour customization
*
* For fine tuning and in special cases you may want to change the default configuration of the pasteable and copyable
* plugins of the spreadsheet grid panel. Thanks to the dependency injection architecture of the spreadsheet grid
* implementation you can simply create your own plugin instance and inject it into the spreadsheet grid panel instance
* configuration:
*
* <code>
...
copyablePluginInstance: Ext.create('Spread.grid.plugin.Copyable', {
// Overriding a method on instance level to change the keystroke for copying.
// Using this it's CTRL+O instead of C but only for this instance of the spreadsheet gird.
detectCopyKeyStroke: function(evt) {
if (evt.getKey() === evt.O && evt.ctrlKey) {
this.copyToClipboard();
}
},
...
}),
pasteablePluginInstance: Ext.create('Spread.grid.plugin.Pasteable', {
useInternalAPIs: true, // Enabling an experimental feature, much faster but dangerous
...
}),
...
</code>
*/
Ext.define('Spread.grid.Panel', {
'extend': Ext.grid.Panel ,
'alias': 'widget.spread',
viewType: 'spreadview',
closeAction: 'destroy',
pluginRegistry: {},
columnLines: true,
/**
* @cfg {Boolean} autoFocusRootPosition
* Automatically focuses the root position initially
*/
autoFocusRootPosition: true,
/**
* @cfg {Boolean} enableKeyNav
* Turns on/off keyboard navigation within the grid.
*/
enableKeyNav: true,
/**
* @cfg {Boolean} editable
* Configures if the grid is in edit mode initially