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