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 { * - */ + */ parser(key) { let parser = this._formats[key]; return parser && parser.parse ? parser.parse : ValueFormat.Default.parse; } - + /**Returns a formatter associated with the key. * @param {string} key key associated with a value format * @returns {function} * - */ + */ formatter(key) { let formatter = this._formats[key]; return formatter && formatter.format ? formatter.format : ValueFormat.Default.format; } - + regexp(key) { let expr = this._exprs[key]; if (!expr) @@ -184,7 +184,7 @@ ValueFormat.Default = { /** Represents an invalid value. */ ValueFormat.InvalidValue = "^invalid^value^"; -/**Wraps a user data and traces the manipulation performed on it and consequent status. +/**Wraps a user data and traces the manipulation performed on it and consequent status. */ class DataItem { /** user data */ @@ -195,7 +195,7 @@ class DataItem { selected; /** state of the user data */ state; - + /**Creates a new DataItem. * @param {any} data user data * @param {object} formats value formatters of the user data's property @@ -285,7 +285,7 @@ class DataItem { /**Returns a string converted from the template using the property values of the 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 {string} string converted from the template using the property values of the user data */ inString(template, formatter) { @@ -303,7 +303,7 @@ class DataItem { /**Manages user data wrapped in {@link DataItem}s, tracing the state after manipulation performed on them. *

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
 	 * 
+	 *			 
 	 *		
 	 * 		
  • 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 * * 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 * @@ -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 * @@ -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();