neo.mjs 8.0.0 → 8.1.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.
- package/apps/ServiceWorker.mjs +2 -2
- package/apps/portal/index.html +1 -1
- package/apps/portal/view/about/Container.mjs +0 -2
- package/apps/portal/view/about/MemberContainer.mjs +1 -20
- package/apps/portal/view/home/FooterContainer.mjs +1 -5
- package/examples/ConfigurationViewport.mjs +37 -32
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/grid/cellEditing/MainContainer.mjs +175 -0
- package/examples/grid/cellEditing/MainContainerStateProvider.mjs +62 -0
- package/examples/grid/cellEditing/MainModel.mjs +30 -0
- package/examples/grid/cellEditing/MainStore.mjs +54 -0
- package/examples/grid/cellEditing/app.mjs +6 -0
- package/examples/grid/cellEditing/index.html +11 -0
- package/examples/grid/cellEditing/neo-config.json +6 -0
- package/examples/grid/container/MainContainer.mjs +7 -6
- package/examples/grid/covid/GridContainer.mjs +36 -36
- package/examples/grid/covid/Util.mjs +1 -1
- package/examples/grid/covid/neo-config.json +6 -5
- package/examples/table/cellEditing/MainContainer.mjs +174 -0
- package/examples/table/cellEditing/MainContainerStateProvider.mjs +62 -0
- package/examples/table/cellEditing/MainModel.mjs +30 -0
- package/examples/table/cellEditing/MainStore.mjs +54 -0
- package/examples/table/cellEditing/app.mjs +6 -0
- package/examples/table/cellEditing/index.html +11 -0
- package/examples/table/cellEditing/neo-config.json +6 -0
- package/examples/table/nestedRecordFields/MainContainerStateProvider.mjs +2 -1
- package/package.json +8 -8
- package/resources/scss/src/apps/portal/home/FooterContainer.scss +11 -2
- package/resources/scss/src/examples/grid/covid/GridContainer.scss +1 -1
- package/resources/scss/src/grid/Container.scss +13 -23
- package/resources/scss/src/grid/View.scss +45 -19
- package/resources/scss/src/grid/header/Button.scss +2 -4
- package/resources/scss/src/grid/header/Toolbar.scss +1 -2
- package/resources/scss/src/grid/plugin/CellEditing.scss +11 -0
- package/resources/scss/src/table/plugin/CellEditing.scss +11 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/Xhr.mjs +1 -1
- package/src/button/Base.mjs +2 -2
- package/src/collection/Base.mjs +5 -5
- package/src/component/Base.mjs +3 -3
- package/src/component/DateSelector.mjs +15 -0
- package/src/container/Base.mjs +2 -2
- package/src/controller/Base.mjs +3 -3
- package/src/dialog/Base.mjs +2 -2
- package/src/form/field/Base.mjs +3 -6
- package/src/form/field/CheckBox.mjs +2 -2
- package/src/form/field/ComboBox.mjs +18 -2
- package/src/form/field/Date.mjs +10 -4
- package/src/form/field/FileUpload.mjs +4 -4
- package/src/form/field/Hidden.mjs +2 -2
- package/src/form/field/Text.mjs +2 -2
- package/src/grid/Container.mjs +340 -43
- package/src/grid/View.mjs +599 -124
- package/src/grid/header/Button.mjs +331 -36
- package/src/grid/header/Toolbar.mjs +111 -4
- package/src/grid/plugin/CellEditing.mjs +30 -0
- package/src/layout/Base.mjs +3 -3
- package/src/list/Base.mjs +2 -2
- package/src/list/Circle.mjs +2 -2
- package/src/list/Color.mjs +2 -2
- package/src/list/Component.mjs +2 -2
- package/src/main/DomEvents.mjs +12 -3
- package/src/manager/Base.mjs +3 -3
- package/src/manager/Component.mjs +20 -11
- package/src/manager/DomEvent.mjs +5 -6
- package/src/manager/Focus.mjs +2 -2
- package/src/manager/Instance.mjs +4 -4
- package/src/manager/Task.mjs +2 -2
- package/src/manager/Toast.mjs +3 -3
- package/src/plugin/Base.mjs +18 -4
- package/src/plugin/Popover.mjs +3 -3
- package/src/plugin/PrefixField.mjs +2 -2
- package/src/plugin/Resizable.mjs +3 -7
- package/src/plugin/Responsive.mjs +2 -2
- package/src/selection/Model.mjs +17 -2
- package/src/selection/grid/CellColumnModel.mjs +1 -1
- package/src/selection/grid/CellColumnRowModel.mjs +1 -1
- package/src/selection/grid/CellModel.mjs +1 -1
- package/src/selection/grid/ColumnModel.mjs +2 -2
- package/src/table/Container.mjs +32 -3
- package/src/table/View.mjs +9 -4
- package/src/table/header/Toolbar.mjs +15 -1
- package/src/table/plugin/CellEditing.mjs +330 -0
- package/src/toolbar/Base.mjs +2 -2
- package/src/toolbar/Breadcrumb.mjs +1 -1
- package/src/tooltip/Base.mjs +2 -2
- package/src/util/KeyNavigation.mjs +14 -8
- package/src/worker/Base.mjs +3 -3
- package/src/grid/README.md +0 -3
@@ -1,4 +1,26 @@
|
|
1
|
+
.neo-grid-view-wrapper {
|
2
|
+
height : 100%;
|
3
|
+
overflow-x: hidden;
|
4
|
+
overflow-y: auto;
|
5
|
+
position : relative;
|
6
|
+
|
7
|
+
.neo-grid-scrollbar {
|
8
|
+
height : 1px;
|
9
|
+
position : absolute;
|
10
|
+
top : 0;
|
11
|
+
visibility : hidden;
|
12
|
+
width : 1px;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
1
16
|
.neo-grid-view {
|
17
|
+
height : 100%;
|
18
|
+
overflow-x: visible;
|
19
|
+
|
20
|
+
&.neo-is-scrolling * {
|
21
|
+
pointer-events: none !important;
|
22
|
+
}
|
23
|
+
|
2
24
|
.neo-center {
|
3
25
|
justify-content: center;
|
4
26
|
}
|
@@ -8,33 +30,37 @@
|
|
8
30
|
}
|
9
31
|
|
10
32
|
.neo-grid-row {
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
33
|
+
position: absolute;
|
34
|
+
|
35
|
+
&:hover {
|
36
|
+
.neo-grid-cell {
|
37
|
+
background-color: var(--grid-cell-background-color-hover);
|
15
38
|
}
|
39
|
+
}
|
16
40
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
}
|
41
|
+
// selection.RowModel
|
42
|
+
&.neo-selected {
|
43
|
+
.neo-grid-cell {
|
44
|
+
background-color: var(--grid-rowmodel-selected-cell-background-color);
|
45
|
+
color : var(--grid-rowmodel-selected-cell-color);
|
23
46
|
}
|
47
|
+
}
|
48
|
+
|
49
|
+
.neo-grid-cell {
|
50
|
+
position: absolute;
|
24
51
|
|
25
52
|
// selection.CellModel
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
}
|
53
|
+
&.neo-selected {
|
54
|
+
background-color: var(--grid-cellmodel-selected-cell-background-color) !important;
|
55
|
+
color : var(--grid-cellmodel-selected-cell-color) !important;
|
56
|
+
}
|
31
57
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
}
|
58
|
+
&.selected-column-cell {
|
59
|
+
background-color: var(--grid-cellmodel-selected-column-cell-background-color);
|
60
|
+
color : var(--grid-cellmodel-selected-column-cell-color);
|
36
61
|
}
|
37
62
|
}
|
63
|
+
}
|
38
64
|
}
|
39
65
|
|
40
66
|
.neo-selection-cellrowmodel,
|
@@ -20,10 +20,8 @@
|
|
20
20
|
border-right: 1px solid var(--grid-container-border-color);
|
21
21
|
}
|
22
22
|
|
23
|
-
&.neo-locked {
|
24
|
-
|
25
|
-
top : 0;
|
26
|
-
z-index : 5001;
|
23
|
+
&.neo-locked {
|
24
|
+
|
27
25
|
}
|
28
26
|
|
29
27
|
&.neo-drag-over {
|
package/src/DefaultConfig.mjs
CHANGED
@@ -262,12 +262,12 @@ const DefaultConfig = {
|
|
262
262
|
useVdomWorker: true,
|
263
263
|
/**
|
264
264
|
* buildScripts/injectPackageVersion.mjs will update this value
|
265
|
-
* @default '8.
|
265
|
+
* @default '8.1.0'
|
266
266
|
* @memberOf! module:Neo
|
267
267
|
* @name config.version
|
268
268
|
* @type String
|
269
269
|
*/
|
270
|
-
version: '8.
|
270
|
+
version: '8.1.0'
|
271
271
|
};
|
272
272
|
|
273
273
|
Object.assign(DefaultConfig, {
|
package/src/Xhr.mjs
CHANGED
package/src/button/Base.mjs
CHANGED
@@ -5,7 +5,7 @@ import NeoArray from '../util/Array.mjs';
|
|
5
5
|
* @class Neo.button.Base
|
6
6
|
* @extends Neo.component.Base
|
7
7
|
*/
|
8
|
-
class
|
8
|
+
class Button extends Component {
|
9
9
|
/**
|
10
10
|
* Valid values for badgePosition
|
11
11
|
* @member {String[]} badgePositions=['bottom-left','bottom-right','top-left','top-right']
|
@@ -581,4 +581,4 @@ class Base extends Component {
|
|
581
581
|
}
|
582
582
|
}
|
583
583
|
|
584
|
-
export default Neo.setupClass(
|
584
|
+
export default Neo.setupClass(Button);
|
package/src/collection/Base.mjs
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import Base from '../core/Base.mjs';
|
2
2
|
import Filter from './Filter.mjs';
|
3
3
|
import Logger from '../util/Logger.mjs';
|
4
4
|
import Observable from '../core/Observable.mjs';
|
@@ -16,7 +16,7 @@ const countMutations = Symbol('countMutations'),
|
|
16
16
|
* @class Neo.collection.Base
|
17
17
|
* @extends Neo.core.Base
|
18
18
|
*/
|
19
|
-
class
|
19
|
+
class Collection extends Base {
|
20
20
|
/**
|
21
21
|
* True automatically applies the core.Observable mixin
|
22
22
|
* @member {Boolean} observable=true
|
@@ -453,7 +453,7 @@ class Base extends CoreBase {
|
|
453
453
|
config.sorters.push(sorter.originalConfig)
|
454
454
|
});
|
455
455
|
|
456
|
-
return Neo.create(
|
456
|
+
return Neo.create(Collection, config)
|
457
457
|
}
|
458
458
|
|
459
459
|
/**
|
@@ -669,7 +669,7 @@ class Base extends CoreBase {
|
|
669
669
|
delete config.items;
|
670
670
|
delete config.sorters;
|
671
671
|
|
672
|
-
me.allItems = Neo.create(
|
672
|
+
me.allItems = Neo.create(Collection, {
|
673
673
|
...Neo.clone(config, true, true),
|
674
674
|
keyProperty: me.keyProperty,
|
675
675
|
sourceId : me.id
|
@@ -1265,4 +1265,4 @@ class Base extends CoreBase {
|
|
1265
1265
|
* @returns {Object}
|
1266
1266
|
*/
|
1267
1267
|
|
1268
|
-
export default Neo.setupClass(
|
1268
|
+
export default Neo.setupClass(Collection);
|
package/src/component/Base.mjs
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
+
import Base from '../core/Base.mjs';
|
1
2
|
import ClassSystemUtil from '../util/ClassSystem.mjs';
|
2
3
|
import ComponentManager from '../manager/Component.mjs';
|
3
|
-
import CoreBase from '../core/Base.mjs';
|
4
4
|
import DomEventManager from '../manager/DomEvent.mjs';
|
5
5
|
import KeyNavigation from '../util/KeyNavigation.mjs';
|
6
6
|
import Logger from '../util/Logger.mjs';
|
@@ -24,7 +24,7 @@ const
|
|
24
24
|
* @class Neo.component.Base
|
25
25
|
* @extends Neo.core.Base
|
26
26
|
*/
|
27
|
-
class
|
27
|
+
class Component extends Base {
|
28
28
|
/**
|
29
29
|
* Valid values for hideMode
|
30
30
|
* @member {String[]} hideModes=['removeDom','visibility']
|
@@ -2698,4 +2698,4 @@ class Base extends CoreBase {
|
|
2698
2698
|
* @param {Object[]} data.oldPath dom element ids upwards
|
2699
2699
|
*/
|
2700
2700
|
|
2701
|
-
export default Neo.setupClass(
|
2701
|
+
export default Neo.setupClass(Component);
|
@@ -392,6 +392,21 @@ class DateSelector extends Component {
|
|
392
392
|
return ClassSystemUtil.beforeSetInstance(value, DateSelectorModel)
|
393
393
|
}
|
394
394
|
|
395
|
+
/**
|
396
|
+
* Triggered before the value config gets changed
|
397
|
+
* @param {String} value
|
398
|
+
* @param {String} oldValue
|
399
|
+
* @protected
|
400
|
+
*/
|
401
|
+
beforeSetValue(value, oldValue) {
|
402
|
+
// If the value is set as a Date, try to convert it into a string
|
403
|
+
if (Neo.typeOf(value) === 'Date') {
|
404
|
+
return DateUtil.convertToyyyymmdd(value)
|
405
|
+
}
|
406
|
+
|
407
|
+
return value
|
408
|
+
}
|
409
|
+
|
395
410
|
/**
|
396
411
|
* Triggered before the weekStartDay config gets changed
|
397
412
|
* @param {String} value
|
package/src/container/Base.mjs
CHANGED
@@ -14,7 +14,7 @@ const byWeight = ({ weight : lhs = 0 }, { weight : rhs = 0 }) => lhs - rhs;
|
|
14
14
|
* @class Neo.container.Base
|
15
15
|
* @extends Neo.component.Base
|
16
16
|
*/
|
17
|
-
class
|
17
|
+
class Container extends Component {
|
18
18
|
static config = {
|
19
19
|
/**
|
20
20
|
* @member {String} className='Neo.container.Base'
|
@@ -746,4 +746,4 @@ class Base extends Component {
|
|
746
746
|
}
|
747
747
|
}
|
748
748
|
|
749
|
-
export default Neo.setupClass(
|
749
|
+
export default Neo.setupClass(Container);
|
package/src/controller/Base.mjs
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import Base from '../core/Base.mjs';
|
2
2
|
import HashHistory from '../util/HashHistory.mjs';
|
3
3
|
|
4
4
|
const
|
@@ -9,7 +9,7 @@ const
|
|
9
9
|
* @class Neo.controller.Base
|
10
10
|
* @extends Neo.core.Base
|
11
11
|
*/
|
12
|
-
class
|
12
|
+
class Controller extends Base {
|
13
13
|
static config = {
|
14
14
|
/**
|
15
15
|
* @member {String} className='Neo.controller.Base'
|
@@ -214,4 +214,4 @@ class Base extends CoreBase {
|
|
214
214
|
}
|
215
215
|
}
|
216
216
|
|
217
|
-
export default Neo.setupClass(
|
217
|
+
export default Neo.setupClass(Controller);
|
package/src/dialog/Base.mjs
CHANGED
@@ -9,7 +9,7 @@ let DragZone;
|
|
9
9
|
* @class Neo.dialog.Base
|
10
10
|
* @extends Neo.container.Panel
|
11
11
|
*/
|
12
|
-
class
|
12
|
+
class Dialog extends Panel {
|
13
13
|
/**
|
14
14
|
* Valid values for closeAction
|
15
15
|
* @member {String[]} closeActions=['close','hide']
|
@@ -796,4 +796,4 @@ class Base extends Panel {
|
|
796
796
|
}
|
797
797
|
}
|
798
798
|
|
799
|
-
export default Neo.setupClass(
|
799
|
+
export default Neo.setupClass(Dialog);
|
package/src/form/field/Base.mjs
CHANGED
@@ -7,7 +7,7 @@ import NeoArray from '../../util/Array.mjs';
|
|
7
7
|
* @class Neo.form.field.Base
|
8
8
|
* @extends Neo.component.Base
|
9
9
|
*/
|
10
|
-
class
|
10
|
+
class Field extends Component {
|
11
11
|
/**
|
12
12
|
* Valid values for isTouchedEvent
|
13
13
|
* @member {String[]} isTouchedEvents=['focusEnter','focusLeave']
|
@@ -78,10 +78,7 @@ class Base extends Component {
|
|
78
78
|
* @returns {Boolean}
|
79
79
|
*/
|
80
80
|
get isDirty() {
|
81
|
-
|
82
|
-
value = this.value;
|
83
|
-
|
84
|
-
return value !== originalValue && Neo.isEmpty(value) !== Neo.isEmpty(originalValue)
|
81
|
+
return !Neo.isEqual(this.getSubmitValue(), this.originalConfig.value)
|
85
82
|
}
|
86
83
|
/**
|
87
84
|
* An internal cache for formGroup(s) and the field name
|
@@ -382,4 +379,4 @@ class Base extends Component {
|
|
382
379
|
* @returns {Object}
|
383
380
|
*/
|
384
381
|
|
385
|
-
export default Neo.setupClass(
|
382
|
+
export default Neo.setupClass(Field);
|
@@ -1,12 +1,12 @@
|
|
1
|
-
import Base from './Base.mjs';
|
2
1
|
import ComponentManager from '../../manager/Component.mjs';
|
2
|
+
import Field from './Base.mjs';
|
3
3
|
import NeoArray from '../../util/Array.mjs';
|
4
4
|
|
5
5
|
/**
|
6
6
|
* @class Neo.form.field.CheckBox
|
7
7
|
* @extends Neo.form.field.Base
|
8
8
|
*/
|
9
|
-
class CheckBox extends
|
9
|
+
class CheckBox extends Field {
|
10
10
|
/**
|
11
11
|
* Valid values for labelPosition
|
12
12
|
* @member {String[]} labelPositions=['left','top']
|
@@ -165,7 +165,7 @@ class ComboBox extends Picker {
|
|
165
165
|
*/
|
166
166
|
afterSetStore(value, oldValue) {
|
167
167
|
let me = this,
|
168
|
-
filters;
|
168
|
+
filters, val;
|
169
169
|
|
170
170
|
if (value) {
|
171
171
|
if (me.useFilter) {
|
@@ -185,7 +185,14 @@ class ComboBox extends Picker {
|
|
185
185
|
me.list.store = value
|
186
186
|
}
|
187
187
|
|
188
|
-
value.on('load', me.onStoreLoad, me)
|
188
|
+
value.on('load', me.onStoreLoad, me);
|
189
|
+
|
190
|
+
if (me.value) {
|
191
|
+
val = me.value;
|
192
|
+
|
193
|
+
me._value = null; // silent reset to trigger a change event
|
194
|
+
me.value = val
|
195
|
+
}
|
189
196
|
}
|
190
197
|
}
|
191
198
|
|
@@ -248,6 +255,11 @@ class ComboBox extends Picker {
|
|
248
255
|
let me = this,
|
249
256
|
{displayField, valueField} = me;
|
250
257
|
|
258
|
+
// Do not create a default store instance, in case there is a bound store to be created
|
259
|
+
if (!value && me.bind?.store) {
|
260
|
+
return null
|
261
|
+
}
|
262
|
+
|
251
263
|
oldValue?.destroy();
|
252
264
|
|
253
265
|
// Promote an array of items to be a Store
|
@@ -312,6 +324,10 @@ class ComboBox extends Picker {
|
|
312
324
|
return null
|
313
325
|
}
|
314
326
|
|
327
|
+
if (!store) { // We will (re)set the value once the store is created
|
328
|
+
return value
|
329
|
+
}
|
330
|
+
|
315
331
|
// we can only match record ids or display values in case the store is loaded
|
316
332
|
if (store.getCount() > 0) {
|
317
333
|
record = store.isFiltered() ? store.allItems.get(value) : store.get(value);
|
package/src/form/field/Date.mjs
CHANGED
@@ -142,7 +142,7 @@ class DateField extends Picker {
|
|
142
142
|
afterSetMinValue(value, oldValue) {
|
143
143
|
let me = this;
|
144
144
|
|
145
|
-
me.changeInputElKey('
|
145
|
+
me.changeInputElKey('min', value);
|
146
146
|
|
147
147
|
if (me.dateSelector) {
|
148
148
|
me.dateSelector.minValue = value
|
@@ -170,8 +170,14 @@ class DateField extends Picker {
|
|
170
170
|
* @protected
|
171
171
|
*/
|
172
172
|
beforeSetValue(value, oldValue) {
|
173
|
-
|
174
|
-
|
173
|
+
if (Neo.typeOf(value) === 'Date') {
|
174
|
+
value = DateUtil.convertToyyyymmdd(value);
|
175
|
+
this.originalConfig.value = value
|
176
|
+
}
|
177
|
+
|
178
|
+
value = super.beforeSetValue(value, oldValue);
|
179
|
+
|
180
|
+
return (this.isoDate && value) ? value.substring(0, 10) : value
|
175
181
|
}
|
176
182
|
|
177
183
|
/**
|
@@ -244,7 +250,7 @@ class DateField extends Picker {
|
|
244
250
|
onInputValueChange(data) {
|
245
251
|
this.invalidInput = !data.valid;
|
246
252
|
|
247
|
-
if (data.valid
|
253
|
+
if (data.valid) {
|
248
254
|
super.onInputValueChange(data)
|
249
255
|
} else {
|
250
256
|
this.validate(false)
|
@@ -1,6 +1,6 @@
|
|
1
|
-
import
|
2
|
-
import NeoArray
|
3
|
-
import StringUtil
|
1
|
+
import Field from './Base.mjs';
|
2
|
+
import NeoArray from '../../util/Array.mjs';
|
3
|
+
import StringUtil from '../../util/String.mjs';
|
4
4
|
|
5
5
|
const
|
6
6
|
sizeRE = /^(\d+)(kb|mb|gb)?$/i,
|
@@ -84,7 +84,7 @@ const
|
|
84
84
|
* @class Neo.form.field.FileUpload
|
85
85
|
* @extends Neo.form.field.Base
|
86
86
|
*/
|
87
|
-
class FileUpload extends
|
87
|
+
class FileUpload extends Field {
|
88
88
|
static config = {
|
89
89
|
/**
|
90
90
|
* @member {String} className='Neo.form.field.FileUpload'
|
@@ -1,10 +1,10 @@
|
|
1
|
-
import
|
1
|
+
import Field from './Base.mjs';
|
2
2
|
|
3
3
|
/**
|
4
4
|
* @class Neo.form.field.Hidden
|
5
5
|
* @extends Neo.form.field.Base
|
6
6
|
*/
|
7
|
-
class Hidden extends
|
7
|
+
class Hidden extends Field {
|
8
8
|
static config = {
|
9
9
|
/**
|
10
10
|
* @member {String} className='Neo.form.field.Hidden'
|
package/src/form/field/Text.mjs
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
import Base from './Base.mjs';
|
2
1
|
import BaseTrigger from './trigger/Base.mjs';
|
3
2
|
import ClearTrigger from './trigger/Clear.mjs';
|
3
|
+
import Field from './Base.mjs';
|
4
4
|
import NeoArray from '../../util/Array.mjs';
|
5
5
|
import StringUtil from '../../util/String.mjs';
|
6
6
|
import VDomUtil from '../../util/VDom.mjs';
|
@@ -10,7 +10,7 @@ import VNodeUtil from '../../util/VNode.mjs';
|
|
10
10
|
* @class Neo.form.field.Text
|
11
11
|
* @extends Neo.form.field.Base
|
12
12
|
*/
|
13
|
-
class Text extends
|
13
|
+
class Text extends Field {
|
14
14
|
/**
|
15
15
|
* Valid values for autoCapitalize
|
16
16
|
* @member {String[]} autoCapitalizeValues=['characters','none','on','off','sentences','words']
|