Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F4132706
mw.widgets.TableWidgetModel.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
mw.widgets.TableWidgetModel.js
View Options
/*!
* MediaWiki Widgets TableWidgetModel class.
*
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* Configuration options.
*
* @typedef {Object} mw.widgets.TableWidgetModel~Config
* @property {Array} [rows] An array of objects containing `key` and `label` properties for every row
* @property {Array} [cols] An array of objects containing `key` and `label` properties for every column
* @property {Array} [data] An array containing all values of the table
* @property {RegExp|Function|string} [validate] Validation pattern to apply on every cell
* @property {boolean} [showHeaders=true] Show table header row. Defaults to true.
* @property {boolean} [showRowLabels=true] Show row labels. Defaults to true.
* @property {boolean} [allowRowInsertion=true] Allow row insertion. Defaults to true.
* @property {boolean} [allowRowDeletion=true] Allow row deletion. Defaults to true.
*/
/**
* @classdesc TableWidget model.
*
* @class
* @mixes OO.EventEmitter
*
* @constructor
* @description Create an instance of `mw.widgets.TableWidgetModel`.
* @param {mw.widgets.TableWidgetModel~Config} [config] Configuration options
*/
mw
.
widgets
.
TableWidgetModel
=
function
MwWidgetsTableWidgetModel
(
config
)
{
config
=
config
||
{};
// Mixin constructors
OO
.
EventEmitter
.
call
(
this
,
config
);
this
.
data
=
config
.
data
||
[];
this
.
validate
=
config
.
validate
;
this
.
showHeaders
=
(
config
.
showHeaders
!==
undefined
)
?
!!
config
.
showHeaders
:
true
;
this
.
showRowLabels
=
(
config
.
showRowLabels
!==
undefined
)
?
!!
config
.
showRowLabels
:
true
;
this
.
allowRowInsertion
=
(
config
.
allowRowInsertion
!==
undefined
)
?
!!
config
.
allowRowInsertion
:
true
;
this
.
allowRowDeletion
=
(
config
.
allowRowDeletion
!==
undefined
)
?
!!
config
.
allowRowDeletion
:
true
;
this
.
initializeProps
(
config
.
rows
,
config
.
cols
);
};
/* Inheritance */
OO
.
mixinClass
(
mw
.
widgets
.
TableWidgetModel
,
OO
.
EventEmitter
);
/* Static Methods */
/**
* Get an entry from a props table
*
* @static
* @private
* @param {string|number} handle The key (or numeric index) of the row/column
* @param {Array} table Props table
* @return {Object|null} An object containing the `key`, `index` and `label`
* properties of the row/column. Returns `null` if the row/column can't be found.
*/
mw
.
widgets
.
TableWidgetModel
.
static
.
getEntryFromPropsTable
=
function
(
handle
,
table
)
{
let
row
=
null
,
i
,
len
;
if
(
typeof
handle
===
'string'
)
{
for
(
i
=
0
,
len
=
table
.
length
;
i
<
len
;
i
++
)
{
if
(
table
[
i
].
key
===
handle
)
{
row
=
table
[
i
];
break
;
}
}
}
else
if
(
typeof
handle
===
'number'
)
{
if
(
handle
<
table
.
length
)
{
row
=
table
[
handle
];
}
}
return
row
;
};
/* Events */
/**
* Fired when a value inside the table has changed.
*
* @event mw.widgets.TableWidgetModel.valueChange
* @param {number} row The row index of the updated cell
* @param {number} column The column index of the updated cell
* @param {any} value The new value
*/
/**
* Fired when a new row is inserted into the table.
*
* @event mw.widgets.TableWidgetModel.insertRow
* @param {Array} data The initial data
* @param {number} index The index in which to insert the new row
* @param {string} key The row key
* @param {string} label The row label
*/
/**
* Fired when a new row is inserted into the table.
*
* @event mw.widgets.TableWidgetModel.insertColumn
* @param {Array} data The initial data
* @param {number} index The index in which to insert the new column
* @param {string} key The column key
* @param {string} label The column label
*/
/**
* Fired when a row is removed from the table.
*
* @event mw.widgets.TableWidgetModel.removeRow
* @param {number} index The removed row index
* @param {string} key The removed row key
*/
/**
* Fired when a column is removed from the table.
*
* @event mw.widgets.TableWidgetModel.removeColumn
* @param {number} index The removed column index
* @param {string} key The removed column key
*/
/**
* Fired when the table data is wiped.
*
* @event mw.widgets.TableWidgetModel.clear
* @param {boolean} clear Clear row/column properties
*/
/* Methods */
/**
* Initializes and ensures the proper creation of the rows and cols property arrays.
* If data exceeds the number of rows and cols given, new ones will be created.
*
* @private
* @param {Array} rowProps The initial row props
* @param {Array} colProps The initial column props
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
initializeProps
=
function
(
rowProps
,
colProps
)
{
// FIXME: Account for extra data with missing row/col metadata
let
i
,
len
;
this
.
rows
=
[];
this
.
cols
=
[];
if
(
Array
.
isArray
(
rowProps
)
)
{
for
(
i
=
0
,
len
=
rowProps
.
length
;
i
<
len
;
i
++
)
{
this
.
rows
.
push
(
{
index
:
i
,
key
:
rowProps
[
i
].
key
,
label
:
rowProps
[
i
].
label
}
);
}
}
if
(
Array
.
isArray
(
colProps
)
)
{
for
(
i
=
0
,
len
=
colProps
.
length
;
i
<
len
;
i
++
)
{
this
.
cols
.
push
(
{
index
:
i
,
key
:
colProps
[
i
].
key
,
label
:
colProps
[
i
].
label
}
);
}
}
};
/**
* Triggers the initialization process and builds the initial table.
*
* @fires mw.widgets.TableWidgetModel.insertRow
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
setupTable
=
function
()
{
this
.
verifyData
();
this
.
buildTable
();
};
/**
* Verifies if the table data is complete and synced with
* row and column properties, and adds empty strings as
* cell data if cells are missing
*
* @private
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
verifyData
=
function
()
{
let
i
,
j
,
rowLen
,
colLen
;
for
(
i
=
0
,
rowLen
=
this
.
rows
.
length
;
i
<
rowLen
;
i
++
)
{
if
(
this
.
data
[
i
]
===
undefined
)
{
this
.
data
.
push
(
[]
);
}
for
(
j
=
0
,
colLen
=
this
.
cols
.
length
;
j
<
colLen
;
j
++
)
{
if
(
this
.
data
[
i
][
j
]
===
undefined
)
{
this
.
data
[
i
].
push
(
''
);
}
}
}
};
/**
* Build initial table
*
* @private
* @fires mw.widgets.TableWidgetModel.insertRow
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
buildTable
=
function
()
{
let
i
,
len
;
for
(
i
=
0
,
len
=
this
.
rows
.
length
;
i
<
len
;
i
++
)
{
this
.
emit
(
'insertRow'
,
this
.
data
[
i
],
i
,
this
.
rows
[
i
].
key
,
this
.
rows
[
i
].
label
);
}
};
/**
* Refresh the entire table with new data
*
* @private
* @fires mw.widgets.TableWidgetModel.insertRow
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
refreshTable
=
function
()
{
// TODO: Clear existing table
this
.
buildTable
();
};
/**
* Set the value of a particular cell.
*
* @param {number|string} row The index or key of the row
* @param {number|string} col The index or key of the column
* @param {any} value The new value
* @fires mw.widgets.TableWidgetModel.valueChange
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
setValue
=
function
(
row
,
col
,
value
)
{
let
rowIndex
,
colIndex
;
if
(
typeof
row
===
'number'
)
{
rowIndex
=
row
;
}
else
if
(
typeof
row
===
'string'
)
{
rowIndex
=
this
.
getRowProperties
(
row
).
index
;
}
if
(
typeof
col
===
'number'
)
{
colIndex
=
col
;
}
else
if
(
typeof
col
===
'string'
)
{
colIndex
=
this
.
getColumnProperties
(
col
).
index
;
}
if
(
typeof
rowIndex
===
'number'
&&
typeof
colIndex
===
'number'
&&
this
.
data
[
rowIndex
]
!==
undefined
&&
this
.
data
[
rowIndex
][
colIndex
]
!==
undefined
&&
this
.
data
[
rowIndex
][
colIndex
]
!==
value
)
{
this
.
data
[
rowIndex
][
colIndex
]
=
value
;
this
.
emit
(
'valueChange'
,
rowIndex
,
colIndex
,
value
);
}
};
/**
* Set the table data.
*
* @param {Array} data The new table data
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
setData
=
function
(
data
)
{
if
(
Array
.
isArray
(
data
)
)
{
this
.
data
=
data
;
this
.
verifyData
();
this
.
refreshTable
();
}
};
/**
* Inserts a row into the table. If the row isn't added at the end of the table,
* all the following data will be shifted back one row.
*
* @param {Array} [data] The data to insert to the row.
* @param {number} [index] The index in which to insert the new row.
* If unset or set to null, the row will be added at the end of the table.
* @param {string} [key] A key to quickly select this row.
* If unset or set to null, no key will be set.
* @param {string} [label] A label to display next to the row.
* If unset or set to null, the key will be used if there is one.
* @fires mw.widgets.TableWidgetModel.insertRow
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
insertRow
=
function
(
data
,
index
,
key
,
label
)
{
const
insertIndex
=
(
typeof
index
===
'number'
)
?
index
:
this
.
rows
.
length
;
// Add the new row metadata
this
.
rows
.
splice
(
insertIndex
,
0
,
{
index
:
insertIndex
,
key
:
key
||
undefined
,
label
:
label
||
undefined
}
);
const
newRowData
=
[];
let
insertDataCell
;
// Add the new row data
const
insertData
=
(
Array
.
isArray
(
data
)
)
?
data
:
[];
// Ensure that all columns of data for this row have been supplied,
// otherwise fill the remaining data with empty strings
for
(
let
i
=
0
,
len
=
this
.
cols
.
length
;
i
<
len
;
i
++
)
{
insertDataCell
=
''
;
if
(
typeof
insertData
[
i
]
===
'string'
||
typeof
insertData
[
i
]
===
'number'
)
{
insertDataCell
=
insertData
[
i
];
}
newRowData
.
push
(
insertDataCell
);
}
this
.
data
.
splice
(
insertIndex
,
0
,
newRowData
);
// Update all indexes in following rows
for
(
let
i
=
insertIndex
+
1
,
len
=
this
.
rows
.
length
;
i
<
len
;
i
++
)
{
this
.
rows
[
i
].
index
++
;
}
this
.
emit
(
'insertRow'
,
data
,
insertIndex
,
key
,
label
);
};
/**
* Inserts a column into the table. If the column isn't added at the end of the table,
* all the following data will be shifted back one column.
*
* @param {Array} [data] The data to insert to the column.
* @param {number} [index] The index in which to insert the new column.
* If unset or set to null, the column will be added at the end of the table.
* @param {string} [key] A key to quickly select this column.
* If unset or set to null, no key will be set.
* @param {string} [label] A label to display next to the column.
* If unset or set to null, the key will be used if there is one.
* @fires mw.widgets.TableWidgetModel.insertColumn
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
insertColumn
=
function
(
data
,
index
,
key
,
label
)
{
const
insertIndex
=
(
typeof
index
===
'number'
)
?
index
:
this
.
cols
.
length
;
// Add the new column metadata
this
.
cols
.
splice
(
insertIndex
,
0
,
{
index
:
insertIndex
,
key
:
key
||
undefined
,
label
:
label
||
undefined
}
);
// Add the new column data
const
insertData
=
(
Array
.
isArray
(
data
)
)
?
data
:
[];
// Ensure that all rows of data for this column have been supplied,
// otherwise fill the remaining data with empty strings
let
insertDataCell
;
for
(
let
i
=
0
,
len
=
this
.
rows
.
length
;
i
<
len
;
i
++
)
{
insertDataCell
=
''
;
if
(
typeof
insertData
[
i
]
===
'string'
||
typeof
insertData
[
i
]
===
'number'
)
{
insertDataCell
=
insertData
[
i
];
}
this
.
data
[
i
].
splice
(
insertIndex
,
0
,
insertDataCell
);
}
// Update all indexes in following cols
for
(
let
i
=
insertIndex
+
1
,
len
=
this
.
cols
.
length
;
i
<
len
;
i
++
)
{
this
.
cols
[
i
].
index
++
;
}
this
.
emit
(
'insertColumn'
,
data
,
index
,
key
,
label
);
};
/**
* Removes a row from the table. If the row removed isn't at the end of the table,
* all the following rows will be shifted back one row.
*
* @param {number|string} handle The key or numerical index of the row to remove
* @fires mw.widgets.TableWidgetModel.removeRow
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
removeRow
=
function
(
handle
)
{
const
rowProps
=
this
.
getRowProperties
(
handle
);
// Exit early if the row couldn't be found
if
(
rowProps
===
null
)
{
return
;
}
this
.
rows
.
splice
(
rowProps
.
index
,
1
);
this
.
data
.
splice
(
rowProps
.
index
,
1
);
// Update all indexes in following rows
for
(
let
i
=
rowProps
.
index
,
len
=
this
.
rows
.
length
;
i
<
len
;
i
++
)
{
this
.
rows
[
i
].
index
--
;
}
this
.
emit
(
'removeRow'
,
rowProps
.
index
,
rowProps
.
key
);
};
/**
* Removes a column from the table. If the column removed isn't at the end of the table,
* all the following columns will be shifted back one column.
*
* @param {number|string} handle The key or numerical index of the column to remove
* @fires mw.widgets.TableWidgetModel.removeColumn
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
removeColumn
=
function
(
handle
)
{
const
colProps
=
this
.
getColumnProperties
(
handle
);
// Exit early if the column couldn't be found
if
(
colProps
===
null
)
{
return
;
}
this
.
cols
.
splice
(
colProps
.
index
,
1
);
for
(
let
i
=
0
,
len
=
this
.
data
.
length
;
i
<
len
;
i
++
)
{
this
.
data
[
i
].
splice
(
colProps
.
index
,
1
);
}
// Update all indexes in following columns
for
(
let
i
=
colProps
.
index
,
len
=
this
.
cols
.
length
;
i
<
len
;
i
++
)
{
this
.
cols
[
i
].
index
--
;
}
this
.
emit
(
'removeColumn'
,
colProps
.
index
,
colProps
.
key
);
};
/**
* Clears the table data.
*
* @fires mw.widgets.TableWidgetModel.clear
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
clear
=
function
()
{
this
.
data
=
[];
this
.
verifyData
();
this
.
emit
(
'clear'
,
false
);
};
/**
* Clears the table data, as well as all row and column properties.
*
* @fires mw.widgets.TableWidgetModel.clear
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
clearWithProperties
=
function
()
{
this
.
data
=
[];
this
.
rows
=
[];
this
.
cols
=
[];
this
.
emit
(
'clear'
,
true
);
};
/**
* Get all table properties.
*
* @return {Object}
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
getTableProperties
=
function
()
{
return
{
showHeaders
:
this
.
showHeaders
,
showRowLabels
:
this
.
showRowLabels
,
allowRowInsertion
:
this
.
allowRowInsertion
,
allowRowDeletion
:
this
.
allowRowDeletion
};
};
/**
* Get the validation pattern to test cells against.
*
* @return {RegExp|Function|string}
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
getValidationPattern
=
function
()
{
return
this
.
validate
;
};
/**
* Get properties of a given row.
*
* @param {string|number} handle The key (or numeric index) of the row
* @return {Object|null} An object containing the `key`, `index` and `label` properties of the row.
* Returns `null` if the row can't be found.
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
getRowProperties
=
function
(
handle
)
{
return
mw
.
widgets
.
TableWidgetModel
.
static
.
getEntryFromPropsTable
(
handle
,
this
.
rows
);
};
/**
* Get properties of all rows.
*
* @return {Array} An array of objects containing `key`, `index` and `label` properties for each row
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
getAllRowProperties
=
function
()
{
return
this
.
rows
.
slice
();
};
/**
* Get properties of a given column.
*
* @param {string|number} handle The key (or numeric index) of the column
* @return {Object|null} An object containing the `key`, `index` and
* `label` properties of the column.
* Returns `null` if the column can't be found.
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
getColumnProperties
=
function
(
handle
)
{
return
mw
.
widgets
.
TableWidgetModel
.
static
.
getEntryFromPropsTable
(
handle
,
this
.
cols
);
};
/**
* Get properties of all columns.
*
* @return {Array} An array of objects containing `key`, `index` and
* `label` properties for each column
*/
mw
.
widgets
.
TableWidgetModel
.
prototype
.
getAllColumnProperties
=
function
()
{
return
this
.
cols
.
slice
();
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Aug 19, 11:45 (3 w, 1 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
92/b0/64a2b5fb6412ecd2bd254e6b54e9
Default Alt Text
mw.widgets.TableWidgetModel.js (14 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment