base.js 경로 수정
parent
22645ee5af
commit
c27bd4d7ae
@ -1,867 +0,0 @@
|
||||
var wctx = {
|
||||
path:"",
|
||||
url:function(path) {
|
||||
return this.path + path;
|
||||
},
|
||||
home:function() {
|
||||
top.location.href = wctx.url("/");
|
||||
},
|
||||
current:function() {
|
||||
let str = top.location.href.replace(top.location.origin + wctx.path, "");
|
||||
let pos = str.indexOf("?");
|
||||
return pos < 0 ? str : str.substr(0, pos);
|
||||
},
|
||||
trace:true
|
||||
};
|
||||
|
||||
function log(msg) {
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
|
||||
function debug(msg) {
|
||||
if (wctx && wctx.trace)
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
|
||||
function trim(s) {
|
||||
if (null == s || undefined == s) return "";
|
||||
if ("string" != typeof(s)) return s;
|
||||
return s.replace(/^\s+/, "").replace(/\s+$/, "");
|
||||
}
|
||||
|
||||
function isEmpty(v) {
|
||||
if (v == undefined
|
||||
|| v == "undefined"
|
||||
|| v == null
|
||||
|| v == "null"
|
||||
) return true;
|
||||
|
||||
switch (typeof(v)) {
|
||||
case "string": return "" == trim(v);
|
||||
case "boolean": if (false == v) return false;
|
||||
case "number": if (0 == v) return false;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
function ifEmpty(v, nv) {
|
||||
if (!isEmpty(v)) return v;
|
||||
if (typeof(nv) == "function")
|
||||
return nv.apply();
|
||||
else
|
||||
return nv;
|
||||
}
|
||||
|
||||
function notEmpty(obj, msg) {
|
||||
if (isEmpty(obj))
|
||||
throw msg;
|
||||
return obj;
|
||||
}
|
||||
|
||||
function toQuery(map, encode) {
|
||||
if (isEmpty(map)) return "";
|
||||
|
||||
var query = [];
|
||||
for (var key in map) {
|
||||
var v = map[key];
|
||||
if (v != null && v == undefined) continue;
|
||||
if (v != null)
|
||||
switch (typeof(v)) {
|
||||
case "object":
|
||||
case "function": continue;
|
||||
}
|
||||
if (isEmpty(v))
|
||||
query.push(key);
|
||||
else
|
||||
query.push(key + "=" + (encode != false ? encodeURIComponent(v) : v));
|
||||
}
|
||||
return query.join("&");
|
||||
}
|
||||
|
||||
function uuid() {
|
||||
var hexDigits = "0123456789abcde",
|
||||
result = [];
|
||||
|
||||
for (var i = 0; i < 36; ++i)
|
||||
result[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
|
||||
result[14] = "4";
|
||||
result[19] = hexDigits.substr((result[19] & 0x3) | 0x8, 1);
|
||||
result[8] = result[13] = result[18] = result[23] = "-";
|
||||
|
||||
return result.join("");
|
||||
}
|
||||
|
||||
function wait(show) {
|
||||
if (show == false)
|
||||
$(".wait").attr("hidden","hidden");
|
||||
else
|
||||
$(".wait").removeAttr("hidden");
|
||||
}
|
||||
|
||||
var dialog = {
|
||||
title:"XIT",
|
||||
template:null,
|
||||
open:function(conf) {
|
||||
if (this.template)
|
||||
this.create(conf);
|
||||
else {
|
||||
var self = this;
|
||||
ajax.get({
|
||||
url:wctx.url("/webjars/html/dialog.html"),
|
||||
success:function(resp) {
|
||||
self.template = resp;
|
||||
self.create(conf);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
close:function(id) {
|
||||
$("#close" + id).click();
|
||||
},
|
||||
create:function(conf) {
|
||||
let last = {
|
||||
dlg: $("div.modal.show").last()[0],
|
||||
setZIndex: (obj, offset) => {
|
||||
if (!last.dlg) return;
|
||||
|
||||
let zIndex = Number($(last.dlg).css("z-index"));
|
||||
obj.css("z-index", zIndex + offset);
|
||||
}
|
||||
};
|
||||
|
||||
conf = conf || {};
|
||||
let id = conf.id || "dlg-" + uuid(),
|
||||
backdropID = id + "-backdrop",
|
||||
size = conf.size || "",
|
||||
tmpl = this.template
|
||||
.replace(/{id}/g, id)
|
||||
.replace(/{title}/g, conf.title || dialog.title);
|
||||
if (size)
|
||||
size = " modal-" + size;
|
||||
tmpl = tmpl.replace(/{size}/, size);
|
||||
dlg = $(tmpl).appendTo("body");
|
||||
|
||||
dlg.find(".modal-body").html(conf.content || "").fadeIn();
|
||||
|
||||
dlg.on("hidden.bs.modal", function() {// on dialog close
|
||||
$("#" + id +",#" + backdropID).remove(); // removes the dialog and its backdrop
|
||||
if (conf.onClose)
|
||||
conf.onClose();
|
||||
});
|
||||
|
||||
if (conf.onOK) {
|
||||
let footer = dlg.find(".modal-footer");
|
||||
footer.removeClass("hidden");
|
||||
footer.show();
|
||||
footer.find("button").unbind("click").click(function() {
|
||||
if (conf.getData) {
|
||||
var selected = conf.getData.apply();
|
||||
if (!selected) return;
|
||||
|
||||
conf.onOK(selected);
|
||||
dialog.close(id);
|
||||
} else {
|
||||
conf.onOK();
|
||||
dialog.close(id);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (conf.timeout)
|
||||
setTimeout(function(){dialog.close(id);}, conf.timeout);
|
||||
}
|
||||
|
||||
last.setZIndex(dlg, 10);
|
||||
dlg.draggable({handle: ".modal-header"}).modal("show");
|
||||
$(".modal-backdrop").each(function() { // gives id to its backdrop
|
||||
let backdrop = $(this);
|
||||
if (!backdrop.prop("id"))
|
||||
backdrop.prop("id", backdropID);
|
||||
});
|
||||
|
||||
if (conf.init)
|
||||
conf.init();
|
||||
},
|
||||
alert:function(conf) {
|
||||
var container = "<div class='container-fluid text-center' style='font-size:1.4em;'>{content}</div>";
|
||||
if ("string" == typeof(conf)) {
|
||||
conf = {
|
||||
content:container.replace(/{content}/g, conf)
|
||||
};
|
||||
} else {
|
||||
conf.content = container.replace(/{content}/g, conf.content);
|
||||
}
|
||||
conf.timeout = ifEmpty(conf.timeout, dialog.timeout);
|
||||
this.open(conf);
|
||||
}
|
||||
};
|
||||
|
||||
function onError(xhr, options, error) {
|
||||
if (xhr.readyState == 0)
|
||||
return dialog.alert("서버에 접근할 수 없습니다.");
|
||||
|
||||
var resp = JSON.parse(xhr.responseText);
|
||||
if (resp.handler)
|
||||
return eval(resp.handler);
|
||||
|
||||
var msgs = [];
|
||||
for (key in resp)
|
||||
msgs.push(resp[key])
|
||||
msgs = msgs.join("<br />");
|
||||
if (msgs)
|
||||
dialog.alert(msgs);
|
||||
}
|
||||
|
||||
var ajax = {
|
||||
request:function(options) {
|
||||
options.beforeSend = function(xhr) {
|
||||
if (wctx.csrf)
|
||||
xhr.setRequestHeader(wctx.csrf.header, wctx.csrf.token);
|
||||
if (!options.silent)
|
||||
wait();
|
||||
}
|
||||
if (!options.type) {
|
||||
if (options.data)
|
||||
options.type = "POST";
|
||||
}
|
||||
|
||||
var success = options.success;
|
||||
options.success = function(resp) {
|
||||
if ("string" == typeof resp)
|
||||
resp = trim(resp);
|
||||
|
||||
var stacktrace = resp.stacktrace;
|
||||
delete resp.stacktrace;
|
||||
|
||||
debug("response", resp);
|
||||
|
||||
if (!resp.failed)
|
||||
return success(resp);
|
||||
|
||||
dialog.alert({
|
||||
title:resp.title,
|
||||
content:[resp.description, resp.message].join("<br />")
|
||||
});
|
||||
|
||||
debug("stacktrace", stacktrace);
|
||||
};
|
||||
var handleError = options.error || onError;
|
||||
options.error = function(xhr, options, error) {
|
||||
wait(false);
|
||||
|
||||
debug("error", xhr, options, error);
|
||||
handleError(xhr, options, error);
|
||||
}
|
||||
|
||||
var handleComplete = options.complete || function(){};
|
||||
options.complete = function() {
|
||||
wait(false);
|
||||
handleComplete();
|
||||
};
|
||||
debug("request", options);
|
||||
$.ajax(options);
|
||||
},
|
||||
get:function(options) {
|
||||
options.type = "GET";
|
||||
ajax.request(options);
|
||||
},
|
||||
post:function(options) {
|
||||
options.type = "POST";
|
||||
ajax.request(options);
|
||||
}
|
||||
};
|
||||
|
||||
var json = {
|
||||
with:function(options) {
|
||||
options.dataType = "json";
|
||||
if (typeof(options.data) == "string") {
|
||||
options.contentType = "application/json; charset=UTF-8";
|
||||
}
|
||||
return options;
|
||||
},
|
||||
get:function(options) {
|
||||
ajax.get(json.with(options));
|
||||
},
|
||||
post:function(options) {
|
||||
ajax.post(json.with(options));
|
||||
}
|
||||
};
|
||||
|
||||
function upload(options) {
|
||||
options.enctype = "multipart/form-data";
|
||||
options.processData = options.contentType = false;
|
||||
var data = options.data,
|
||||
formData = new FormData();
|
||||
for (var key in data) {
|
||||
var val = data[key];
|
||||
if (!Array.isArray(val))
|
||||
formData.append(key, val);
|
||||
else {
|
||||
for (var i = 0; i < val.length; ++i)
|
||||
formData.append(key, val[i]);
|
||||
}
|
||||
}
|
||||
options.data = formData;
|
||||
ajax.post(options);
|
||||
}
|
||||
|
||||
$.fn.onEnterPress = function(handler) {
|
||||
return this.each(function(){
|
||||
$(this).keypress(function(evt){
|
||||
if (!handler || evt.which != 13) return;
|
||||
handler.apply();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function labelFor(input) {
|
||||
let selector = "label[for='{id}']",
|
||||
str = "string" == typeof(input),
|
||||
obj = $(input),
|
||||
key = str ? input
|
||||
: obj.attr("id") || obj.attr("name");
|
||||
if (!key) return "";
|
||||
|
||||
selector = selector.replace(/{id}/gi, key);
|
||||
return $(selector).text()
|
||||
|| obj.attr("title")
|
||||
|| obj.attr("placeholder");
|
||||
}
|
||||
|
||||
function validationFailureHandler() {
|
||||
var handler = {
|
||||
notice:function(msg, input) {
|
||||
dialog.alert({
|
||||
content:msg,
|
||||
onClose:function(){input.focus();}
|
||||
});
|
||||
},
|
||||
valueMissing: function(input) {
|
||||
handler.notice(labelFor(input) + "를(을) 입력하십시오.", input);
|
||||
},
|
||||
typeMismatch: function(input) {
|
||||
handler.notice(input.value + "는 " + labelFor(input) + "의 형식에 맞지 않습니다.", input);
|
||||
},
|
||||
tooLong: function(input) {
|
||||
handler.notice(input.value + " 값이 너무 깁니다.", input);
|
||||
},
|
||||
patternMismatch: function(input) {
|
||||
handler.notice(input.value + "는 " + labelFor(input) + "의 형식에 맞지 않습니다.", input);
|
||||
},
|
||||
rangeOverflow: function(input) {
|
||||
handler.notice(labelFor(input) + "의 값은 " + input.max + "보다 작아야 합니다.", input);
|
||||
},
|
||||
rangeUnderflow: function(input) {
|
||||
handler.notice(labelFor(input) + "의 값은 " + input.min + "보다 커야 합니다.", input);
|
||||
},
|
||||
stepMismatch: function(input) {
|
||||
handler.notice(labelFor(input) + "의 값은 " + input.step + "씩 증가 또는 감소해야 합니다.", input);
|
||||
}
|
||||
};
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**Returns the result of validation on the input object.<br />
|
||||
* The types of validation checks are those defined by input objects' basic validity property, which are
|
||||
* <ul><li>valueMissing</li>
|
||||
* <li>typeMismatch</li>
|
||||
* <li>tooLong</li>
|
||||
* <li>patternMismatch</li>
|
||||
* <li>rangeOverflow</li>
|
||||
* <li>rangeUnderflow</li>
|
||||
* <li>stepMismatch</li>
|
||||
* </ul>
|
||||
* To be effective, the input object must be set with attributes
|
||||
* <ul><li>required</li>
|
||||
* <li>type</li>
|
||||
* <li>maxLength</li>
|
||||
* <li>pattern</li>
|
||||
* <li>max</li>
|
||||
* <li>min</li>
|
||||
* <li>step</li>
|
||||
* </ul>
|
||||
* On failure, failureHandler takes over.<br />
|
||||
* The default handler from <code>validationFailureHandler()</code> displays a message
|
||||
* and puts the focus back to the input object.<br />
|
||||
* For the handler to display a message appropriate for the failure,
|
||||
* it is recommended to have a label associated with the input object.
|
||||
* @param input input object
|
||||
* @param failureHandler object that handles validation failure.<br />
|
||||
* If not provided, the default handler from <code>validationFailureHandler()</code> is used.
|
||||
* @returns
|
||||
* <ul><li>true if the value of the input object is valid</li>
|
||||
* <li>false otherwise</li>
|
||||
* </ul>
|
||||
*/
|
||||
function validInput(input, failureHandler) {
|
||||
var validity = input.validity;
|
||||
if (!validity || validity.valid) return true;
|
||||
|
||||
for (var key in validity) {
|
||||
if (!validity[key]) continue;
|
||||
|
||||
if (!failureHandler)
|
||||
failureHandler = validationFailureHandler();
|
||||
var handler = failureHandler[key];
|
||||
if (handler)
|
||||
handler(input);
|
||||
else {
|
||||
log("Handler not found for validation failure of " + key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**Returns the result of input validation on the selected input objects.<br />
|
||||
* The types of validation checks are those defined by input objects' basic validity property, which are
|
||||
* <ul><li>valueMissing</li>
|
||||
* <li>typeMismatch</li>
|
||||
* <li>tooLong</li>
|
||||
* <li>patternMismatch</li>
|
||||
* <li>rangeOverflow</li>
|
||||
* <li>rangeUnderflow</li>
|
||||
* <li>stepMismatch</li>
|
||||
* </ul>
|
||||
* To be effective, the input objects must be set with attributes
|
||||
* <ul><li>required</li>
|
||||
* <li>type</li>
|
||||
* <li>maxLength</li>
|
||||
* <li>pattern</li>
|
||||
* <li>max</li>
|
||||
* <li>min</li>
|
||||
* <li>step</li>
|
||||
* </ul>
|
||||
* On failure, failureHandler takes over.<br />
|
||||
* The default handler from <code>validationFailureHandler()</code> displays a message
|
||||
* and puts the focus back to the offending input object.<br />
|
||||
* For the handler to display a message appropriate for the failure,
|
||||
* it is recommended to have labels associated with input objects.
|
||||
* @param failureHandler object that handles validation failure.<br />
|
||||
* If not provided, the default handler from <code>validationFailureHandler()</code> is used.
|
||||
* @returns
|
||||
* <ul><li>true if the input values of the selected objects are valid</li>
|
||||
* <li>false otherwise</li>
|
||||
* </ul>
|
||||
*/
|
||||
$.fn.validInputs = function(failureHandler) {
|
||||
var valid = true;
|
||||
this.each(function(){
|
||||
var input = $(this);
|
||||
if (!(valid = validInput(input[0], failureHandler))) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return valid;
|
||||
}
|
||||
|
||||
$.fn.getValues = function(propertyMapper) {
|
||||
var inputValues = {};
|
||||
this.each(function() {
|
||||
var input = $(this),
|
||||
key = input.prop("id") || input.prop("name"),
|
||||
value = input.val();
|
||||
if (isEmpty(key) || value === undefined) return;
|
||||
|
||||
var type = input.prop("type");
|
||||
if ("file" == type) {
|
||||
value = input.get(0).files;
|
||||
} else if (["checkbox", "radio"].indexOf(type) > -1) {
|
||||
if (!input.is(":checked")) return;
|
||||
}
|
||||
|
||||
var stored = inputValues[key];
|
||||
if (stored === undefined) {
|
||||
inputValues[key] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(stored)) {
|
||||
if (!Array.isArray(value))
|
||||
stored.push(value);
|
||||
else
|
||||
stored = stored.concat(value);
|
||||
} else {
|
||||
var array = [stored];
|
||||
if (!Array.isArray(value))
|
||||
array.push(value);
|
||||
else
|
||||
array = array.concat(value);
|
||||
inputValues[key] = array;
|
||||
}
|
||||
});
|
||||
|
||||
if (propertyMapper) { // propertyMapper = {property:valueProvider, ...}
|
||||
for (var property in propertyMapper) {
|
||||
var valueProvider = propertyMapper[property],
|
||||
value = undefined;
|
||||
switch (typeof(valueProvider)) {
|
||||
case "string":
|
||||
value = inputValues[valueProvider];
|
||||
break;
|
||||
case "function":
|
||||
value = valueProvider(inputValues);
|
||||
break;
|
||||
}
|
||||
if (value === undefined) continue;
|
||||
|
||||
delete inputValues[valueProvider];
|
||||
inputValues[property] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return inputValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param config
|
||||
* {start:0,
|
||||
* fetchSize:10,
|
||||
* totalSize:135,
|
||||
* links:3,
|
||||
* first:function(index, label){return "..."},
|
||||
* previous:function(index, label){return "..."},
|
||||
* link:function(index, label){return "..."},
|
||||
* current:function(index, label){return "..."},
|
||||
* next:function(index, label){return "..."},
|
||||
* last:function(index, label){return "..."}
|
||||
* }
|
||||
* @returns {String}
|
||||
*/
|
||||
function paginate(config) {
|
||||
var rc = config.totalSize || 0;
|
||||
// if (!rc) return "";
|
||||
|
||||
var fetchCount = config.fetchSize || 0;
|
||||
// if (!fetchCount) return "";
|
||||
|
||||
var fetch = {
|
||||
all:0,
|
||||
none:-1,
|
||||
count:function(elementCount, size) {
|
||||
if (!elementCount || size == fetch.all) return 1;
|
||||
return parseInt((elementCount / size) + ((elementCount % size) == 0 ? 0 : 1));
|
||||
},
|
||||
end:function(elementCount, size, start) {
|
||||
if (size < fetch.all) throw "Invalid size: " + size;
|
||||
if (elementCount < 0) throw "Invalid elementCount: " + elementCount;
|
||||
var last = elementCount - 1;
|
||||
if (size == fetch.all) return last;
|
||||
return Math.min(last, start + size -1);
|
||||
},
|
||||
page:function(current, count) {
|
||||
return parseInt(count < 1 ? 0 : current / count);
|
||||
},
|
||||
band:function(page, visibleLinks) {
|
||||
return parseInt(visibleLinks < 1 ? 0 : page / visibleLinks);
|
||||
}
|
||||
};
|
||||
var lc = fetch.count(rc, fetchCount);
|
||||
if (lc < 2) return "";
|
||||
|
||||
var links = ifEmpty(config.links, fetch.all),
|
||||
page = fetch.page(ifEmpty(config.start, 0), fetchCount),
|
||||
band = fetch.band(page, links),
|
||||
tags = {
|
||||
link:function(tag, index, label) {
|
||||
return !tag ? "" : tag(index, label);
|
||||
},
|
||||
first:function() {
|
||||
return band < 2 ? "" : tags.link(config.first, 0, 1);
|
||||
},
|
||||
previous:function() {
|
||||
if (band < 1) return "";
|
||||
var prevBand = band - 1,
|
||||
prevPage = (prevBand * links) + (links - 1),
|
||||
fromRec = prevPage * fetchCount;
|
||||
return tags.link(config.previous, fromRec, prevPage + 1);
|
||||
},
|
||||
visibleLinks:function() {
|
||||
var s = "",
|
||||
fromPage = links == fetch.all ? 0 : band * links,
|
||||
toPage = links == fetch.all ? lc : Math.min(lc, fromPage + links);
|
||||
for (var i = fromPage; i < toPage; ++i) {
|
||||
var fromRec = i * fetchCount,
|
||||
label = i + 1;
|
||||
s += tags.link(i == page ? config.current : config.link, fromRec, label);
|
||||
}
|
||||
return s;
|
||||
},
|
||||
next:function(bandCount) {
|
||||
bandCount = parseInt(bandCount);
|
||||
if (bandCount - band < 2) return "";
|
||||
|
||||
var nextBand = band + 1,
|
||||
page = nextBand * links,
|
||||
fromRec = page * fetchCount;
|
||||
return tags.link(config.next, fromRec, page + 1);
|
||||
},
|
||||
last:function(bandCount) {
|
||||
bandCount = parseInt(bandCount);
|
||||
var lastBand = bandCount - 1;
|
||||
if (lastBand - band < 2) return "";
|
||||
|
||||
var pages = lastBand * links,
|
||||
fromRec = pages * fetchCount;
|
||||
return tags.link(config.last, fromRec, pages + 1);
|
||||
}
|
||||
},
|
||||
tag = "";
|
||||
if (links != fetch.all) {
|
||||
tag += tags.first();
|
||||
tag += tags.previous();
|
||||
}
|
||||
tag += tags.visibleLinks();
|
||||
if (links != fetch.all) {
|
||||
var bandCount = parseInt(lc / links);
|
||||
bandCount += lc % links == 0 ? 0 : 1;
|
||||
tag += tags.next(bandCount);
|
||||
tag += tags.last(bandCount);
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
$.fn.paginate = function(config) {
|
||||
return this.each(function(){
|
||||
var tag = paginate(config),
|
||||
container = $(this);
|
||||
if (tag)
|
||||
container.html(tag).show();
|
||||
else {
|
||||
if (config.hideIfEmpty != false)
|
||||
container.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.setPaging = function(config) {
|
||||
config.links = 5;
|
||||
config.first = function(index, label) {return '<li onclick="{func};" class="page-item first"><a class="page-link"><i class="tf-icon bx bx-chevrons-left"></i></a></li>'.replace(/{func}/, config.func.replace(/{index}/, label));};
|
||||
config.previous = function(index, label) {return '<li onclick="{func}" class="page-item prev"><a class="page-link"><i class="tf-icon bx bx-chevron-left"></i></a></li>'.replace(/{func}/, config.func.replace(/{index}/, label));};
|
||||
config.link = function(index, label) {return '<li onclick="{func}" class="page-item"><a class="page-link">{label}</a></li>'.replace(/{func}/, config.func.replace(/{index}/, label)).replace(/{label}/, label);};
|
||||
config.current = function(index, label) {return '<li class="page-item active"><a class="page-link">{label}</a></li>'.replace(/{label}/, label);};
|
||||
config.next = function(index, label) {return '<li onclick="{func}" class="page-item next"><a class="page-link"><i class="tf-icon bx bx-chevron-right"></i></a></li>'.replace(/{func}/, config.func.replace(/{index}/, label));};
|
||||
config.last = function(index, label) {return '<li onclick="{func}" class="page-item last"><a class="page-link"><i class="tf-icon bx bx-chevrons-right"></i></a></li>'.replace(/{func}/, config.func.replace(/{index}/, label));};
|
||||
|
||||
return this.each(function(){
|
||||
let list = config.list,
|
||||
start = list.empty ? 0 : config.start + 1,
|
||||
end = list.empty ? 0 : config.start + list.length,
|
||||
pagingInfo = list.empty ? "" : start + " ~ " + numberFormat.format(end) + " / " + numberFormat.format(config.totalSize);
|
||||
$("#"+ config.prefix + "PagingInfo").html(pagingInfo);
|
||||
|
||||
let tag = paginate(config),
|
||||
container = $(this);
|
||||
if (tag)
|
||||
container.html(tag.replace(/{func}/g, config.func)).show();
|
||||
else {
|
||||
if (config.hideIfEmpty != false)
|
||||
container.hide();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.setPagingInfo = function(config) {
|
||||
return this.each(function(){
|
||||
let list = config.list;
|
||||
let pagingInfo = list.empty ? "" : 1
|
||||
+ " ~ "
|
||||
+ numberFormat.format(list.length)
|
||||
+ " / " + numberFormat.format(config.totalSize);
|
||||
$("#"+ config.prefix + "PagingInfo").html(pagingInfo);
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.setCurrentRow = function(val) {
|
||||
if (!val) return;
|
||||
|
||||
return this.each(function() {
|
||||
var e = $(this);
|
||||
e.find("tr").each(function(){
|
||||
var tr = $(this),
|
||||
current = val == tr.attr("data-key");
|
||||
if (current)
|
||||
tr.addClass("current-row");
|
||||
else
|
||||
tr.removeClass("current-row");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class FormFields {
|
||||
constructor(selector) {
|
||||
this.form = document.querySelector(this.selector = selector);
|
||||
this.children = ["input", "select", "textarea"].map(tag => this.selector + " " + tag).join(",");
|
||||
this.datamap = [];
|
||||
}
|
||||
|
||||
set(ctrl, obj) {
|
||||
let setChanged = evt => {
|
||||
let input = evt.target,
|
||||
name = input.getAttribute("data-map"),
|
||||
val = input.value;
|
||||
ctrl.setValue(name, val);
|
||||
};
|
||||
document.querySelectorAll(this.children).forEach(input => {
|
||||
let prop = input.getAttribute("data-map")
|
||||
|| input.name
|
||||
|| input.id;
|
||||
if (!prop) return;
|
||||
|
||||
input.removeEventListener("change", setChanged);
|
||||
|
||||
let dataItem = obj instanceof DataItem,
|
||||
value = dataItem ? obj.getValue(prop) : obj[prop],
|
||||
inputType = (input.type || input.tagName || "").toLowerCase();
|
||||
|
||||
switch (inputType) {
|
||||
case "radio": input.checked = value && value == input.value; break;
|
||||
case "checkbox": input.checked = value && value == input.value; break;
|
||||
case "select":
|
||||
for(let option of input.options) {
|
||||
option.selected = option.value == value;
|
||||
}
|
||||
break;
|
||||
default: input.value = ifEmpty(value, ""); break;
|
||||
}
|
||||
input.addEventListener("change", setChanged);
|
||||
});
|
||||
}
|
||||
|
||||
get() {
|
||||
let obj = {};
|
||||
document.querySelectorAll(this.children).forEach(input => {
|
||||
let property = input.name || input.id;
|
||||
let value = input.value;
|
||||
if ("radio" == input.type) {
|
||||
if (input.checked)
|
||||
obj[property] = value;
|
||||
} else {
|
||||
obj[property] = value;
|
||||
}
|
||||
// log(property, value, "radio" == input.type ? "radio" : "", input.checked ? "checked" : "");
|
||||
});
|
||||
return obj;
|
||||
//return Object.fromEntries(new FormData(this.form).entries());
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.datePicker = function(selector) {
|
||||
return this.each(function() {
|
||||
$(this)
|
||||
.datepicker()
|
||||
.attr("maxlength", "10")
|
||||
.on("input",function(e) {
|
||||
if (this.value.length <= 0
|
||||
|| this.value.length != this.selectionStart
|
||||
)
|
||||
return;
|
||||
|
||||
var value = this.value.replaceAll("-","");
|
||||
if (value.length > 7) {
|
||||
this.value = value.substring(0,4)+"-"+value.substring(4,6)+"-"+value.substring(6);
|
||||
} else if (value.length > 5) {
|
||||
this.value = value.substring(0,4)+"-"+value.substring(4);
|
||||
}
|
||||
})
|
||||
.on("paste", function(e) {
|
||||
var value = e.originalEvent.clipboardData.getData('text');
|
||||
if (value.length == 8)
|
||||
this.value = value.substring(0,4)+"-"+value.substring(4,6)+"-"+value.substring(6);
|
||||
});
|
||||
|
||||
var calendarIcon = $(this).next("button.bx-calendar");
|
||||
if (calendarIcon.length > 0) {
|
||||
$(calendarIcon).on("click", function() {
|
||||
$(this).prev().focus();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fromSource 시작값을 갖는 input의 selector
|
||||
* @param toSource 종료값을 갖는 input의 selector
|
||||
*/
|
||||
function inputsInRange(fromSource, toSource) {
|
||||
var from = $(fromSource),
|
||||
to = $(toSource),
|
||||
compare = function() {
|
||||
var fromVal = from.val() || "",
|
||||
toVal = to.val() || "",
|
||||
ok = toVal >= fromVal;
|
||||
if (ok) return;
|
||||
|
||||
if ($(this)[0] == from[0])
|
||||
to.val(from.val())
|
||||
else
|
||||
from.val(to.val());
|
||||
};
|
||||
from.change(compare);
|
||||
to.change(compare);
|
||||
}
|
||||
|
||||
function ignore() {
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
|
||||
function fileInput(conf) {
|
||||
conf = conf || {};
|
||||
var name = conf.name || "upload",
|
||||
tag = "<input type='file' name='{name}'{multiple}{accept} style='display:none;'>"
|
||||
.replace(/{name}/, name)
|
||||
.replace(/{multiple}/, conf.multiple ? " multiple" : "")
|
||||
.replace(/{accept}/, conf.accept ? " accept='" + conf.accept + "'" : ""),
|
||||
obj = {
|
||||
name:name,
|
||||
input:null,
|
||||
files:[],
|
||||
|
||||
select:function(onSelect) {
|
||||
if (!obj.input) {
|
||||
var input = obj.input = $(tag);
|
||||
$("body").append(input);
|
||||
input.change(function() {
|
||||
var files = $(this).get(0).files,
|
||||
length = files.length,
|
||||
selected = [];
|
||||
for (var i = 0; i < length; ++i) {
|
||||
var file = files[i];
|
||||
file.id = name + (obj.files.length);
|
||||
selected.push(file);
|
||||
obj.files.push(file);
|
||||
}
|
||||
onSelect(selected);
|
||||
})
|
||||
}
|
||||
obj.input.click();
|
||||
},
|
||||
|
||||
getFiles:function() {
|
||||
return obj.files;
|
||||
},
|
||||
|
||||
remove:function(id) {
|
||||
if (!id) return;
|
||||
|
||||
var files = obj.files;
|
||||
for (var i = 0; i < files.length; ++i) {
|
||||
var file = files[i];
|
||||
if (id == file.id) {
|
||||
files.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
clear:function() {
|
||||
if (obj.input)
|
||||
$(obj.input).remove();
|
||||
obj.input = null;
|
||||
obj.files.forEach(function(file) {delete file;});
|
||||
obj.files = [];
|
||||
}
|
||||
};
|
||||
return obj;
|
||||
}
|
Loading…
Reference in New Issue