diff --git a/src/main/webapp/resources/js/base/dataset.js b/src/main/webapp/resources/js/base/dataset.js index 9bc7d39b..c00478b4 100644 --- a/src/main/webapp/resources/js/base/dataset.js +++ b/src/main/webapp/resources/js/base/dataset.js @@ -1,6 +1,6 @@ /* Copyright (c) 2020 Emjay Khan. All rights reserved. */ -/**@file Classes and objects to help control user data in HTML pages +/**@file Classes and objects to help control user data in HTML pages */ function lpad(v) { @@ -26,7 +26,7 @@ const numberFormat = { } }, - /**Formats the value + /**Formats the value * @param {number} value value to format * @returns {string} formatted value */ @@ -38,13 +38,13 @@ const numberFormat = { /** value format for dates */ const dateFormat = { - /**Formats the value + /**Formats the value * @param {number} value value to format * @returns {string} formatted value */ format(value) { if (isEmpty(value)) return ""; - + let _format = v => { let date = "number" == typeof v ? new Date(v) : v; let year = date.getFullYear(), @@ -52,7 +52,7 @@ const dateFormat = { day = lpad(date.getDate()); return year + "-" + month + "-" + day; }; - + switch (value instanceof Date ? "date" : typeof value) { case "number": case "date": return _format(value); @@ -60,7 +60,7 @@ const dateFormat = { default: return ""; } }, - + parse(value) { return isEmpty(value) ? "" : value.replace(/-/gi, ""); } @@ -68,7 +68,7 @@ const dateFormat = { /** value format for time */ const timeFormat = { - /**Formats the value + /**Formats the value * @param {number} value value to format * @returns {string} formatted value */ @@ -80,7 +80,7 @@ const timeFormat = { seconds = lpad(date.getSeconds()); return hours + ":" + minutes + ":" + seconds; }; - + switch (value instanceof Date ? "date" : typeof value) { case "number": case "date": return _format(value); @@ -90,7 +90,7 @@ const timeFormat = { default: return ""; } }, - + parse(value) { return isEmpty(value) ? "" : value.replace(/:/gi, ""); } @@ -98,7 +98,7 @@ const timeFormat = { /** value format for datetimes */ const datetimeFormat = { - /**Formats the value + /**Formats the value * @param {number} value value to format * @returns {string} formatted value */ @@ -110,7 +110,7 @@ const datetimeFormat = { default: return ""; } }, - + parse(value) { return isEmpty(value) ? "" : timeFormat.parse(dateFormat.parse(value)).replace(/ /gi, ""); } @@ -126,8 +126,8 @@ const datetimeFormat = { * key0: numberFormat, * key1: dateFormat, * key2: { - * format(value) {...}, - * parse(value) {...} + * format(value) {...}, + * parse(value) {...} * } * }) */ @@ -149,24 +149,24 @@ class ValueFormat { *
For a Dataset to work properly, it needs a keymapper to identify user data. - * And you specify it in a Dataset's configuration. + * And you specify it in a Dataset's configuration. *
let dataset = new Dataset({
* keymapper: function(info) {return info.keyProperty;},
* ...
@@ -350,12 +350,12 @@ class Dataset {
_items;
_byKeys;
_current;
-
+
/**Dataset configuration
*/
conf;
_formats;
-
+
/**Creates a new Dataset with a configuration.
* The configuration is an object with which you specify
* - keymapper - function that returns a key of a user data. Used to identify user data in the Dataset. Mandatory.
@@ -370,21 +370,21 @@ class Dataset {
* - {@link Dataset#onReplace onReplace}
* - {@link Dataset#onRemove onRemove}
* - {@link Dataset#onDirtiesChange onDirtiesChange}
- *
+ *
*
* trace - true to enable message logging
- *
+ *
* @param conf {object} configuration
*/
constructor(conf) {
this._items = [];
this._byKeys = {};
this._current = null;
-
+
this.conf = notEmpty(conf, "conf is required but missing");
notEmpty(conf.keymapper, "keymapper is required but missing");
this._formats = new ValueFormat(conf.formats);
-
+
if (!conf.trace)
this.log = () => {};
@@ -438,12 +438,12 @@ class Dataset {
* let added = dirties.added;
* let modified = dirties.modified;
* let removed = dirties.removed;
- */
+ */
getKeys(status){
let dataset = this.getDataset(status);
if ("dirty" != status)
return dataset.map(e => this.getKey(e));
-
+
let result = {};
for (let prop in dataset) {
result[prop] = dataset[prop].map(e => this.getKey(e));
@@ -495,7 +495,7 @@ class Dataset {
let array = Array.isArray(obj) ? obj : this.conf.dataGetter(obj) || [];
if (!Array.isArray(array))
throw new Error("The data must be an array");
-
+
this._items = array.map(e => new DataItem(e, this._formats));
this._items.forEach(item => {
let key = "key-" + this.getKey(item.data);
@@ -505,29 +505,29 @@ class Dataset {
this.onDatasetChange(obj);
this.setState(!Array.isArray(obj) ? obj.state : state);
this.onDirtiesChange(this.dirty);
-
+
return this;
}
-
+
_getDataItems(obj) {
obj = obj || {};
let array = Array.isArray(obj) ? obj : this.conf.dataGetter(obj) || [];
if (!Array.isArray(array))
throw new Error("The data must be an array");
-
+
let _items = array.map(e => new DataItem(e, this._formats)),
_byKeys = {};
_items.forEach(item => {
let key = "key-" + this.getKey(item.data);
_byKeys[key] = item;
});
-
+
return {
items: _items,
byKeys: _byKeys
};
}
-
+
/**Adds user data to the Dataset.
* To get user data from an object, the dataGetter configured is called.
* After user data is set, the methods
@@ -543,7 +543,7 @@ class Dataset {
addData(obj) {
if (this.empty)
return this.setData(obj);
-
+
let state = this.state;
let data = this._getDataItems(obj);
this._items = this._items.concat(data.items);
@@ -557,13 +557,13 @@ class Dataset {
this.onDatasetChange(obj);
this.setState(!Array.isArray(obj) ? obj.state : state);
this.onDirtiesChange(this.dirty);
-
+
return this;
-
+
}
/**Clears the Dataset's user data.
- * @returns {Dataset} the Dataset
+ * @returns {Dataset} the Dataset
*/
clear() {
this.setData(null);
@@ -603,7 +603,7 @@ class Dataset {
/**Sets the user data as current that is associated with the key.
* @param {string} key key to a user data
- * After the data is set, the method
+ * After the data is set, the method
* - {@link Dataset#onCurrentChange}
*
* is called back.
@@ -636,7 +636,7 @@ class Dataset {
}
/**Sets the state to the Dataset.
- * After the state is set, the methods
+ * After the state is set, the methods
* - {@link Dataset#onCurrentChange}
* - {@link Dataset#onSelectionChange}
*
@@ -734,7 +734,7 @@ class Dataset {
}
if ("item" == option)
return result;
-
+
let getData = item => item.data;
if ("dirty" != status)
return "item" == option ? result : result.map(e => getData(e));
@@ -833,13 +833,13 @@ class Dataset {
*/
append(data) {
if (!data) return this;
-
+
let notDirty = !this.dirty,
array = Array.isArray(data) ? data : [data];
array.forEach(e => {
let item = new DataItem(e, this._formats);
this._items.push(item);
-
+
let key = this.getKey(e);
this._byKeys["key-" + key] = item;
item.state = "added";
@@ -849,10 +849,10 @@ class Dataset {
this.onAppend(array);
state.currentKey = this.getKey(array[array.length - 1]);
this.setState(state);
-
+
if (notDirty)
this.onDirtiesChange(true);
-
+
return this;
};
@@ -880,11 +880,11 @@ class Dataset {
*/
modify(key, modifier) {
if (!modifier) return this;
-
+
let item = this.getData(key, "item");
if (!item)
return log("Item not found with " + key);
-
+
let notDirty = !this.dirty,
data = item.data,
prev = Object.assign({}, data),
@@ -898,11 +898,11 @@ class Dataset {
}
return changed;
};
-
+
let current = data == this.getCurrent(),
revert = modifier(item) == ValueFormat.InvalidValue,
changed = modifiedProps(prev, data);
-
+
if (changed.length > 0) {
if (!item.state)
item.state = "modified";
@@ -946,30 +946,30 @@ class Dataset {
*/
replace(replacement) {
if (isEmpty(replacement)) return this;
-
+
let before = this.dirty,
replacements = Array.isArray(replacement) ? replacement : [replacement],
replacing = [];
replacements.forEach(obj => {
let data = obj.data;
if (!data) return;
-
+
let key = obj.key || this.getKey(data);
if (!key) return;
-
+
let oldItem = this.getData(key, "item"),
newItem = new DataItem(data, this._formats),
pos = oldItem ? this._items.indexOf(oldItem) : -1;
-
- newItem.selected = oldItem && oldItem.selected;
+
+ newItem.selected = oldItem && oldItem.selected;
if (pos > -1)
this._items[pos] = newItem;
else
this._items.push(newItem);
-
+
delete this._byKeys["key-" + key];
this._byKeys["key-" + this.getKey(data)] = newItem;
-
+
if (this._current == oldItem)
this._current = newItem;
@@ -999,7 +999,7 @@ class Dataset {
*/
remove(key) {
if (!key || this.empty) return this;
-
+
let before = this.dirty,
keys = Array.isArray(key) ? key : [key],
removed = this._items.filter(item => {
@@ -1012,13 +1012,13 @@ class Dataset {
}),
currentPos = this._items.indexOf(this._current),
state = this.state;
-
+
if (currentPos > -1) {
let newKey = null;
for (let i = currentPos, length = this._items.length; i < length; ++i) {
let item = this._items[i];
if (item.unreachable) continue;
-
+
newKey = this.getKey(item);
break;
}
@@ -1026,7 +1026,7 @@ class Dataset {
for (let i = this._items.length - 1; i > 0; --i) {
let item = this._items[i];
if (item.unreachable) continue;
-
+
newKey = this.getKey(item);
break;
}
@@ -1037,7 +1037,7 @@ class Dataset {
let after = this.dirty;
if (before != after)
this.onDirtiesChange(after);
-
+
return this;
}
@@ -1049,7 +1049,7 @@ class Dataset {
*
* are called.
* Note that unlike {@link Dataset#remove} this method deletes user data completely from the Dataset
- * and the erased user data are not traced as dirty user data.
+ * and the erased user data are not traced as dirty user data.
* @param {string|array} key key or keys to user data
* @returns {Dataset} the Dataset
* @example
@@ -1058,7 +1058,7 @@ class Dataset {
*/
erase(key) {
if (!key || this.empty) return;
-
+
let before = this.dirty,
keys = Array.isArray(key) ? key : [key],
erased = this._items.filter(item => {
@@ -1069,16 +1069,16 @@ class Dataset {
}
return erase;
});
-
+
let currentPos = erased.indexOf(this._current) > -1 ? this._items.indexOf(this._current) : -1,
state = this.state;
-
+
if (currentPos > -1) {
let newKey = null;
for (let i = currentPos + 1, length = this._items.length; i < length; ++i) {
let item = this._items[i];
if (item.unreachable || erased.includes(item)) continue;
-
+
newKey = this.getKey(item);
break;
}
@@ -1086,7 +1086,7 @@ class Dataset {
for (let i = this._items.length - 1; i > 0; --i) {
let item = this._items[i];
if (item.unreachable || erased.includes(item)) continue;
-
+
newKey = this.getKey(item);
break;
}
@@ -1104,7 +1104,7 @@ class Dataset {
/**Returns an array of strings converted from the template using the property values of the Dataset's user data.
* In the template, placeholder for the properties of the user data is specified like {property name}.
* @param {string} template template string
- * @param {function} formatter function to format a row string with custom property placeholders
+ * @param {function} formatter function to format a row string with custom property placeholders
* @returns {array} array of strings converted from the template using the property values of the user data
*/
inStrings(template, formatter) {
@@ -1136,7 +1136,7 @@ class Dataset {
break;
default: return null;
}
-
+
let item = this.getData(key, "item");
return item ? item.getValue(property) : undefined;
}
@@ -1157,7 +1157,7 @@ class Dataset {
*/
setValue(...args) {
let key = null,
- property = null,
+ property = null,
value = null;
switch (args.length) {
case 2:
@@ -1181,41 +1181,41 @@ class Dataset {
* @param {object|array} obj object that has user data or an array of user data
*/
onDatasetChange(obj) {this.log("Dataset changed", obj);}
-
+
/**Called back when current user data is changed.
* @param {DataItem} currentItem current dataItem
*/
onCurrentChange(currentItem) {this.log("Current changed", currentItem);}
/**Called back when user data selection changes.
- * @param {array} selected array of selected user data
+ * @param {array} selected array of selected user data
*/
onSelectionChange(selected) {this.log("Selection changed", selected);}
/**Called back when user data is appended.
- * @param {object|array} appended user data or array of user data
+ * @param {object|array} appended user data or array of user data
*/
onAppend(appended) {this.log("Data appended", appended);}
/**Called back when user data is modified.
- * @param {array} props names of changed properties
+ * @param {array} props names of changed properties
* @param {DataItem} modified modified user dataItem
* @param {boolean} current whether current user data is modified
*/
onModify(props, modified, current) {this.log("Data modified", props, modified, current ? "current" : "");}
/**Called back when user data are replaced.
- * @param {array} replacing array of user dataItems replacing the old ones
+ * @param {array} replacing array of user dataItems replacing the old ones
*/
onReplace(replacing) {this.log("Data replaced", replacing);}
/**Called back when user data are removed.
- * @param {array} removed array of removed dataItems
+ * @param {array} removed array of removed dataItems
*/
onRemove(removed) {this.log("Data removed", removed)}
/**Called back when the Dataset gets dirty or not dirty.
- * @param {boolean} dirty
+ * @param {boolean} dirty
* - true if the Dataset is dirty
* - false otherwise
*
@@ -1230,9 +1230,9 @@ class DatasetControl {
this.prefixName = conf.prefixName;
this.infoSize = conf.infoSize;
this.appendData = conf.appendData;
-
+
this.query = {};
-
+
conf.onDatasetChange = obj => this.onDatasetChange(obj),
conf.onCurrentChange = item => this.onCurrentChange(item),
conf.onSelectionChange = selected => this.onSelectionChange(selected),
@@ -1245,7 +1245,7 @@ class DatasetControl {
}
this.dataset = new Dataset(conf);
-
+
this.urls = conf.urls || {
load:this.url("/list.do"),
getInfo:this.url("/info.do"),
@@ -1254,11 +1254,11 @@ class DatasetControl {
remove:this.url("/remove.do")
};
}
-
+
prefixed(str) {
return (this.prefix || "") + str;
}
-
+
url(str) {
return wctx.url("/" + this.prefixed(str));
}
@@ -1284,7 +1284,7 @@ class DatasetControl {
}
});
}
-
+
download(type) {
this.query.download = type || "xls";
let query = toQuery(this.query);
@@ -1295,7 +1295,7 @@ class DatasetControl {
setData(obj) {
this.dataset.setData(obj);
}
-
+
addData(obj) {
this.dataset.addData(obj);
}
@@ -1303,7 +1303,7 @@ class DatasetControl {
onDatasetChange(obj) {
debug("onDatasetChange", obj);
}
-
+
getCurrent(option) {
return this.dataset.getCurrent(option);
}
@@ -1345,42 +1345,42 @@ class DatasetControl {
else
this.setInfo(info);
}
-
+
setInfo(info) {}
-
+
newInfo(obj) {
this.dataset.append(obj || {});
this.getInfo();
}
-
+
getValue(name) {
return this.dataset.getValue(name);
}
-
+
setValue(name, value) {
this.dataset.setValue(name, value);
}
-
+
onAppend(items) {
debug("on append", items);
}
-
+
onModify(props, modified, current) {
debug("on modify", props, "modified", modified, "current", current);
}
-
+
save(info) {
if (!info) return;
let item = this.getCurrent("item"),
create = "added" == item.state;
-
+
ajax.post({
url:!create ? this.urls.update : this.urls.create,
data:info,
success:resp => this.onSave(resp)
});
}
-
+
onSave(resp) {
if (resp.saved) {
dialog.alert("저장됐습니다.");
@@ -1388,7 +1388,7 @@ class DatasetControl {
this._load();
}
}
-
+
remove(params) {
let selected = this.dataset.getKeys("selected");
if (selected.length < 1) return;
@@ -1397,14 +1397,14 @@ class DatasetControl {
params = {};
params[this.prefixed("IDs")] = selected.join(",");
}
-
+
ajax.post({
url:this.urls.remove,
data:params,
success:resp => this.onRemove(selected, resp)
});
}
-
+
onRemove(selected, resp) {
if (resp.saved)
this._load();