yourteam 封裝套件引入
This commit is contained in:
		
							parent
							
								
									006f100c9c
								
							
						
					
					
						commit
						a738e27b22
					
				@ -2061,7 +2061,7 @@ License: You must have a valid license purchased only from wrapbootstrap.com (li
 | 
			
		||||
    <script src="lib/datagrid/datatables/datatables.bundle.js"></script>
 | 
			
		||||
    <script>
 | 
			
		||||
          
 | 
			
		||||
        $("#app").load("dashboard.html");
 | 
			
		||||
        $("#app").load("_dashboard.html");
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
    </script>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4435
									
								
								Frontend/js/bootstrap.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4435
									
								
								Frontend/js/bootstrap.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										48
									
								
								Frontend/js/yourteam/plugins/yt-tab.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								Frontend/js/yourteam/plugins/yt-tab.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var _ytTabInited = []
 | 
			
		||||
$(function () {
 | 
			
		||||
    $("[data-tabname][data-target]:not([data-tabrole='child'])").each(function (index, value) {
 | 
			
		||||
        let tabName = $(value).data("tabname");
 | 
			
		||||
        if (_ytTabInited.indexOf(tabName) == -1) { 
 | 
			
		||||
            var ytTab = new YTTab({ tabName: tabName })     
 | 
			
		||||
            _ytTabInited.push(tabName);
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
class YTTab {
 | 
			
		||||
    constructor(option = {}) {
 | 
			
		||||
        this.tabName = option.tabName ?? null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    init();
 | 
			
		||||
 | 
			
		||||
    init() {
 | 
			
		||||
        $(`[data-tabname=${this.tabName}][data-target][data-tabrole='child']`).css("display", "none");
 | 
			
		||||
        $(`[data-tabname=${this.tabName}][data-target][data-tabrole='child']`).first().show();
 | 
			
		||||
 | 
			
		||||
        this.event();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    event() {
 | 
			
		||||
        // custom tab
 | 
			
		||||
        // example : 
 | 
			
		||||
        // <button id="test" data-target="#okDiv" data-tabname="tab1"></button>
 | 
			
		||||
        // <div id="okDiv" data-tabrole="child" data-tabname="tab1"></div>
 | 
			
		||||
        $("body").on("click", `[data-tabname=${this.tabName}][data-target]`, function () {
 | 
			
		||||
            let target = $(this).data("target");
 | 
			
		||||
            let obj = this;
 | 
			
		||||
            let tabName = $(target).data("tabname");
 | 
			
		||||
            if (tabName) {
 | 
			
		||||
                if ($(target).data("tabrole") == "child") {
 | 
			
		||||
                    $(obj).trigger("yt:tab:show");
 | 
			
		||||
                    $(`[data-tabname='${tabName}'][data-tabrole='child']`).css("opacity", 0).hide();
 | 
			
		||||
                    $(target).show().animate({ opacity: 1 }, 200, function () {
 | 
			
		||||
                        $(obj).trigger("yt:tab:shown");
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										108
									
								
								Frontend/js/yourteam/plugins/yt-tooltip.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								Frontend/js/yourteam/plugins/yt-tooltip.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,108 @@
 | 
			
		||||
$.fn.YTTooltip = function (option) {
 | 
			
		||||
    let eleArr = [];
 | 
			
		||||
 | 
			
		||||
    this.each(function (index, value) {
 | 
			
		||||
 | 
			
		||||
        let obj = {
 | 
			
		||||
            ele: value,
 | 
			
		||||
            isShowArr: [],
 | 
			
		||||
            html: $(option.html) || '',
 | 
			
		||||
            tooltipDiv: null,
 | 
			
		||||
            direction: option.direction || 'bottom',
 | 
			
		||||
            toggle: "click",
 | 
			
		||||
            hideTooltipEvent: hideTooltipEvent,
 | 
			
		||||
            onShow: option.onShow || null,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        if (obj.toggle == "hover") {
 | 
			
		||||
            obj.toggle == "mouseenter"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $(obj.ele).on(obj.toggle, function () {
 | 
			
		||||
            let tooId = $(this).data("yttooltipid");
 | 
			
		||||
            let display = "flex";
 | 
			
		||||
            //顯示 tooltip 程序 及 存入已顯示紀錄arr
 | 
			
		||||
            if (!tooId || obj.isShowArr.indexOf(tooId) == -1) {
 | 
			
		||||
                let ranId = Math.floor((Math.random() * (9999999 - 1000000)) + 1000000);
 | 
			
		||||
                obj.isShowArr.push(ranId);
 | 
			
		||||
                let clone = $(obj.html);
 | 
			
		||||
                //body 元素 高寬
 | 
			
		||||
                let bodyWidth = $("body")[0].offsetWidth;
 | 
			
		||||
                let bodyHeight = $("body")[0].offsetHeight;
 | 
			
		||||
                //計算引用元素 offset
 | 
			
		||||
                let offset = $(this).offset();
 | 
			
		||||
                //引用元素 高寬
 | 
			
		||||
                let width = $(this)[0].offsetWidth;
 | 
			
		||||
                let height = $(this)[0].offsetHeight;
 | 
			
		||||
 | 
			
		||||
                $(this).data("yttooltipid", ranId);
 | 
			
		||||
                $(clone).attr("id", "yt_tooltip_" + ranId)
 | 
			
		||||
                $("body").append(clone);
 | 
			
		||||
                obj.tooltipDiv = clone;
 | 
			
		||||
                //顯示 tooltip
 | 
			
		||||
                $(clone).css({ "display": display, "position": "absolute" });
 | 
			
		||||
                obj.onShow ? obj.onShow(clone,obj) : "";
 | 
			
		||||
                //tooltip 高寬
 | 
			
		||||
                let toolWidth = $(clone)[0].offsetWidth;
 | 
			
		||||
                let toolHeight = $(clone)[0].offsetHeight;
 | 
			
		||||
 | 
			
		||||
                let left = offset.left + width + toolWidth > bodyWidth ? offset.left - toolWidth : offset.left + width;
 | 
			
		||||
                let top = offset.top + height + toolHeight > bodyHeight ? offset.top - toolHeight : offset.top + height;
 | 
			
		||||
 | 
			
		||||
                //計算 位置
 | 
			
		||||
                if (obj.direction == "left") {
 | 
			
		||||
                    left = offset.left < toolWidth ? offset.left + width + 5 : offset.left - toolWidth - 10;
 | 
			
		||||
                } else if (obj.direction == "right") {
 | 
			
		||||
                    left = offset.left + toolWidth + width > bodyWidth ? offset.left - toolWidth - 10 : offset.left + width + 10;
 | 
			
		||||
                } else if (obj.direction == "bottom") {
 | 
			
		||||
                    top = offset.top + toolHeight + height > bodyHeight ? offset.top - toolHeight - 10 : offset.top + height + 10;
 | 
			
		||||
                } else if (obj.direction == "top") {
 | 
			
		||||
                    top = offset.top < toolHeight ? offset.top + height + 5 : offset.top - toolHeight - 10;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (obj.direction == "left" || obj.direction == "right") {
 | 
			
		||||
                    $(clone).css({ left: left, top: offset.top });
 | 
			
		||||
                } else if (obj.direction == "top" || obj.direction == "bottom"){
 | 
			
		||||
                    $(clone).css({ left: offset.left, top: top});
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                obj.hideTooltipEvent(tooId);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (obj.toggle == "hover") {
 | 
			
		||||
                $(obj.tooltipDiv).off("mouseover").on("mouseover", function () {
 | 
			
		||||
                    $(this).css("display", "flex");
 | 
			
		||||
                })
 | 
			
		||||
                $(obj.tooltipDiv).off("mouseleave").on("mouseleave", function () {
 | 
			
		||||
                    let tooId = $(this).attr("id").split("yt_tooltip_")[1];
 | 
			
		||||
                    obj.hideTooltipEvent(tooId);
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        if (obj.toggle == "hover") {
 | 
			
		||||
            $(obj.ele).on("mouseleave", function (e) {
 | 
			
		||||
                let tooId = $(this).data("yttooltipid");
 | 
			
		||||
                hideTooltipEvent(tooId);
 | 
			
		||||
                e.stopPropagation();
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        function hideTooltipEvent(tooId) {
 | 
			
		||||
            $("#yt_tooltip_" + tooId).hide();
 | 
			
		||||
            setTimeout(function () {
 | 
			
		||||
                if ($("#yt_tooltip_" + tooId).css("display") == "none") {
 | 
			
		||||
                    obj.isShowArr.splice($.inArray(tooId, obj.isShowArr), 1);
 | 
			
		||||
                    $("#yt_tooltip_" + tooId).remove();
 | 
			
		||||
                }
 | 
			
		||||
            }, 100)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        eleArr.push(obj);
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    let result = eleArr.filter(x => this.toArray().findIndex(y => y == x.ele) != -1)[0];
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										250
									
								
								Frontend/js/yourteam/yourteam.ajax.class.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								Frontend/js/yourteam/yourteam.ajax.class.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,250 @@
 | 
			
		||||
var YourTeam = YourTeam || {};
 | 
			
		||||
/**
 | 
			
		||||
 * This is a description of the Ajax constructor function.
 | 
			
		||||
 * @class Ajax
 | 
			
		||||
 * @classdesc This is a description of the Ajax class.
 | 
			
		||||
 * @author Darren Chen @2021/02/06
 | 
			
		||||
 * @copyright Darren Chen @Your Team Co., Ltd. 2021
 | 
			
		||||
 */
 | 
			
		||||
class Ajax {
 | 
			
		||||
    /**
 | 
			
		||||
    * constructor
 | 
			
		||||
    * @constructor
 | 
			
		||||
    *  @param {String} apiUrl API URL. def="".
 | 
			
		||||
    *  @param {String} sendData the data object which you will be send. def= null.
 | 
			
		||||
    *  @param {Fcnction} successFunction successFunction. def=null.(use def successFunction)
 | 
			
		||||
    *  @param {Fcnction} errorFunction errorFunction. def=null.(use def successFunction)
 | 
			
		||||
    *  @param {String} type HTTP METHOD. def="GET".
 | 
			
		||||
    *  @param {Object} conType content type
 | 
			
		||||
    *  @param {String} dataType data format. def="JSON".
 | 
			
		||||
    *  @param {String} isAsync the api synchronization. def=false.
 | 
			
		||||
    *  @return {Object} this
 | 
			
		||||
    */
 | 
			
		||||
    constructor(apiUrl = "", sendData = null, successFunction = null, errorFunction = null, type = "GET", isAsync = false, conType = this.contentType.Json, dataType = "JSON") {
 | 
			
		||||
        this.conType = conType;
 | 
			
		||||
        this.apiUrl = apiUrl;
 | 
			
		||||
        this.isAsync = isAsync;
 | 
			
		||||
        this.type = type;
 | 
			
		||||
        this.dataType = dataType;
 | 
			
		||||
        this.sendData = sendData;
 | 
			
		||||
        if (successFunction) this.successFunction = successFunction;
 | 
			
		||||
        if (errorFunction) this.errorFunction = errorFunction;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
    * dataToString
 | 
			
		||||
    * @description convert the data object to string
 | 
			
		||||
    *  @param {Object} data API URL. def="".
 | 
			
		||||
    *  @return {String} strJsonData
 | 
			
		||||
    */
 | 
			
		||||
    dataToString = function (data) {
 | 
			
		||||
        let strJsonData = data ? (data.Data ? JSON.stringify(data.Data) : null) : null;
 | 
			
		||||
        return strJsonData;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
    * beforeSendFunction
 | 
			
		||||
    * @description beforeSendFunction
 | 
			
		||||
    */
 | 
			
		||||
    beforeSendFunction = function () {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
    * successFunction
 | 
			
		||||
    * @description successFunction
 | 
			
		||||
    * @param {Object} data the data object from the api return
 | 
			
		||||
    * @return {Object} data
 | 
			
		||||
    */
 | 
			
		||||
    successFunction = function (data) {
 | 
			
		||||
        return data;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
    * errorFunction
 | 
			
		||||
    * @description errorFunction
 | 
			
		||||
    * @param {Object} xhr HTTP STATUS
 | 
			
		||||
    * @param {Object} ajaxOptions the ajax option message
 | 
			
		||||
    * @param {String} thrownError the error message
 | 
			
		||||
    */
 | 
			
		||||
    errorFunction = function (xhr, ajaxOptions, thrownError) {
 | 
			
		||||
        if (xhr.status != "201" && xhr.status != "204") {
 | 
			
		||||
            console.log(xhr.status);
 | 
			
		||||
            console.log(thrownError);
 | 
			
		||||
            window.alert("執行失敗,請聯絡客服人員。");
 | 
			
		||||
        } else if (xhr.status == "401") {
 | 
			
		||||
            window.alert("登入時間超時,請重新登入!");
 | 
			
		||||
            location.href = "~/Login/Login";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
    * completeFunction
 | 
			
		||||
    * @description completeFunction
 | 
			
		||||
    */
 | 
			
		||||
    completeFunction = function () {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
    * content type
 | 
			
		||||
    * @description content type
 | 
			
		||||
    */
 | 
			
		||||
    contentType = {
 | 
			
		||||
        Json: 1,
 | 
			
		||||
        FormData : 2
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
    * enum 
 | 
			
		||||
    * @description enum
 | 
			
		||||
    * @param {Object} eo object
 | 
			
		||||
    * @return {Object} enum
 | 
			
		||||
    */
 | 
			
		||||
    enums(eo) {
 | 
			
		||||
        var enums = function () { };
 | 
			
		||||
        for (var key in eo) {
 | 
			
		||||
            var enumObject = new enums();
 | 
			
		||||
            enums[key] = eo[key];
 | 
			
		||||
        }
 | 
			
		||||
        return enums;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
    * send
 | 
			
		||||
    * @description send
 | 
			
		||||
    * @param {Object} conType content type
 | 
			
		||||
    * @param {Object} sendData send data
 | 
			
		||||
    * @param {Function} successFunction the ajax success function
 | 
			
		||||
    * @param {Function} errorFunction the ajax error function
 | 
			
		||||
    * @return {Object} this
 | 
			
		||||
    */
 | 
			
		||||
    send = function (conType = this.contentType.Json, sendData = null, successFunction = null, errorFunction = null) {
 | 
			
		||||
 | 
			
		||||
        if (!CheckMultiSend(this.apiUrl, this.type, this.dataToString(this.sendData))) { //連點防呆
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        if (sendData) {
 | 
			
		||||
            this.sendData = sendData;
 | 
			
		||||
        }
 | 
			
		||||
        if (successFunction) {
 | 
			
		||||
            this.successFunction = successFunction;
 | 
			
		||||
        }
 | 
			
		||||
        if (errorFunction) {
 | 
			
		||||
            this.errorFunction = errorFunction;
 | 
			
		||||
        }
 | 
			
		||||
        if (conType === this.contentType.Json) {
 | 
			
		||||
            $.ajax({
 | 
			
		||||
                url: this.apiUrl,
 | 
			
		||||
                async: this.isAsync,
 | 
			
		||||
                type: this.type,
 | 
			
		||||
                dataType: this.dataType,
 | 
			
		||||
                traditional: true,
 | 
			
		||||
                contentType: "application/json; charset=utf-8",
 | 
			
		||||
                data: this.dataToString(this.sendData),
 | 
			
		||||
 | 
			
		||||
                //cache: false,
 | 
			
		||||
                //processData: false,
 | 
			
		||||
 | 
			
		||||
                beforeSend: this.beforeSendFunction,
 | 
			
		||||
                success: this.successFunction,
 | 
			
		||||
                error: this.errorFunction,
 | 
			
		||||
                complete: this.completeFunction,
 | 
			
		||||
                statusCode: {
 | 
			
		||||
                    201: this.successFunction
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        else if (conType === this.contentType.FormData) {
 | 
			
		||||
            $.ajax({
 | 
			
		||||
                url: this.apiUrl,
 | 
			
		||||
                async: this.isAsync,
 | 
			
		||||
                type: this.type,
 | 
			
		||||
                dataType: this.dataType,
 | 
			
		||||
 | 
			
		||||
                traditional: true,
 | 
			
		||||
 | 
			
		||||
                contentType: false,
 | 
			
		||||
                enctype: 'multipart/form-data',
 | 
			
		||||
                data: this.sendData,
 | 
			
		||||
                cache: false,
 | 
			
		||||
                processData: false,
 | 
			
		||||
                beforeSend: this.beforeSendFunction,
 | 
			
		||||
                success: this.successFunction,
 | 
			
		||||
                error: this.errorFunction,
 | 
			
		||||
                complete: this.completeFunction
 | 
			
		||||
            });
 | 
			
		||||
            alert(conType);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            console.error("the content type is null.");
 | 
			
		||||
        }
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
YourTeam.Ajax = YourTeam.Ajax || Ajax;
 | 
			
		||||
 | 
			
		||||
var ckeckMultiSendArr = [];
 | 
			
		||||
function CheckMultiSend(url, type, data) {
 | 
			
		||||
    //根據 url type data 
 | 
			
		||||
    let text = String(url) + String(type);
 | 
			
		||||
    if (type != "GET") {
 | 
			
		||||
        if (ckeckMultiSendArr.indexOf(text) == -1) {
 | 
			
		||||
            ckeckMultiSendArr.unshift(text);
 | 
			
		||||
            let timer = setInterval(function () {
 | 
			
		||||
                ckeckMultiSendArr.splice(0);
 | 
			
		||||
                clearInterval(timer);
 | 
			
		||||
            }, 500)
 | 
			
		||||
        } else {
 | 
			
		||||
            return false
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
//var YourTeamAjax = {
 | 
			
		||||
//    apiUrl: "",
 | 
			
		||||
//    isAsync: false,
 | 
			
		||||
//    type: "GET",
 | 
			
		||||
//    dataType: "JSON",
 | 
			
		||||
//    sendData: null,
 | 
			
		||||
//    dataToString: function (data) {
 | 
			
		||||
//        let strJsonData = data ? (data.Data ? JSON.stringify(data.Data) : null) : null;
 | 
			
		||||
//        return strJsonData;
 | 
			
		||||
//    },
 | 
			
		||||
//    beforeSendFunction: function () {
 | 
			
		||||
//        $.blockUI({ message: '<h1><img src="/Content/img/loading.gif" style="width:200px;" /> Loding...</h1>' });
 | 
			
		||||
//    },
 | 
			
		||||
//    successFunction: function (data) {
 | 
			
		||||
//        return data;
 | 
			
		||||
//    },
 | 
			
		||||
//    errorFunction: function (xhr, ajaxOptions, thrownError) {
 | 
			
		||||
//        if (xhr.status != "201") {
 | 
			
		||||
//            console.log(xhr.status);
 | 
			
		||||
//            console.log(thrownError);
 | 
			
		||||
//            window.alert("執行失敗,請聯絡YourTeam客服人員。");
 | 
			
		||||
//        }
 | 
			
		||||
//    },
 | 
			
		||||
//    completeFunction: function () {
 | 
			
		||||
//        $.unblockUI();
 | 
			
		||||
//    },
 | 
			
		||||
//    send: function (sendData = null, successFunction = null, errorFunction = null) {
 | 
			
		||||
//        if (sendData) {
 | 
			
		||||
//            this.sendData = sendData;
 | 
			
		||||
//        }
 | 
			
		||||
//        if (successFunction) {
 | 
			
		||||
//            this.successFunction = successFunction;
 | 
			
		||||
//        }
 | 
			
		||||
//        if (errorFunction) {
 | 
			
		||||
//            this.errorFunction = errorFunction;
 | 
			
		||||
//        }
 | 
			
		||||
//        $.ajax({
 | 
			
		||||
//            url: this.apiUrl,
 | 
			
		||||
//            async: this.isAsync,
 | 
			
		||||
//            type: this.type,
 | 
			
		||||
//            dataType: this.dataType,
 | 
			
		||||
//            traditional: true,
 | 
			
		||||
//            contentType: "application/json; charset=utf-8",
 | 
			
		||||
//            data: this.dataToString(this.sendData),
 | 
			
		||||
//            beforeSend: this.beforeSendFunction,
 | 
			
		||||
//            success: this.successFunction,
 | 
			
		||||
//            error: this.errorFunction,
 | 
			
		||||
//            complete: this.completeFunction,
 | 
			
		||||
//            statusCode: {
 | 
			
		||||
//                201: this.successFunction
 | 
			
		||||
//            }
 | 
			
		||||
//        });
 | 
			
		||||
//    }
 | 
			
		||||
//};
 | 
			
		||||
							
								
								
									
										320
									
								
								Frontend/js/yourteam/yourteam.chartjs.class.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										320
									
								
								Frontend/js/yourteam/yourteam.chartjs.class.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,320 @@
 | 
			
		||||
var YourTeam = YourTeam || {};
 | 
			
		||||
YourTeam.Chartjs = YourTeam.Chartjs || {};
 | 
			
		||||
class Bar {
 | 
			
		||||
    constructor() {
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 初始化Bar基本圖表
 | 
			
		||||
    * @param {String} cvsId the canvas`s id    
 | 
			
		||||
    * @param {Array} aryLabelsX X軸標籤值(String Array)
 | 
			
		||||
    * @param {Array} aryVluesY Y軸量值(Integer Array)
 | 
			
		||||
    * @param {String} strTitle the title of the chart;def value = null
 | 
			
		||||
    * @returns {Object} chart element
 | 
			
		||||
    */
 | 
			
		||||
    initBasesss(cvsId, aryLabels, aryVlues, strTitle = null) {
 | 
			
		||||
        //function newDate(days) {
 | 
			
		||||
        //    return new YourTeam.Utility.DateHelper().getChangeDateTime(false, '/', 0, 0, days);
 | 
			
		||||
        //}
 | 
			
		||||
        let myDatasets = [];
 | 
			
		||||
        let objJson = {};
 | 
			
		||||
        for (let i = 0; i < aryVlues.length; i++) {
 | 
			
		||||
            objJson = {};
 | 
			
		||||
            objJson.label = aryLabels[i];
 | 
			
		||||
            objJson.data = [aryVlues[i]];
 | 
			
		||||
            objJson.borderColor = "rgba(220,20,20,1)";
 | 
			
		||||
            objJson.backgroundColor = "rgba(220,20,20,0.5)";
 | 
			
		||||
            myDatasets.push(objJson);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let config = {
 | 
			
		||||
            type: "bar",
 | 
			
		||||
            data: {
 | 
			
		||||
                //labels: [newDate(-5), newDate(-4), newDate(-3), newDate(-2), newDate(-1), newDate(0)],
 | 
			
		||||
                labels: aryLabels,
 | 
			
		||||
                datasets: myDatasets
 | 
			
		||||
                //datasets: [{
 | 
			
		||||
                //    //data: [2, 5, 3, 4, 7, 3],
 | 
			
		||||
                //    data: aryVlues,
 | 
			
		||||
                //    borderColor: "rgba(220,20,20,1)",
 | 
			
		||||
                //    backgroundColor: "rgba(220,20,20,0.5)"
 | 
			
		||||
                //}]
 | 
			
		||||
            },
 | 
			
		||||
            options: {
 | 
			
		||||
                legend: {
 | 
			
		||||
                    display: true,
 | 
			
		||||
                    labels: {
 | 
			
		||||
                        fontColor: 'rgb(255, 99, 132)'
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                scales: {
 | 
			
		||||
                    xAxes: [{
 | 
			
		||||
                        type: "category",
 | 
			
		||||
                        labels: aryLabels
 | 
			
		||||
                    }],
 | 
			
		||||
                    yAxes: [{
 | 
			
		||||
                        ticks: {
 | 
			
		||||
                            beginAtZero: true
 | 
			
		||||
                        }
 | 
			
		||||
                    }]
 | 
			
		||||
                },
 | 
			
		||||
                title: {
 | 
			
		||||
                    display: (strTitle) ? true : false,
 | 
			
		||||
                    text: (strTitle) ? strTitle : ""
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        let ctx = document.getElementById(cvsId).getContext("2d");
 | 
			
		||||
        //window.myLine = new Chart(ctx, config);
 | 
			
		||||
        return new Chart(ctx, config);
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 初始化Bar基本圖表
 | 
			
		||||
    * @param {String} cvsId the canvas`s id    
 | 
			
		||||
    * @param {Array} aryLabelsX X軸標籤值(String Array)
 | 
			
		||||
    * @param {Array} aryVluesY Y軸量值(Integer Array)
 | 
			
		||||
    * @param {String} strTitle the title of the chart;def value = null
 | 
			
		||||
    * @param {String} type the chart is vertical or horizontal ;def value = "bar" (vertical), "horizontalBar" (horizontal)
 | 
			
		||||
    * @returns {Object} chart element
 | 
			
		||||
    */
 | 
			
		||||
    initBase(cvsId, aryLabels, aryVlues, strLabel = null, strTitle = null, chart = null,type="bar",animation = null) {
 | 
			
		||||
        //function newDate(days) {
 | 
			
		||||
        //    return new YourTeam.Utility.DateHelper().getChangeDateTime(false, '/', 0, 0, days);
 | 
			
		||||
        //}
 | 
			
		||||
        if (chart !== null) {
 | 
			
		||||
            chart.destroy();
 | 
			
		||||
        }
 | 
			
		||||
        let myDatasets = [];
 | 
			
		||||
        let objJson = {};
 | 
			
		||||
        let valLabelObj = {};
 | 
			
		||||
  
 | 
			
		||||
        objJson.backgroundColor = [];
 | 
			
		||||
 | 
			
		||||
        objJson.label = strLabel ?? "";
 | 
			
		||||
        for (let i = 0; i < aryVlues.length; i++) {
 | 
			
		||||
            objJson.borderColor = "rgba(220,20,20,1)";
 | 
			
		||||
            objJson.backgroundColor.push("rgba(" + random(0, 255) + "," + random(0, 255) + "," + random(0, 255) + ",0.5)");
 | 
			
		||||
        }
 | 
			
		||||
        objJson.data = aryVlues;
 | 
			
		||||
        myDatasets.push(objJson);
 | 
			
		||||
        
 | 
			
		||||
       
 | 
			
		||||
        let config = {
 | 
			
		||||
            type: type,
 | 
			
		||||
            data: {
 | 
			
		||||
                //labels: [newDate(-5), newDate(-4), newDate(-3), newDate(-2), newDate(-1), newDate(0)],
 | 
			
		||||
                labels: aryLabels,
 | 
			
		||||
                datasets: myDatasets
 | 
			
		||||
                //datasets: [{
 | 
			
		||||
                //    //data: [2, 5, 3, 4, 7, 3],
 | 
			
		||||
                //    data: aryVlues,
 | 
			
		||||
                //    borderColor: "rgba(220,20,20,1)",
 | 
			
		||||
                //    backgroundColor: "rgba(220,20,20,0.5)"
 | 
			
		||||
                //}]
 | 
			
		||||
            },
 | 
			
		||||
            options: {
 | 
			
		||||
                indexAxis: 'y',
 | 
			
		||||
                legend: {
 | 
			
		||||
                    labels: {
 | 
			
		||||
                        generateLabels: function (chart) {
 | 
			
		||||
                            let labels = chart.data.labels;
 | 
			
		||||
                            let dataset = chart.data.datasets[0];
 | 
			
		||||
                            let legend = labels.map(function (label, index) {
 | 
			
		||||
                                return {
 | 
			
		||||
                                    datasetIndex: 0,
 | 
			
		||||
                                    fillStyle: dataset.backgroundColor && dataset.backgroundColor[index],
 | 
			
		||||
                                    strokeStyle: dataset.borderColor && dataset.borderColor[index],
 | 
			
		||||
                                    lineWidth: 0,
 | 
			
		||||
                                    text: label
 | 
			
		||||
                                }
 | 
			
		||||
                            });
 | 
			
		||||
                            return legend;
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    onClick: null
 | 
			
		||||
                },
 | 
			
		||||
                
 | 
			
		||||
                scales: {
 | 
			
		||||
                    xAxes: [{
 | 
			
		||||
                        
 | 
			
		||||
                        ticks: {
 | 
			
		||||
                            beginAtZero: true,
 | 
			
		||||
                            callback: function (value, index, values) {
 | 
			
		||||
                                if (value.length > 10) {
 | 
			
		||||
                                    value = value.substring(0, 10) + "...";
 | 
			
		||||
                                }
 | 
			
		||||
                                return value;
 | 
			
		||||
                            },
 | 
			
		||||
                        },
 | 
			
		||||
                    }],
 | 
			
		||||
                    yAxes: [{
 | 
			
		||||
                        ticks: {
 | 
			
		||||
                            beginAtZero: true
 | 
			
		||||
                        }
 | 
			
		||||
                    }],
 | 
			
		||||
                   
 | 
			
		||||
                },
 | 
			
		||||
                animation: animation,
 | 
			
		||||
                title: {
 | 
			
		||||
                    display: (strTitle) ? true : false,
 | 
			
		||||
                    text: (strTitle) ? strTitle : ""
 | 
			
		||||
                },
 | 
			
		||||
                tooltips: {
 | 
			
		||||
                    callbacks: {
 | 
			
		||||
                        //label: function (tooltipItem) {
 | 
			
		||||
                        //    console.log(tooltipItem)
 | 
			
		||||
                        //    return tooltipItem.yLabel;
 | 
			
		||||
                        //},
 | 
			
		||||
                        //title: function (tooltipItem) {
 | 
			
		||||
                        //    console.log(tooltipItem)
 | 
			
		||||
                        //    return tooltipItem.xLabel
 | 
			
		||||
                        //}
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
           
 | 
			
		||||
        }
 | 
			
		||||
        let ctx = document.getElementById(cvsId).getContext("2d");
 | 
			
		||||
        //window.myLine = new Chart(ctx, config);
 | 
			
		||||
        return new Chart(ctx, config);
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 初始化Bar日期基本圖表
 | 
			
		||||
    * @param {String} cvsId the canvas`s id    
 | 
			
		||||
    * @param {Array} aryLabelsX X軸標籤值(Date Array)
 | 
			
		||||
    * @param {Array} aryVluesY Y軸量值(Integer Array)
 | 
			
		||||
    * @param {String} strTitle the title of the chart;def value = null
 | 
			
		||||
    * @returns {Object} chart element
 | 
			
		||||
    */
 | 
			
		||||
    initBaseDate(cvsId, aryLabels, aryVlues, strTitle = null, chart = null) {
 | 
			
		||||
        //function newDate(days) {
 | 
			
		||||
        //    return new YourTeam.Utility.DateHelper().getChangeDateTime(false, '/', 0, 0, days);
 | 
			
		||||
        //}
 | 
			
		||||
        if (chart !== null) {
 | 
			
		||||
            chart.destroy();
 | 
			
		||||
        }
 | 
			
		||||
        let config = {
 | 
			
		||||
            type: "bar",
 | 
			
		||||
            data: {
 | 
			
		||||
                //labels: [newDate(-5), newDate(-4), newDate(-3), newDate(-2), newDate(-1), newDate(0)],
 | 
			
		||||
                labels: aryLabels,
 | 
			
		||||
                datasets: [{
 | 
			
		||||
                    //data: [2, 5, 3, 4, 7, 3],
 | 
			
		||||
                    data: aryVlues,
 | 
			
		||||
                    borderColor: "rgba(220,20,20,1)",
 | 
			
		||||
                    backgroundColor: "rgba(220,20,20,0.5)"
 | 
			
		||||
                }]
 | 
			
		||||
            },
 | 
			
		||||
            options: {
 | 
			
		||||
                scales: {
 | 
			
		||||
                    xAxes: [{
 | 
			
		||||
                        type: "time",
 | 
			
		||||
                        time: {
 | 
			
		||||
                            unit: "day",
 | 
			
		||||
                            round: "day",
 | 
			
		||||
                            displayFormats: {
 | 
			
		||||
                                day: "YYYY/MM/DD"
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }],
 | 
			
		||||
                    yAxes: [{
 | 
			
		||||
                        ticks: {
 | 
			
		||||
                            beginAtZero: true
 | 
			
		||||
                        }
 | 
			
		||||
                    }]
 | 
			
		||||
                },
 | 
			
		||||
                title: {
 | 
			
		||||
                    display: (strTitle) ? true : false,
 | 
			
		||||
                    text: (strTitle) ? strTitle : ""
 | 
			
		||||
                },
 | 
			
		||||
                
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        let ctx = document.getElementById(cvsId).getContext("2d");
 | 
			
		||||
        //window.myLine = new Chart(ctx, config);
 | 
			
		||||
        return new Chart(ctx, config);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
YourTeam.Chartjs.Bar = YourTeam.Chartjs.BarHelper || Bar;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Pie {
 | 
			
		||||
    constructor() {
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 初始化Pie基本圖表
 | 
			
		||||
    * @param {String} cvsId the canvas`s id    
 | 
			
		||||
    * @param {Array} aryLabels 標籤值(String Array)
 | 
			
		||||
    * @param {Array} aryVlues  量值(Integer Array)
 | 
			
		||||
    * @param {String} strTitle the title of the chart;def value = null
 | 
			
		||||
    * @param {Integer} borderWidth the width of the border;def value = 1
 | 
			
		||||
    * @param {Array} aryStrBgColor the rgba or color code with the backaround;def value = null
 | 
			
		||||
    * @param {Array} aryStrBorderColor the rgba or color code with the border;def value = null
 | 
			
		||||
    * @returns {Object} chart element
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
   
 | 
			
		||||
 | 
			
		||||
    initBase(cvsId, aryLabels, aryVlues, strTitle = null, chart = null, borderWidth = 1, aryStrBgColor = null, aryStrBorderColor = null)
 | 
			
		||||
    {
 | 
			
		||||
        if (chart !== null) {
 | 
			
		||||
            chart.destroy();
 | 
			
		||||
        }
 | 
			
		||||
        if (!aryStrBgColor) {
 | 
			
		||||
            aryStrBgColor = [];
 | 
			
		||||
            for (let i = 0; i < aryVlues.length; i++) {
 | 
			
		||||
                aryStrBgColor.push('rgb(' + random(0, 255) + ', ' + random(0, 255) + ', ' + random(0, 255) + ')');
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (!aryStrBorderColor) {
 | 
			
		||||
            aryStrBorderColor = [];
 | 
			
		||||
            for (let i = 0; i < aryVlues.length; i++) {
 | 
			
		||||
                aryStrBorderColor.push('rgb(255,255,255)');
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        let config = {
 | 
			
		||||
            type: (aryVlues.length % 2) ? "doughnut" :"doughnut",
 | 
			
		||||
            data: {
 | 
			
		||||
                labels: aryLabels,
 | 
			
		||||
                datasets: [{
 | 
			
		||||
                    data: aryVlues,
 | 
			
		||||
                    backgroundColor: aryStrBgColor,
 | 
			
		||||
                    borderColor: aryStrBorderColor,
 | 
			
		||||
                    borderWidth: borderWidth
 | 
			
		||||
                }]                
 | 
			
		||||
            },
 | 
			
		||||
            options: {
 | 
			
		||||
                //cutoutPercentage: 40,
 | 
			
		||||
                cutoutPercentage: 60,
 | 
			
		||||
                maintainAspectRatio: false,
 | 
			
		||||
                responsive: false,
 | 
			
		||||
                legend: {
 | 
			
		||||
                    display: false,
 | 
			
		||||
                },
 | 
			
		||||
 | 
			
		||||
                title: {
 | 
			
		||||
                    display: (strTitle) ? true : false,
 | 
			
		||||
                    text: (strTitle) ? strTitle : ""
 | 
			
		||||
                },
 | 
			
		||||
                tooltips: {
 | 
			
		||||
                    position: 'nearest',
 | 
			
		||||
                    xAlign: "left",
 | 
			
		||||
                    yAlign: 'center'
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        let ctx = document.getElementById(cvsId).getContext("2d");        
 | 
			
		||||
        //window.myLine = new Chart(ctx, config);
 | 
			
		||||
        return new Chart(ctx, config);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
YourTeam.Chartjs.Pie = YourTeam.Chartjs.PieHelper || Pie;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function random(min, max) {
 | 
			
		||||
    return Math.floor(Math.random() * max) + min;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										211
									
								
								Frontend/js/yourteam/yourteam.ckeditor5.init.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								Frontend/js/yourteam/yourteam.ckeditor5.init.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,211 @@
 | 
			
		||||
var editor = [];
 | 
			
		||||
$(function () {
 | 
			
		||||
    initCkeditor()
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
/*  --Uplaod Adapater   */
 | 
			
		||||
//class MyUploadAdapter {
 | 
			
		||||
//    constructor(loader) {
 | 
			
		||||
//        this.loader = loader;
 | 
			
		||||
//    }
 | 
			
		||||
//    // start upload methods
 | 
			
		||||
//    upload() {
 | 
			
		||||
//        return new Promise((resolve, reject) => {
 | 
			
		||||
//            // 使用 FileReader() 物件讀取檔案
 | 
			
		||||
//            const reader = this.reader = new window.FileReader();
 | 
			
		||||
 | 
			
		||||
//            // 觸發錯誤事件,以 reject 丟回 Promise 失敗原因
 | 
			
		||||
//            reader.addEventListener('error', err => {
 | 
			
		||||
//                reject(err);
 | 
			
		||||
//            });
 | 
			
		||||
//            // 觸發 abort 事件時,以 reject() ,使 Promise 失敗
 | 
			
		||||
//            reader.addEventListener('abort', () => {
 | 
			
		||||
//                reject();
 | 
			
		||||
//            });
 | 
			
		||||
 | 
			
		||||
//            // 告訴 FileReader 物件用 url 格式讀取,用於設定 img.src 性質
 | 
			
		||||
//            this.loader.file.then(file => {
 | 
			
		||||
 | 
			
		||||
//                console.log(file)
 | 
			
		||||
 | 
			
		||||
//                // 觸發 load 事件後,resolve 丟回物件完成 Promise
 | 
			
		||||
//                reader.addEventListener('load', () => {
 | 
			
		||||
//                    //file.src = reader.result;
 | 
			
		||||
//                    let myFile = new BICYCLER.Utility.File();
 | 
			
		||||
//                    let myMath = new BICYCLER.Utility.Math();
 | 
			
		||||
//                    let strExtName = "", strOrgName = "", strSaveName = ""
 | 
			
		||||
//                    strSaveName = myMath.guid().replace(' ', '');
 | 
			
		||||
//                    strExtName = myFile.getFileExtension(file.name);
 | 
			
		||||
//                    strOrgName = (strExtName === null || strExtName === "") ? file.name : file.name.replace('.' + strExtName, '');
 | 
			
		||||
 | 
			
		||||
//                    editorImage.push(file)
 | 
			
		||||
//                    resolve({
 | 
			
		||||
//                        filename: file.name,
 | 
			
		||||
//                        orgname: strOrgName,
 | 
			
		||||
//                        savename: strSaveName,
 | 
			
		||||
//                        extname: strExtName,
 | 
			
		||||
//                        size: file.size,
 | 
			
		||||
//                        urls: {
 | 
			
		||||
//                            default: reader.result
 | 
			
		||||
//                        }
 | 
			
		||||
//                    });
 | 
			
		||||
//                });
 | 
			
		||||
//                reader.readAsDataURL(file);
 | 
			
		||||
//            });
 | 
			
		||||
 | 
			
		||||
//            //this.loader.read().then(data => {
 | 
			
		||||
//            //    editor.editing.view.change(writer => {
 | 
			
		||||
//            //        writer.setAttribute('src', data, viewImg);
 | 
			
		||||
//            //    });
 | 
			
		||||
//            //});
 | 
			
		||||
//        });
 | 
			
		||||
//    }
 | 
			
		||||
//    // start abort()
 | 
			
		||||
//    abort() {
 | 
			
		||||
//        //  觸發 FileReader abort 事件
 | 
			
		||||
//        this.reader.abort();
 | 
			
		||||
//    }
 | 
			
		||||
//}
 | 
			
		||||
 | 
			
		||||
function initCkeditor() {
 | 
			
		||||
    return new Promise((resolve) => {
 | 
			
		||||
        let toolbar = {
 | 
			
		||||
            toolbar: {
 | 
			
		||||
                items: [
 | 
			
		||||
                    'heading',
 | 
			
		||||
                    '|',
 | 
			
		||||
                    'fontfamily', 'fontsize', 'fontColor', 'fontBackgroundColor',
 | 
			
		||||
                    '|',
 | 
			
		||||
                    'bold', 'italic', 'underline', 'strikethrough',
 | 
			
		||||
                    '-',
 | 
			
		||||
                    'alignment', 'numberedList', 'bulletedList',
 | 
			
		||||
                    '|',
 | 
			
		||||
                    'indent', 'outdent',
 | 
			
		||||
                    '|',
 | 
			
		||||
                    'link', 'blockquote', /*'ckfinder ,'*/ 'insertTable',
 | 
			
		||||
                    '|',
 | 
			
		||||
                    'undo', 'redo',
 | 
			
		||||
                    '|',
 | 
			
		||||
                    'fullScreen'
 | 
			
		||||
                ],
 | 
			
		||||
                shouldNotGroupWhenFull: true,
 | 
			
		||||
                language: "zh",
 | 
			
		||||
            },
 | 
			
		||||
            image: {
 | 
			
		||||
                toolbar: [
 | 
			
		||||
                    'toggleImageCaption', 'linkImage',
 | 
			
		||||
                    '|',
 | 
			
		||||
                    'imageStyle:alignBlockLeft', 'imageStyle:alignCenter', 'imageStyle:alignBlockRight', 'imageStyle:wrapText',
 | 
			
		||||
                    "|",
 | 
			
		||||
                    'resizeImage:original', 'resizeImage:25', 'resizeImage:50', 'resizeImage:75'
 | 
			
		||||
                ],
 | 
			
		||||
            },
 | 
			
		||||
            table: {
 | 
			
		||||
                contentToolbar: ['tableProperties', 'tableCellProperties', 'tableRow', 'tableColumn', 'mergeTableCells']
 | 
			
		||||
            },
 | 
			
		||||
            //image介面刪除callback
 | 
			
		||||
            //imageRemoveEvent: {
 | 
			
		||||
            //    additionalElementTypes: null, 
 | 
			
		||||
            //    callback: (imagesSrc, nodeObjects) => {
 | 
			
		||||
            //        console.log('callback called', imagesSrc, nodeObjects)
 | 
			
		||||
            //    }
 | 
			
		||||
            //},
 | 
			
		||||
            ckfinder: {
 | 
			
		||||
                //ckfinder 連接器
 | 
			
		||||
                uploadUrl: '/By_Admin/CKfinder/CKfinder/connector?command=Init&type=Images&lang=zh-tw&langCode=zh-tw',
 | 
			
		||||
                options: {
 | 
			
		||||
                    language: 'zh-tw',
 | 
			
		||||
                    resourceType: 'Images'
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $("[data-toggle^=ckeditor]").each((index, value) => {
 | 
			
		||||
            //取得原有element class
 | 
			
		||||
            let oriWidth = $(value).css("width");
 | 
			
		||||
            let oriMaxWidth = $(value).css("max-width");
 | 
			
		||||
 | 
			
		||||
            ClassicEditor.create(value, toolbar)
 | 
			
		||||
                .then(NewEditor => {
 | 
			
		||||
                    if ($("[data-toggle^=ckeditor]").length == 1) {
 | 
			
		||||
                        editor = NewEditor;
 | 
			
		||||
 | 
			
		||||
                        //讀進來的Source element disabled時,該CKEditor => enableReadOnlyMode('secret string')
 | 
			
		||||
                        if ($(value).prop("disabled") == true) {
 | 
			
		||||
                            editor.enableReadOnlyMode('bicycler');
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        //剪貼簿讀進來不呈現樣式
 | 
			
		||||
                        //const plugin = editor.plugins.get('Clipboard');
 | 
			
		||||
                        //plugin.on('inputTransformation', (evt, data) => {
 | 
			
		||||
                        //    const dataTransfer = data.dataTransfer;
 | 
			
		||||
                        //    data.content = editor.data.processor.toView(regexTextToHtml(dataTransfer.getData('text/plain')));
 | 
			
		||||
                        //})
 | 
			
		||||
 | 
			
		||||
                        //上傳照片(非CKfinder)配置UploadAdapter
 | 
			
		||||
                        //editor.plugins.get('FileRepository').createUploadAdapter = loader => {
 | 
			
		||||
                        //    console.log(editor.plugins.get('FileRepository'))
 | 
			
		||||
                        //    return new MyUploadAdapter(loader)
 | 
			
		||||
                        //}
 | 
			
		||||
 | 
			
		||||
                        //放入原有col- class 
 | 
			
		||||
                        $(editor.ui.view.element).css("width", oriWidth);
 | 
			
		||||
                        $(editor.ui.view.element).css("max-width", oriMaxWidth);
 | 
			
		||||
 | 
			
		||||
                        resolve();
 | 
			
		||||
                    } else {
 | 
			
		||||
                        let sub = $(value).data("toggle").split("ckeditor")[1];
 | 
			
		||||
                        editor[sub] = NewEditor
 | 
			
		||||
 | 
			
		||||
                        //讀進來的Source element disabled時,該CKEditor => enableReadOnlyMode('secret string')
 | 
			
		||||
                        if ($(value).prop("disabled") == true) {
 | 
			
		||||
                            editor[sub].enableReadOnlyMode('2421ww');
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        //貼上時指文字呈現
 | 
			
		||||
                        //const plugin = editor[sub].plugins.get('Clipboard');
 | 
			
		||||
                        //plugin.on('inputTransformation', (evt, data) => {
 | 
			
		||||
                        //    const dataTransfer = data.dataTransfer;
 | 
			
		||||
                        //    data.content = editor[sub].data.processor.toView(regexTextToHtml(dataTransfer.getData('text/plain')));
 | 
			
		||||
                        //})
 | 
			
		||||
 | 
			
		||||
                        //上傳照片(非CKfinder)配置UploadAdapter
 | 
			
		||||
                        editor[sub].plugins.get('FileRepository').createUploadAdapter = loader => {
 | 
			
		||||
                            console.log(editor[sub].plugins.get('FileRepository'))
 | 
			
		||||
                            return new MyUploadAdapter(loader)
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        //放入原有col- class 
 | 
			
		||||
                        $(editor[sub].ui.view.element).css("width", oriWidth);
 | 
			
		||||
                        $(editor[sub].ui.view.element).css("max-width", oriMaxWidth);
 | 
			
		||||
 | 
			
		||||
                        resolve();
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
                .catch(err => {
 | 
			
		||||
                    console.error(err.stack);
 | 
			
		||||
                    resolve();
 | 
			
		||||
                });
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function regexTextToHtml(text) {
 | 
			
		||||
    let data = text;
 | 
			
		||||
    data = data.replace(/\r/gm, "");
 | 
			
		||||
    data = data.replace(/\n\n/gm, "\n");
 | 
			
		||||
    data = data.replace(/^/gm, "<p>");
 | 
			
		||||
    data = data.replace(/\n|\n\n/gm, "</p>");
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function regexHtmlToText(html) {
 | 
			
		||||
    let data = html;
 | 
			
		||||
    data = data.replace(/<p>/gm, "");
 | 
			
		||||
    data = data.replace(/<\/p>/gm, "\n");
 | 
			
		||||
    data = data.replace(/ /gm, " ");
 | 
			
		||||
    data = data.replace(/ /gm, " ");
 | 
			
		||||
    data = data.replace(/ /gm, " ");
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										644
									
								
								Frontend/js/yourteam/yourteam.jquery.datatables.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										644
									
								
								Frontend/js/yourteam/yourteam.jquery.datatables.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,644 @@
 | 
			
		||||
var YourTeam = YourTeam || {};
 | 
			
		||||
YourTeam.JqDataTables = YourTeam.JqDataTables || {};
 | 
			
		||||
/* @deprecated since version 0.2
 | 
			
		||||
*  @description change datatables prototype language
 | 
			
		||||
*  @author Darren Chen
 | 
			
		||||
*  @date   2018/04/18
 | 
			
		||||
*/
 | 
			
		||||
$.fn.dataTable.defaults.oLanguage = {
 | 
			
		||||
    "sProcessing": "等待中...",
 | 
			
		||||
    "sLengthMenu": "顯示 _MENU_ 項結果",
 | 
			
		||||
    "sZeroRecords": "沒有匹配結果",
 | 
			
		||||
    "sInfo": "顯示第 _START_ 至 _END_ 項結果,共 _TOTAL_ 項",
 | 
			
		||||
    "sInfoEmpty": "顯示第 0 至 0 項結果,共 0 項",
 | 
			
		||||
    "sInfoFiltered": "(由 _MAX_ 項結果過濾)",
 | 
			
		||||
    "sInfoPostFix": "",
 | 
			
		||||
    "sSearch": "搜索:",
 | 
			
		||||
    "sUrl": "",
 | 
			
		||||
    "sThousands": "",
 | 
			
		||||
    "sEmptyTable": "表中數據為空",
 | 
			
		||||
    "sLoadingRecords": "載入中...",
 | 
			
		||||
    "sInfoThousands": ",",
 | 
			
		||||
    "oPaginate": {
 | 
			
		||||
        "sFirst": "首頁",
 | 
			
		||||
        "sPrevious": "上頁",
 | 
			
		||||
        "sNext": "下頁",
 | 
			
		||||
        "sLast": "末頁"
 | 
			
		||||
    },
 | 
			
		||||
    "oAria": {
 | 
			
		||||
        "sSortAscending": ": 以升序排列此列",
 | 
			
		||||
        "sSortDescending": ": 以降序排列此列"
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* @deprecated since version 0.1
 | 
			
		||||
*  @description init the jq datatables no data with the page ui
 | 
			
		||||
*  @param {String} tag jq datatables id(#id) or class(.class)
 | 
			
		||||
*  @param {Array} colnum_defs these is colnum def. with init the table
 | 
			
		||||
*  @param {function} initComplete after init complete run a function
 | 
			
		||||
*  @param {function} drawCallback after draw complete run a function
 | 
			
		||||
*  @author Darren Chen
 | 
			
		||||
*  @date   2020/12/10
 | 
			
		||||
*/
 | 
			
		||||
function fnInitJqDataTablesNoData(tag, dataSet = null, columns = null, columnDefs = null, initComplete = null, drawCallback = null, rowsGroup = null, rowGroup = null, dom = '<"toolbar">frtipl' ) {
 | 
			
		||||
    let fnDrawCallBack = function () {
 | 
			
		||||
        drawCallback != null ? drawCallback() : "";
 | 
			
		||||
        let api = this.api();
 | 
			
		||||
        $(".dataTables_scrollBody").css("overflow", "auto");
 | 
			
		||||
        if (api.rows().data().length <= 1) {
 | 
			
		||||
            $(".dataTables_scrollBody").css("overflow", "visible");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    let table = null;
 | 
			
		||||
    let oTable = {
 | 
			
		||||
        "sDom": dom,
 | 
			
		||||
        "data": dataSet,
 | 
			
		||||
        "autoWidth": true,
 | 
			
		||||
        "processing": true,
 | 
			
		||||
        "columns": columns,
 | 
			
		||||
        "aoColumnDefs": columnDefs,
 | 
			
		||||
        "stateSave": true,
 | 
			
		||||
        "pagingType": "full_numbers_custom",
 | 
			
		||||
        "destroy": false,
 | 
			
		||||
        "initComplete": initComplete,
 | 
			
		||||
        "drawCallback": fnDrawCallBack,
 | 
			
		||||
        "rowsGroup": rowsGroup,
 | 
			
		||||
        "rowGroup": rowGroup,
 | 
			
		||||
        "retrieve": true,
 | 
			
		||||
        "responsive": {
 | 
			
		||||
            details: {
 | 
			
		||||
           
 | 
			
		||||
                target: '.dt-mobile-btn',
 | 
			
		||||
                type: "column",
 | 
			
		||||
                renderer: function (api, rowIdx, columns) {
 | 
			
		||||
                    var data = $.map(columns, function (col, i) {
 | 
			
		||||
                        return col.hidden ?
 | 
			
		||||
                            '<tr data-dt-row="' + col.rowIndex + '" data-dt-column="' + col.columnIndex + '">' +
 | 
			
		||||
                            '<td>' + col.title + ':' + '</td> ' +
 | 
			
		||||
                            '<td>' + col.data + '</td>' +
 | 
			
		||||
                            '</tr>' :
 | 
			
		||||
                            '';
 | 
			
		||||
                    }).join('');
 | 
			
		||||
 | 
			
		||||
                    return data ?
 | 
			
		||||
                        $('<table/>').append(data) :
 | 
			
		||||
                        false;
 | 
			
		||||
                },
 | 
			
		||||
              
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let time = 0;
 | 
			
		||||
    table = $(tag).DataTable(oTable);
 | 
			
		||||
    table.on('processing', function (e, settings, processing) {
 | 
			
		||||
        //過100ms的讀取才秀出loading
 | 
			
		||||
        setTimeout(function () {
 | 
			
		||||
            time == 1 ? loadingSetting("show", "dtProcessing") : "";
 | 
			
		||||
        }, 100);
 | 
			
		||||
 | 
			
		||||
        if (processing && time == 0) {  //第一次讀取processing = true
 | 
			
		||||
            time = 1;
 | 
			
		||||
        } else if (!processing && time == 1 ) {   //結束讀取後processing = false
 | 
			
		||||
            loadingSetting("hide", "dtProcessing");
 | 
			
		||||
            time = 0;
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
    table.on('responsive-display', function (e, datatable, row, showHide, update ) {
 | 
			
		||||
        table.columns.adjust();
 | 
			
		||||
    });
 | 
			
		||||
    return table;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function fnInitJqDataTables(tag, colnum_defs = null, initComplete = null, drawCallback = null) {
 | 
			
		||||
    return $(tag).DataTable({
 | 
			
		||||
        "dom": '<"toolbar"><"wrapper"ti>',
 | 
			
		||||
        //"responsive": true,
 | 
			
		||||
        "autoWidth": true,
 | 
			
		||||
        //"aoColumns": columns,
 | 
			
		||||
        "aoColumnDefs": colnum_defs,
 | 
			
		||||
        "initComplete": initComplete,
 | 
			
		||||
        "drawCallback": drawCallback,
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* @deprecated since version 1.1
 | 
			
		||||
*  @description init jq datatables use jQuery AJAX
 | 
			
		||||
*  @param {String} API url
 | 
			
		||||
*  @param {String} table id (#id)
 | 
			
		||||
*  @param {Object} data
 | 
			
		||||
*  @param {Object} columns 
 | 
			
		||||
*  @param {Object} columns_def
 | 
			
		||||
*  @param {Object} order
 | 
			
		||||
*  @param {String} table header button id (#id)
 | 
			
		||||
*  @param {String} html tag string with the header
 | 
			
		||||
*  @return {String} JSON string
 | 
			
		||||
*  @author Darren Chen
 | 
			
		||||
*  @date   2020/12/11
 | 
			
		||||
*/
 | 
			
		||||
function fnInitJqDataTablesAjax(apiUrl, tag, sendData = null, columns, columns_def, initComplete = null, drawCallback = null, rowsGroup = null, rowGroup = null ,order = null, btn = null, dom = null) {
 | 
			
		||||
    //$(tag).dataTable().fnClearTable();
 | 
			
		||||
    //let sData = data ? (data.Data ? JSON.stringify(data.Data) : null) : null;  
 | 
			
		||||
    if (sendData == null) { 
 | 
			
		||||
        sendData = function (json) {
 | 
			
		||||
            console.log("讀取列表", json)
 | 
			
		||||
            return json;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let fnDrawCallBack = function () {
 | 
			
		||||
        drawCallback != null ? drawCallback() : "";
 | 
			
		||||
        let api = this.api();
 | 
			
		||||
        $(".dataTables_scrollBody").css("overflow", "auto");
 | 
			
		||||
        if (api.rows().data().length <= 1) {
 | 
			
		||||
            $(".dataTables_scrollBody").css("overflow", "visible");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    let table = null;
 | 
			
		||||
    try {
 | 
			
		||||
        let oTable = {
 | 
			
		||||
            "ajax": {
 | 
			
		||||
                method: "GET",
 | 
			
		||||
                url: apiUrl,
 | 
			
		||||
                cache: true,
 | 
			
		||||
                async:false,
 | 
			
		||||
                dataSrc: sendData,
 | 
			
		||||
            },
 | 
			
		||||
            "responsive": {
 | 
			
		||||
                details: {
 | 
			
		||||
                    target: '.dt-mobile-btn',
 | 
			
		||||
                    renderer: function (api, rowIdx, columns) {
 | 
			
		||||
                        var data = $.map(columns, function (col, i) {
 | 
			
		||||
                            return col.hidden ?
 | 
			
		||||
                                '<tr data-dt-row="' + col.rowIndex + '" data-dt-column="' + col.columnIndex + '">' +
 | 
			
		||||
                                '<td>' + col.title + ':' + '</td> ' +
 | 
			
		||||
                                '<td>' + col.data + '</td>' +
 | 
			
		||||
                                '</tr>' :
 | 
			
		||||
                                '';
 | 
			
		||||
                        }).join('');
 | 
			
		||||
 | 
			
		||||
                        return data ?
 | 
			
		||||
                            $('<table/>').append(data) :
 | 
			
		||||
                            false;
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
            "data": null,
 | 
			
		||||
            "EmptyTable": true,
 | 
			
		||||
            "destroy": true,
 | 
			
		||||
            "processing": false,
 | 
			
		||||
            "sDom":'<"toolbar">frtipl',
 | 
			
		||||
            "pagingType": $(window).width() < 768 ? "simple" : "full_numbers_custom",
 | 
			
		||||
            //"responsive": true,
 | 
			
		||||
            "autoWidth": true,
 | 
			
		||||
            "aoColumns": columns,
 | 
			
		||||
            "aoColumnDefs": columns_def,
 | 
			
		||||
            "deferRender": true,
 | 
			
		||||
            "fixedColumns": true,
 | 
			
		||||
            "stateSave": true,
 | 
			
		||||
            "scrollX": true,
 | 
			
		||||
            "scrollY": "700px",
 | 
			
		||||
            "scrollCollapse": true,
 | 
			
		||||
            "autoWidth": true,
 | 
			
		||||
            //"sScrollY": "480px",
 | 
			
		||||
            "orderMulti": true,
 | 
			
		||||
            "header": "#liaison_header",
 | 
			
		||||
            "initComplete": initComplete,
 | 
			
		||||
            "drawCallback": fnDrawCallBack,
 | 
			
		||||
            "rowGroup": rowGroup,
 | 
			
		||||
            "rowsGroup": rowsGroup,
 | 
			
		||||
            
 | 
			
		||||
        };
 | 
			
		||||
        if (order) {
 | 
			
		||||
            oTable.order = order;
 | 
			
		||||
        }
 | 
			
		||||
        if (dom) {
 | 
			
		||||
            oTable.dom = dom;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let time = 0;
 | 
			
		||||
        table = $(tag).DataTable(oTable);
 | 
			
		||||
        table.on('processing', function (e, settings, processing) {
 | 
			
		||||
            //過100ms的讀取才秀出loading
 | 
			
		||||
            setTimeout(function () {
 | 
			
		||||
                time == 1 ? loadingSetting("show", "dtProcessing") : "";
 | 
			
		||||
            }, 100);
 | 
			
		||||
 | 
			
		||||
            if (processing && time != 1) {  //第一次讀取processing = true
 | 
			
		||||
                time = 1;
 | 
			
		||||
            } else if (!processing && time == 1) {  //結束讀取後processing = false
 | 
			
		||||
                loadingSetting("hide", "dtProcessing");
 | 
			
		||||
                time = 0;
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) {
 | 
			
		||||
        console.error(e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return table;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function fnInitJqDataTablesOdata(apiUrl, tag, sendData, columns, columns_def, drawCallback = null, order = null) {
 | 
			
		||||
    //$(tag).dataTable().fnClearTable();
 | 
			
		||||
    //let sData = data ? (data.Data ? JSON.stringify(data.Data) : null) : null;    
 | 
			
		||||
    let table = null;
 | 
			
		||||
    try {
 | 
			
		||||
        let oTable = {
 | 
			
		||||
            "sAjaxSource": apiUrl,
 | 
			
		||||
            "iODataVersion": 3,
 | 
			
		||||
            "aoColumns": columns,
 | 
			
		||||
            "aoColumnDefs": columns_def,
 | 
			
		||||
            "fnServerData": fnServerOData, // required
 | 
			
		||||
            "bProcessing": true,
 | 
			
		||||
            "bServerSide": true,  // optional
 | 
			
		||||
            "bDestroy": true,
 | 
			
		||||
            "bUseODataViaJSONP": false,  // set to true if using cross-domain requests
 | 
			
		||||
            "sDom": '<"toolbar">f<"selector">rtipl',
 | 
			
		||||
            "stateSave": true,
 | 
			
		||||
        };
 | 
			
		||||
        if (order) {
 | 
			
		||||
            oTable.order = order;
 | 
			
		||||
        }
 | 
			
		||||
        table = $(tag).DataTable(oTable);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) {
 | 
			
		||||
        console.error(e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return table;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function fnInitJqDataTablesServerSideAjax(apiUrl, tag, sendData, columns, columns_def, initComplete = null, drawCallback = null, rowsGroup = null, rowGroup = null, order = null, btn = null, dom = null) {
 | 
			
		||||
    //$(tag).dataTable().fnClearTable();
 | 
			
		||||
    //let sData = data ? (data.Data ? JSON.stringify(data.Data) : null) : null;    
 | 
			
		||||
    let table = null;
 | 
			
		||||
 | 
			
		||||
    let fnDrawCallBack = function () {
 | 
			
		||||
        let api = this.api();
 | 
			
		||||
 | 
			
		||||
        drawCallback != null ? drawCallback(api) : "";
 | 
			
		||||
        //若只有一列 overflow改為 visible (tooltip/popover 不會阻擋)
 | 
			
		||||
        $(".dataTables_scrollBody").css("overflow", "auto");
 | 
			
		||||
        if (api.rows().data().length <= 1) {
 | 
			
		||||
            $(".dataTables_scrollBody").css("overflow", "visible");
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
    }
 | 
			
		||||
    try {
 | 
			
		||||
        let oTable = {
 | 
			
		||||
            "sAjaxSource": apiUrl,
 | 
			
		||||
            //"ajax": {
 | 
			
		||||
            //    "method":"POST",
 | 
			
		||||
            //    "url": apiUrl,
 | 
			
		||||
            //},
 | 
			
		||||
            "responsive": {
 | 
			
		||||
                details: {
 | 
			
		||||
                    renderer: function (api, rowIdx, columns) {
 | 
			
		||||
                        var data = $.map(columns, function (col, i) {
 | 
			
		||||
                            return col.hidden ?
 | 
			
		||||
                                '<tr data-dt-row="' + col.rowIndex + '" data-dt-column="' + col.columnIndex + '">' +
 | 
			
		||||
                                '<td>' + col.title + ':' + '</td> ' +
 | 
			
		||||
                                '<td>' + col.data + '</td>' +
 | 
			
		||||
                                '</tr>' :
 | 
			
		||||
                                '';
 | 
			
		||||
                        }).join('');
 | 
			
		||||
 | 
			
		||||
                        return data ?
 | 
			
		||||
                            $('<table/>').append(data) :
 | 
			
		||||
                            false;
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
            "fnServerParams": sendData,
 | 
			
		||||
            "data": null,
 | 
			
		||||
            "EmptyTable": true,
 | 
			
		||||
            "destroy": true,
 | 
			
		||||
            "processing": false,
 | 
			
		||||
            "sDom": '<"toolbar">f<"selector">rtipl',
 | 
			
		||||
            "paging": true,
 | 
			
		||||
            "pagingType": $(window).width() < 768 ? "simple" : "full_numbers_custom",
 | 
			
		||||
            //"responsive": true,
 | 
			
		||||
            "autoWidth": true,
 | 
			
		||||
            "aoColumns": columns,
 | 
			
		||||
            "aoColumnDefs": columns_def,
 | 
			
		||||
            "deferRender": true,
 | 
			
		||||
            "fixedColumns": true,
 | 
			
		||||
            "stateSave": true,
 | 
			
		||||
            "stateSaveParams": function (settings, data) {
 | 
			
		||||
                //紀錄該頁是否有篩選Filter
 | 
			
		||||
                if ($(".column_filter")) {
 | 
			
		||||
                    let saveFilterArr = [];
 | 
			
		||||
                    
 | 
			
		||||
                    $(".column_filter input:checkbox:checked").each(function (i, v) {
 | 
			
		||||
                        let id = $(v)[0].id;
 | 
			
		||||
                        saveFilterArr.push(id);
 | 
			
		||||
                    })
 | 
			
		||||
                    data.CustomFilter = JSON.stringify(saveFilterArr);  //把勾選的篩選儲存到datatable state
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "scrollX": true,
 | 
			
		||||
            "scrollY": "700px",
 | 
			
		||||
            "scrollCollapse": true,
 | 
			
		||||
            "autoWidth": true,
 | 
			
		||||
            //"sScrollY": "480px",
 | 
			
		||||
            "orderMulti": true,
 | 
			
		||||
            "bServerSide": true,
 | 
			
		||||
            "header": "#liaison_header",
 | 
			
		||||
            "initComplete": initComplete,
 | 
			
		||||
            "drawCallback": fnDrawCallBack,
 | 
			
		||||
            "rowGroup": rowGroup,
 | 
			
		||||
            "rowsGroup": rowsGroup,
 | 
			
		||||
           
 | 
			
		||||
        };
 | 
			
		||||
        if (order) {
 | 
			
		||||
            oTable.order = order;
 | 
			
		||||
        }
 | 
			
		||||
        if (dom) {
 | 
			
		||||
            oTable.dom = dom;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let time = 0;
 | 
			
		||||
        
 | 
			
		||||
        table = $(tag).DataTable(oTable);
 | 
			
		||||
        $.fn.DataTable.ext.pager.numbers_length = 9;
 | 
			
		||||
       
 | 
			
		||||
        console.log($.fn.DataTable.ext.pager)
 | 
			
		||||
        table.on('processing', function (e, settings, processing) {
 | 
			
		||||
            //過100ms的讀取才秀出loading
 | 
			
		||||
            setTimeout(function () {
 | 
			
		||||
                time == 1 ? loadingSetting("show", "pageload") : "";
 | 
			
		||||
            }, 100);
 | 
			
		||||
 | 
			
		||||
            if (processing && time == 0) {  //第一次讀取processing = true
 | 
			
		||||
                time = 1;
 | 
			
		||||
            } else if (!processing && time == 1 && tableStatus != 2){   //結束讀取後processing = false
 | 
			
		||||
                loadingSetting("hide", "pageload");
 | 
			
		||||
                time = 0;
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        table.on('xhr', function (e, settings, json, xhr) {
 | 
			
		||||
            console.log("讀取列表", json.aaData);
 | 
			
		||||
           
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        table.on('page', function (e, setting) {
 | 
			
		||||
            $(`${tag}_wrapper .dataTables_scrollBody`).scrollTop(0);
 | 
			
		||||
            pageScrollPos = 0;
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) {
 | 
			
		||||
        console.error(e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return table;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
YourTeam.JqDataTables.getTableByOdata = fnInitJqDataTablesOdata;
 | 
			
		||||
YourTeam.JqDataTables.getTableByAjax = fnInitJqDataTablesAjax;
 | 
			
		||||
YourTeam.JqDataTables.getTableByServerSideAjax = fnInitJqDataTablesServerSideAjax;
 | 
			
		||||
YourTeam.JqDataTables.getTableByStatic = fnInitJqDataTablesNoData;
 | 
			
		||||
YourTeam.JqDataTables.getTableByNoAjax = fnInitJqDataTables;
 | 
			
		||||
 | 
			
		||||
/* @deprecated since version 1.1
 | 
			
		||||
*  @description add one new row  with the jq datatables
 | 
			
		||||
*  @param {Object} table the jq datatables
 | 
			
		||||
*  @param {Object} item one JSON item with the data Object
 | 
			
		||||
*  @param {Object} data the data Object
 | 
			
		||||
*  @return
 | 
			
		||||
*  @author Darren Chen
 | 
			
		||||
*  @date   2020/12/11
 | 
			
		||||
*/
 | 
			
		||||
function fnJqDataTablesNewRow(table, itemSpace) {
 | 
			
		||||
    let isSuccess = false;
 | 
			
		||||
    try {
 | 
			
		||||
        table.row.add(itemSpace).draw(false);
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) {
 | 
			
		||||
        console.error(e);
 | 
			
		||||
        return isSuccess;
 | 
			
		||||
    }
 | 
			
		||||
    return isSuccess;
 | 
			
		||||
}
 | 
			
		||||
YourTeam.JqDataTables.newRow = fnJqDataTablesNewRow;
 | 
			
		||||
 | 
			
		||||
/* @deprecated since version 1.1
 | 
			
		||||
*  @description add one row and data with the jq datatables
 | 
			
		||||
*  @param {Object} table the jq datatables
 | 
			
		||||
*  @param {Object} item one JSON item with the data Object
 | 
			
		||||
*  @param {Object} data the data Object
 | 
			
		||||
*  @return 
 | 
			
		||||
*  @author Darren Chen
 | 
			
		||||
*  @date   2020/12/11
 | 
			
		||||
*/
 | 
			
		||||
function fnJqDataTablesAddRow(table, item) {
 | 
			
		||||
    let isSuccess = false;
 | 
			
		||||
    try {
 | 
			
		||||
        if (table && item) {
 | 
			
		||||
            table.row.add(item).draw(false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) {
 | 
			
		||||
        console.error(e);
 | 
			
		||||
        return isSuccess;
 | 
			
		||||
    }
 | 
			
		||||
    return isSuccess;
 | 
			
		||||
}
 | 
			
		||||
YourTeam.JqDataTables.addRow = fnJqDataTablesAddRow;
 | 
			
		||||
 | 
			
		||||
/* @deprecated since version 1.1
 | 
			
		||||
*  @description remove one row and data with the jq datatables
 | 
			
		||||
*  @param {String} tableId the datatables`s id
 | 
			
		||||
*  @param {String} elementSelector the jq selector with remove row element
 | 
			
		||||
*  @return {Bollean} isSuccess
 | 
			
		||||
*  @author Darren Chen
 | 
			
		||||
*  @date   2020/12/11
 | 
			
		||||
*/
 | 
			
		||||
function fnJqDataTablesRemoveRow(tableId, elementSelector) {
 | 
			
		||||
    let isSuccess = false;
 | 
			
		||||
    try {
 | 
			
		||||
        $('#' + tableId + ' tbody').on('click', elementSelector, function () {
 | 
			
		||||
            table.row($(this).parents('tr')).remove().draw(false);
 | 
			
		||||
        });
 | 
			
		||||
        isSuccess = true;
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) {
 | 
			
		||||
        console.error(e);
 | 
			
		||||
        return isSuccess;
 | 
			
		||||
    }
 | 
			
		||||
    return isSuccess;
 | 
			
		||||
}
 | 
			
		||||
YourTeam.JqDataTables.removeRow = fnJqDataTablesRemoveRow;
 | 
			
		||||
 | 
			
		||||
/* @deprecated since version 0.3
 | 
			
		||||
*  @description display buton 
 | 
			
		||||
*  @param {Boolean} have create power?
 | 
			
		||||
*  @param {Boolean} have edit power?
 | 
			
		||||
*  @param {Boolean} have delete power?
 | 
			
		||||
*  @param {Boolean} have print power?
 | 
			
		||||
*  @return {String}
 | 
			
		||||
*  @author Darren Chen
 | 
			
		||||
*  @date   2018/04/18
 | 
			
		||||
*/
 | 
			
		||||
function showControlItem(Create, Edit, Delete, Print) {
 | 
			
		||||
    if (Create) {
 | 
			
		||||
        $("#btnCreat").show();
 | 
			
		||||
        $("#ERP_insert").show();
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        $("#btnCreat").hide();
 | 
			
		||||
        $("#ERP_insert").hide();
 | 
			
		||||
    }
 | 
			
		||||
    if (Edit) {
 | 
			
		||||
        $("a.green").show();
 | 
			
		||||
        $("#date_check").show();
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        $("a.green").hide();
 | 
			
		||||
        $("#date_check").hide();
 | 
			
		||||
    }
 | 
			
		||||
    if (Delete) {
 | 
			
		||||
        $("#checkDelete").show();
 | 
			
		||||
        $("#date_check").show();
 | 
			
		||||
        $("a.red").show();
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        $("#checkDelete").hide();
 | 
			
		||||
        $("#date_check").hide();
 | 
			
		||||
        $("a.red").hide();
 | 
			
		||||
    }
 | 
			
		||||
    if (Print) {
 | 
			
		||||
        $("a[name='print']").show();
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        $("a[name='print']").hide();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let hide_star = "********";
 | 
			
		||||
 | 
			
		||||
/* @deprecated since version 0.2
 | 
			
		||||
*  @description replace the field
 | 
			
		||||
*  @param {String} the element id
 | 
			
		||||
*  @param {Boolean} ready only
 | 
			
		||||
*  @author Darren Chen
 | 
			
		||||
*  @date   2018/04/18
 | 
			
		||||
*/
 | 
			
		||||
function hide_field(tag, is_readonly = null) {
 | 
			
		||||
    var text = "";
 | 
			
		||||
    $(tag).each(function () {
 | 
			
		||||
        if ($(this).prop("tagName").toLowerCase() === "input") {
 | 
			
		||||
            text = $(this).val().toString();
 | 
			
		||||
            if (text === "-999999999") {
 | 
			
		||||
                $(this).val(hide_star);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if ($(this).prop("tagName").toLowerCase() === "div") {
 | 
			
		||||
            text = $(this).text().toString();
 | 
			
		||||
            if (text === "-999999999") {
 | 
			
		||||
                $(this).text(hide_star);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if ($(this).prop("tagName").toLowerCase() === "td") {
 | 
			
		||||
            text = $(this).text().toString();
 | 
			
		||||
            if (text === "-999999999") {
 | 
			
		||||
                $(this).text(hide_star);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (is_readonly) {
 | 
			
		||||
            $(this).prop("readonly", true);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* @deprecated since version 0.1
 | 
			
		||||
*  @description 阻止ServerSide Datatable 在特定時間內傳出大量值
 | 
			
		||||
*  @author JunHao Lin
 | 
			
		||||
*  @date   2021/12/22
 | 
			
		||||
*/
 | 
			
		||||
function serverSideExecLimit() {
 | 
			
		||||
    let lastTime;
 | 
			
		||||
    $($.fn.dataTable.tables(true)).on('order.dt page.dt search.dt xhr.dt', function (e, settings, ordArr) {
 | 
			
		||||
 | 
			
		||||
        //排序時Callback會回傳兩次,所以判斷時間差只抓取一次
 | 
			
		||||
        //(時間差之內的排序執行 || 換頁執行 || 搜尋執行)
 | 
			
		||||
        if (settings.oInit.bServerSide == true) {
 | 
			
		||||
            if (((e.timeStamp - lastTime <= 300 && (e.handleObj.origType == "order") || e.handleObj.origType == "page" || e.handleObj.origType == "search")) && settings.oAjaxData != undefined  && (settings.oAjaxData).length != 0) {
 | 
			
		||||
                
 | 
			
		||||
                if (tableStatus == 0) {   //tableStatus = 0 | 還沒觸發執行
 | 
			
		||||
                    tableStatus = 1  //tableStatus = 1 | 已觸發執行,可接受執行  
 | 
			
		||||
                    calEventTime = setInterval(function () {   //計數五秒
 | 
			
		||||
                        if (timeNum == 5) {   //若到第五秒
 | 
			
		||||
                            pageEventNum = searchEventNum = orderEventNum = 0  //執行次數復歸
 | 
			
		||||
                            timeNum = 0  //秒數歸零
 | 
			
		||||
                            tableStatus = 0  //狀態復歸
 | 
			
		||||
                            clearInterval(calEventTime)  //計數關閉
 | 
			
		||||
                        }
 | 
			
		||||
                        timeNum++;   //秒數++
 | 
			
		||||
                    }, 1000)
 | 
			
		||||
                }
 | 
			
		||||
                //在五秒之內,排序執行超過五次
 | 
			
		||||
                if (timeNum < 5 && orderEventNum >= 5 && e.handleObj.origType == "order" && tableStatus == 1) {
 | 
			
		||||
                    tableStatus = 2;
 | 
			
		||||
                }
 | 
			
		||||
                //在五秒之內,搜尋執行超過五次
 | 
			
		||||
                if (timeNum < 5 && searchEventNum >= 10 && e.handleObj.origType == "search" && tableStatus == 1) {
 | 
			
		||||
                    tableStatus = 2;
 | 
			
		||||
                }
 | 
			
		||||
                //在五秒之內,換頁執行超過五次
 | 
			
		||||
                if (timeNum < 5 && pageEventNum >= 5 && e.handleObj.origType == "page" && tableStatus == 1) {
 | 
			
		||||
                    tableStatus = 2;
 | 
			
		||||
                }
 | 
			
		||||
                //執行次數++
 | 
			
		||||
                switch (e.handleObj.origType) {
 | 
			
		||||
                    case "order":
 | 
			
		||||
                        orderEventNum++;
 | 
			
		||||
                        break;
 | 
			
		||||
                    case "search":
 | 
			
		||||
                        searchEventNum++;
 | 
			
		||||
                        break;
 | 
			
		||||
                    case "page":
 | 
			
		||||
                        pageEventNum++;
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                //tableStatus = 2 | 已觸發執行,不可接受執行(超出執行條件)  
 | 
			
		||||
                if (tableStatus == 2) {
 | 
			
		||||
                    showAlert("danger", "執行次數過多!")
 | 
			
		||||
                    loadingSetting("show","dtServerSide");    //出現loading
 | 
			
		||||
                    setTimeout(function () {
 | 
			
		||||
                        loadingSetting("hide", "dtServerSide");
 | 
			
		||||
                        pageEventNum = searchEventNum = orderEventNum = 0   //執行次數復歸
 | 
			
		||||
                        timeNum = 0  //秒數歸零
 | 
			
		||||
                        tableStatus = 0   //狀態復歸
 | 
			
		||||
                        clearInterval(calEventTime)   //計數關閉
 | 
			
		||||
                    }, 5000)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        lastTime = e.timeStamp;  //時間差
 | 
			
		||||
 | 
			
		||||
    }).DataTable()
 | 
			
		||||
}
 | 
			
		||||
YourTeam.JqDataTables.limitServerSideExec = serverSideExecLimit;
 | 
			
		||||
 | 
			
		||||
function sortNumbersIgnoreText(a, b, high) {
 | 
			
		||||
    var reg = /[+-]?((\d+(\.\d*)?)|\.\d+)([eE][+-]?[0-9]+)?/;
 | 
			
		||||
    a = a.match(reg);
 | 
			
		||||
    a = a !== null ? parseFloat(a[0]) : high;
 | 
			
		||||
    b = b.match(reg);
 | 
			
		||||
    b = b !== null ? parseFloat(b[0]) : high;
 | 
			
		||||
    return ((a < b) ? -1 : ((a > b) ? 1 : 0));
 | 
			
		||||
}
 | 
			
		||||
jQuery.extend(jQuery.fn.dataTableExt.oSort, {
 | 
			
		||||
    "sort-numbers-ignore-text-asc": function (a, b) {
 | 
			
		||||
        return sortNumbersIgnoreText(a, b, Number.POSITIVE_INFINITY);
 | 
			
		||||
    },
 | 
			
		||||
    "sort-numbers-ignore-text-desc": function (a, b) {
 | 
			
		||||
        return sortNumbersIgnoreText(a, b, Number.NEGATIVE_INFINITY) * -1;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										946
									
								
								Frontend/js/yourteam/yourteam.utility.class.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										946
									
								
								Frontend/js/yourteam/yourteam.utility.class.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,946 @@
 | 
			
		||||
var YourTeam = YourTeam || {};
 | 
			
		||||
YourTeam.Utility = YourTeam.Utility || {};
 | 
			
		||||
class UrlHelper {
 | 
			
		||||
    constructor() {
 | 
			
		||||
    }
 | 
			
		||||
    /* @deprecated since version 0.2
 | 
			
		||||
    *  @description get the param value
 | 
			
		||||
    *  @param {String} sName url param name
 | 
			
		||||
    *  @return {String}
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2018/04/18
 | 
			
		||||
    */
 | 
			
		||||
    param = function (sName) {
 | 
			
		||||
        this._sName = sName;
 | 
			
		||||
        let sReg = new RegExp("(^|&)" + _sName + "=([^&]*)(&|$)"); //創建一個含有目標参数的正則表達式對象
 | 
			
		||||
        let sMatchTarget = window.location.search.substr(1).match(sReg);  //匹配目標参數
 | 
			
		||||
        if (sMatchTarget !== null) {
 | 
			
		||||
            return unescape(sMatchTarget[2]);
 | 
			
		||||
        }
 | 
			
		||||
        return null; //返回参數值
 | 
			
		||||
    }
 | 
			
		||||
    /* @deprecated since version 0.2 
 | 
			
		||||
    *  @description get the param value form the page`s url
 | 
			
		||||
    *  @param {String} sName url param name
 | 
			
		||||
    *  @param {String} sPageName url page name
 | 
			
		||||
    *  @return {String}
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2018/04/18
 | 
			
		||||
    */
 | 
			
		||||
    paramForPage = function (sName, sPageName) {
 | 
			
		||||
        this.prototype = fnGetUrlParam;
 | 
			
		||||
        let str = this.prototype(sName);
 | 
			
		||||
        this._sPageName = sPageName;
 | 
			
		||||
        if (str !== null && window.location.href.indexOf(_sPageName) !== -1) {
 | 
			
		||||
            return str;
 | 
			
		||||
        }
 | 
			
		||||
        //if (location.pathname) {
 | 
			
		||||
        //    var sReg = new RegExp("(^|&)" + sName + "=([^&]*)(&|$)"); //創建一個含有目標参数的正則表達式對象
 | 
			
		||||
        //    var sMatchTarget = window.location.search.substr(1).match(sReg);  //匹配目標参數
 | 
			
		||||
        //    if (sMatchTarget !== null && window.location.href.indexOf(sPageName) !== -1) {
 | 
			
		||||
        //        return unescape(sMatchTarget[2]);
 | 
			
		||||
        //    }
 | 
			
		||||
        //}
 | 
			
		||||
        return null; //返回参數值
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
YourTeam.Utility.Url = YourTeam.Utility.Url || UrlHelper;
 | 
			
		||||
 | 
			
		||||
class UIOperat {
 | 
			
		||||
    constructor() {
 | 
			
		||||
    }
 | 
			
		||||
    /* @deprecated since version 0.1 
 | 
			
		||||
    *  @description disabled all element in the page (close out some element)
 | 
			
		||||
    *  @param {Array} aOutElementId close out element array
 | 
			
		||||
    *  @return 
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2018/04/22
 | 
			
		||||
    */
 | 
			
		||||
    disabledAllElement = function (aOutElementId) {
 | 
			
		||||
        let aElement = document.getElementsByTagName("input");
 | 
			
		||||
        fnSetAllElementDisabled(aElement, aOutElementId);
 | 
			
		||||
 | 
			
		||||
        aElement = document.getElementsByTagName("textarea");
 | 
			
		||||
        fnSetAllElementDisabled(aElement, aOutElementId);
 | 
			
		||||
 | 
			
		||||
        aElement = document.getElementsByTagName("select");
 | 
			
		||||
        fnSetAllElementDisabled(aElement, aOutElementId);
 | 
			
		||||
 | 
			
		||||
        aElement = document.getElementsByTagName("button");
 | 
			
		||||
        fnSetAllElementDisabled(aElement, aOutElementId);
 | 
			
		||||
 | 
			
		||||
        //aElement = document.getElementsByTagName("label");
 | 
			
		||||
        //for (var i = 0; i < aElement.length; i++) {
 | 
			
		||||
        //    for (var ii = 0; ii < aOutElementId.length; ii++) {
 | 
			
		||||
        //        if (aElement[i] != aOutElementId[ii])
 | 
			
		||||
        //            aElement[i].setAttribute("style", "pointer-events:none;display:block;");
 | 
			
		||||
        //    }
 | 
			
		||||
        //}
 | 
			
		||||
    }
 | 
			
		||||
    /* @deprecated since version 0.1 
 | 
			
		||||
    *  @description  set all element disabled (close out some element)
 | 
			
		||||
    *  @param {Array} aElement element array
 | 
			
		||||
    *  @param {Array} aOutElementId close out element array
 | 
			
		||||
    *  @return 
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2018/04/22
 | 
			
		||||
    */
 | 
			
		||||
    setAllElementDisabled = function (aElement, aOutElementId) {
 | 
			
		||||
        for (let i = 0; i < aElement.length; i++) {
 | 
			
		||||
 | 
			
		||||
            for (let ii = 0; ii < aOutElementId.length; ii++) {
 | 
			
		||||
                if (aElement[i] !== aOutElementId[ii])
 | 
			
		||||
                    aElement[i].disabled = true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* @deprecated since version 0.1 
 | 
			
		||||
    *  @description get checked checkboxs (array) for this project
 | 
			
		||||
    *  @param {string} checkBoxName  the delete checkbox`s element name
 | 
			
		||||
    *  @return 
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2018/07/24
 | 
			
		||||
    */
 | 
			
		||||
    getCheckedArray(checkBoxName = "id") {
 | 
			
		||||
        return $('input:checkbox[name=' + checkBoxName + ']:checked').map(function () {
 | 
			
		||||
            return $(this).val();
 | 
			
		||||
        }).get();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
YourTeam.Utility.UIOperat = YourTeam.Utility.UIOperat || UIOperat;
 | 
			
		||||
 | 
			
		||||
class UIData {
 | 
			
		||||
    constructor() {
 | 
			
		||||
    }
 | 
			
		||||
    /* @deprecated since version 0.1 
 | 
			
		||||
    *  @description get checked checkboxs 
 | 
			
		||||
    *  @param {String} checkBoxName  the delete checkbox`s element name
 | 
			
		||||
    *  @return ex."551,676,991,188,457,125"
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2018/07/24
 | 
			
		||||
    */
 | 
			
		||||
    checkBoxValueJoin = function (checkBoxName) {
 | 
			
		||||
        return $('input:checkbox[name=' + checkBoxName + ']:checked').map(function () {
 | 
			
		||||
            return $(this).val();
 | 
			
		||||
        }).get().join(',');
 | 
			
		||||
    }
 | 
			
		||||
    /* @deprecated since version 0.1 
 | 
			
		||||
    *  @description get checked checkboxs 
 | 
			
		||||
    *  @param {String} checkBoxName  the delete checkbox`s element name
 | 
			
		||||
    *  @return ex."551,676,991,188,457,125"
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2018/07/24
 | 
			
		||||
    */
 | 
			
		||||
    checkBoxValueArray = function (checkBoxName) {
 | 
			
		||||
        let ary = [];
 | 
			
		||||
        $('input:checkbox[name=' + checkBoxName + ']:checked').each(function (index, element) {
 | 
			
		||||
            ary.push($(element).val());
 | 
			
		||||
        });
 | 
			
		||||
        return ary;
 | 
			
		||||
    }
 | 
			
		||||
    /* @deprecated since version 0.1
 | 
			
		||||
    *  @description Convrt Int To Float
 | 
			
		||||
    *  @param {String} number ori number
 | 
			
		||||
    *  @param {String} keepNum keep number after .
 | 
			
		||||
    *  @return {String}
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2019/12/31
 | 
			
		||||
    */
 | 
			
		||||
    convrtIntToFloat = function (number, keepNum) {
 | 
			
		||||
        let zeroNumber = fnPaddingRight("1", keepNum + 1, "0");
 | 
			
		||||
        zeroNumber = parseInt(zeroNumber);
 | 
			
		||||
        return Math.round(parseFloat(number) * zeroNumber) / zeroNumber;
 | 
			
		||||
    }
 | 
			
		||||
    /* @deprecated since version 0.1
 | 
			
		||||
    *  @description The string Padding Left char
 | 
			
		||||
    *  @param {String} str ori string
 | 
			
		||||
    *  @param {Number} lenght will get string`s lenght
 | 
			
		||||
    *  @param {String} add char
 | 
			
		||||
    *  @return {String}
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2019/12/31
 | 
			
		||||
    */
 | 
			
		||||
    paddingLeft = function (str, lenght, char) {
 | 
			
		||||
        if (str.length >= lenght)
 | 
			
		||||
            return str;
 | 
			
		||||
        else
 | 
			
		||||
            return fnPaddingLeft(char + str, lenght);
 | 
			
		||||
    }
 | 
			
		||||
    /* @deprecated since version 0.1
 | 
			
		||||
    *  @description The string Padding Right char
 | 
			
		||||
    *  @param {String} str ori string
 | 
			
		||||
    *  @param {Number} lenght will get string`s lenght
 | 
			
		||||
    *  @param {String} add char 
 | 
			
		||||
    *  @return {String}
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2019/12/31
 | 
			
		||||
    */
 | 
			
		||||
    paddingRight = function (str, lenght, char) {
 | 
			
		||||
        if (str.length >= lenght)
 | 
			
		||||
            return str;
 | 
			
		||||
        else
 | 
			
		||||
            return fnPaddingRight(str + char, lenght);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
YourTeam.Utility.UIData = YourTeam.Utility.UIData || UIData;
 | 
			
		||||
 | 
			
		||||
class CookieHelper {
 | 
			
		||||
    constructor() {
 | 
			
		||||
    }
 | 
			
		||||
    /* @deprecated since version 0.1 
 | 
			
		||||
    *  @description Create a simple cookie  (The duration is preset to 2 days)
 | 
			
		||||
    *  @param {String} name  name with the cookie
 | 
			
		||||
    *  @param {String} value  value with the cookie
 | 
			
		||||
    *  @return 
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2018/07/24
 | 
			
		||||
    */
 | 
			
		||||
    create = function (name, value) {
 | 
			
		||||
        let expires = new Date();
 | 
			
		||||
        //有效時間保存 2 天 2*24*60*60*1000
 | 
			
		||||
        expires.setTime(expires.getTime() + 172800000);
 | 
			
		||||
        document.cookie = name + "=" + escape(value) + ";expires=" + expires.toGMTString();
 | 
			
		||||
    }
 | 
			
		||||
    /* @deprecated since version 0.1 
 | 
			
		||||
    *  @description Get the cookie value by cookie name
 | 
			
		||||
    *  @param {String} name  name with the cookie
 | 
			
		||||
    *  @return {String}
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2018/07/24
 | 
			
		||||
    */
 | 
			
		||||
    get(name) {
 | 
			
		||||
        let arg = escape(name) + "=";
 | 
			
		||||
        let nameLen = arg.length;
 | 
			
		||||
        let cookieLen = document.cookie.length;
 | 
			
		||||
        let i = 0;
 | 
			
		||||
        while (i < cookieLen) {
 | 
			
		||||
            let j = i + nameLen;
 | 
			
		||||
            if (document.cookie.substring(i, j) === arg) return this.getByIndex(j);
 | 
			
		||||
            i = document.cookie.indexOf(" ", i) + 1;
 | 
			
		||||
            if (i === 0) break;
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    /* @deprecated since version 0.1 
 | 
			
		||||
    *  @description Get the cookie value by index
 | 
			
		||||
    *  @param {Number} index  name with the cookie
 | 
			
		||||
    *  @return {String}
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2018/07/24
 | 
			
		||||
    */
 | 
			
		||||
    getByIndex(startIndex) {
 | 
			
		||||
        let endIndex = document.cookie.indexOf(";", startIndex);
 | 
			
		||||
        if (endIndex === -1) endIndex = document.cookie.length;
 | 
			
		||||
        return unescape(document.cookie.substring(startIndex, endIndex));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* @deprecated since version 0.1
 | 
			
		||||
    *  @description Remove the cookie by cookie name
 | 
			
		||||
    *  @param {String} name  name with the cookie
 | 
			
		||||
    *  @return {Boolean}
 | 
			
		||||
    *  @author Darren Chen
 | 
			
		||||
    *  @date   2021/05/27
 | 
			
		||||
    */
 | 
			
		||||
    remove(name) {
 | 
			
		||||
        document.cookie = name + "=; expires=Thu, 01 Jan 1970 00:00:01 GMT;";
 | 
			
		||||
        if (this.get(name) === null || this.get(name) === "undefined") {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
YourTeam.Utility.Cookie = YourTeam.Utility.Cookie || CookieHelper;
 | 
			
		||||
 | 
			
		||||
var mathHelperRandomNotRepeatNum = [];
 | 
			
		||||
class MathHelper {
 | 
			
		||||
    constructor() {
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 取得隨機值
 | 
			
		||||
    * @param {Number} min 最小值
 | 
			
		||||
    * @param {Number} max 最大值
 | 
			
		||||
    * @returns {Number} 
 | 
			
		||||
    */
 | 
			
		||||
    random(min, max) {
 | 
			
		||||
        return Math.floor(Math.random() * max) + min;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 取得GUID
 | 
			
		||||
    * @param {String} str 分隔符號,預設值'-'。
 | 
			
		||||
    * @param {Boolean} isUpperCase 是否大寫,預設值true。
 | 
			
		||||
    * @returns {String} 
 | 
			
		||||
    */
 | 
			
		||||
    guid(str = null, isUpperCase = true) {
 | 
			
		||||
        let strGuid = 'xxxxxxxx-xxxx-0xxx-yxyx-xxxxxxxxxxxx';
 | 
			
		||||
        if (str) {
 | 
			
		||||
            strGuid = strGuid.replace('-', str);
 | 
			
		||||
        }
 | 
			
		||||
        strGuid = strGuid.replace(/[xy]/g, function (c) {
 | 
			
		||||
            var string = Math.random() * 16 | 0, v = c === 'x' ? string : (string & 0x3 | 0x8);
 | 
			
		||||
            return string.toString(16);
 | 
			
		||||
        });
 | 
			
		||||
        if (isUpperCase) {
 | 
			
		||||
            strGuid.toUpperCase();
 | 
			
		||||
        }
 | 
			
		||||
        return strGuid;
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 四捨五入取小數點後2位
 | 
			
		||||
    * @param {Number} num 數值
 | 
			
		||||
    * @returns {Number} 
 | 
			
		||||
    */
 | 
			
		||||
    roundRight2p(num) {
 | 
			
		||||
        return +(Math.round(num + "e+2") + "e-2");
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 四捨五入取小數點後2位
 | 
			
		||||
    * @param {Number} num 數值
 | 
			
		||||
    * @returns {Number} 
 | 
			
		||||
    */
 | 
			
		||||
    roundRight2p2(num) {
 | 
			
		||||
        let m = Number((Math.abs(num) * 100).toPrecision(15));
 | 
			
		||||
        return Math.round(m) / 100 * Math.sign(num);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
YourTeam.Utility.Math = YourTeam.Utility.Math || MathHelper;
 | 
			
		||||
 | 
			
		||||
class DateHelper {
 | 
			
		||||
    constructor() {
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 取得現在時間(yyyy-MM-dd)
 | 
			
		||||
    * @param {Boolean} isTwYear it`s Taiwan year?
 | 
			
		||||
    * @returns {String} 
 | 
			
		||||
    */
 | 
			
		||||
    getNow = function (isTwYear = false) {
 | 
			
		||||
        let d = new Date();
 | 
			
		||||
        let year = isTwYear ? d.getFullYear() - 1911 : d.getFullYear();
 | 
			
		||||
        let month = d.getMonth() + 1;
 | 
			
		||||
        let day = d.getDate();
 | 
			
		||||
 | 
			
		||||
        let now = year + '-' +
 | 
			
		||||
            (month < 10 ? '0' : '') + month + '-' +
 | 
			
		||||
            (day < 10 ? '0' : '') + day;
 | 
			
		||||
 | 
			
		||||
        return now;
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 取得日期時間(2020/02/02 PM 18:05:25)
 | 
			
		||||
    * @param {Boolean} isTwYear it`s Taiwan year?
 | 
			
		||||
    * @param {String} dateInterval 最小值
 | 
			
		||||
    * @param {Boolean} isPadZero 最大值
 | 
			
		||||
    * @param {Number} timeTagType 時間前戳標記 1:AM/PM  2:上午/下午
 | 
			
		||||
    * @returns {String} 
 | 
			
		||||
    */
 | 
			
		||||
    getNowHaveTimeTag = function (isTwYear = false, dateInterval = '/', isPadZero = true, timeTagType = 1) {
 | 
			
		||||
        let now = new Date();
 | 
			
		||||
        let years = isTwYear ? now.getFullYear() - 1911 : now.getFullYear();
 | 
			
		||||
        let months = now.getMonth();
 | 
			
		||||
        let days = now.getDay();
 | 
			
		||||
        let hours = now.getHours();
 | 
			
		||||
        let minutes = now.getMinutes();
 | 
			
		||||
        let seconds = now.getSeconds();
 | 
			
		||||
 | 
			
		||||
        let dateValue = years;
 | 
			
		||||
        let timeValue = ((hours >= 12) ? "下午 " : "上午 ");
 | 
			
		||||
        if (timeTagType === 2) timeValue = ((hours >= 12) ? "AM " : "PM ");
 | 
			
		||||
        if (isPadZero) {
 | 
			
		||||
            dateValue += (dateInterval + ((months < 10) ? "0" : "") + months);
 | 
			
		||||
            dateValue += (dateInterval + ((days < 10) ? "0" : "") + days);
 | 
			
		||||
            timeValue += ((hours > 12) ? "0" + (hours - 12) : hours);
 | 
			
		||||
            timeValue += ((minutes < 10) ? ":0" : ":") + minutes;
 | 
			
		||||
            timeValue += ((seconds < 10) ? ":0" : ":") + seconds;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            dateValue += (dateInterval + months);
 | 
			
		||||
            dateValue += (dateInterval + days);
 | 
			
		||||
            timeValue += ((hours > 12) ? hours - 12 : hours);
 | 
			
		||||
            timeValue += minutes;
 | 
			
		||||
            timeValue += seconds;
 | 
			
		||||
        }
 | 
			
		||||
        return dateValue + " " + timeValue;
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 取得日期時間(2020/02/02 18:05:25)
 | 
			
		||||
    * @param {Boolean} isTwYear it`s Taiwan year?
 | 
			
		||||
    * @param {String} dateInterval 日期間隔字元
 | 
			
		||||
    * @param {Boolean} isPadZero   是否補0
 | 
			
		||||
    * @returns {String} 回傳時間字串
 | 
			
		||||
    */
 | 
			
		||||
    getNowChangeInterval = function (isTwYear = false, dateInterval = '/', isPadZero = true) {
 | 
			
		||||
        let today = new Date();
 | 
			
		||||
        let year = isTwYear ? today.getFullYear() - 1911 : today.getFullYear();
 | 
			
		||||
        let currentDateTime =
 | 
			
		||||
            year + dateInterval + ((isPadZero && today.getMonth() + 1 < 10) ? '0' : '') +
 | 
			
		||||
            (today.getMonth() + 1) + dateInterval + ((isPadZero && today.getDate() < 10) ? '0' : '') +
 | 
			
		||||
            today.getDate() + ' ' + ((isPadZero && today.getHours() < 10) ? '0' : '') +
 | 
			
		||||
            today.getHours() + ':' + ((isPadZero && today.getMinutes() < 10) ? '0' : '') +
 | 
			
		||||
            today.getMinutes();
 | 
			
		||||
        return currentDateTime;
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 取得加減的日期時間(2020/02/02 18:05:25)
 | 
			
		||||
    * @param {Boolean} isTwYear it`s Taiwan year?
 | 
			
		||||
    * @param {String} dateInterval 日期間隔字元
 | 
			
		||||
    * @param {Boolean} isPadZero   是否補0
 | 
			
		||||
    * @returns {String} 回傳時間字串
 | 
			
		||||
    */
 | 
			
		||||
    getChangeDateTime(isTwYear = false, dateInterval = '/', addYears = 0, addMonths = 0, addDays = 0, isPadZero = true) {
 | 
			
		||||
        let today = new Date();
 | 
			
		||||
        let year = isTwYear ? today.getFullYear() - 1911 : today.getFullYear();
 | 
			
		||||
        if (addYears > year || addMonths > today.getMonth() || addDays > today.getDate()) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        let date =
 | 
			
		||||
            (year + addYears) + dateInterval + ((isPadZero && today.getMonth() + addMonths + 1 < 10) ? '0' : '') +
 | 
			
		||||
            (today.getMonth() + addMonths + 1) + dateInterval + ((isPadZero && today.getDate() + addDays < 10) ? '0' : '') +
 | 
			
		||||
            (today.getDate() + addDays);
 | 
			
		||||
        return date;
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 取得禮拜/週幾(禮拜五)
 | 
			
		||||
    * @param {String} dayPreString 前置詞 (禮拜/週/周)
 | 
			
		||||
    * @returns {String} 回傳時間字串
 | 
			
		||||
    */
 | 
			
		||||
    getWeekDay(dayPreString = "") {
 | 
			
		||||
        let day = "";
 | 
			
		||||
        let day_list = ['日', '一', '二', '三', '四', '五', '六'];
 | 
			
		||||
 | 
			
		||||
        let today = new Date();
 | 
			
		||||
        let dayGet = today.getDay(); // or "new Date().getDay()";
 | 
			
		||||
        if (dayPreString === "") {
 | 
			
		||||
            day = "(" + day_list[dayGet] + ")";
 | 
			
		||||
        } else {
 | 
			
		||||
            day = dayPreString + day_list[dayGet];
 | 
			
		||||
        }
 | 
			
		||||
        return day;
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 取得月份天數
 | 
			
		||||
    * @param {Number} year 年份 (def null)
 | 
			
		||||
    * @param {Number} month 月份 (def null)
 | 
			
		||||
    * @returns {Number} 回傳月份天數
 | 
			
		||||
    */
 | 
			
		||||
    getMonthDayCount(year=null,month=null) {
 | 
			
		||||
        let myYear = year;
 | 
			
		||||
        let myMonth = month;
 | 
			
		||||
        let myDate,myDayCount;
 | 
			
		||||
        
 | 
			
		||||
        if (!myYear) {
 | 
			
		||||
            myYear = new Date().getFullYear();
 | 
			
		||||
        }
 | 
			
		||||
        if (!myMonth) {
 | 
			
		||||
            myMonth = new Date().getMonth();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //宣告日期物件
 | 
			
		||||
        myDate = new Date(myYear, myMonth+1, 0);
 | 
			
		||||
        //取得天數
 | 
			
		||||
        myDayCount = myDate.getDate();
 | 
			
		||||
 | 
			
		||||
        return daycount;
 | 
			
		||||
    }
 | 
			
		||||
    /*
 | 
			
		||||
    * @deprecated since version 0.1
 | 
			
		||||
    * @description 取得月份最後一天的日期字串
 | 
			
		||||
    * @param {Number} year 年份 (def null)
 | 
			
		||||
    * @param {Number} month 月份 (def null)
 | 
			
		||||
    * @returns {String} 回傳月份天數字串
 | 
			
		||||
    */
 | 
			
		||||
    getMonthLastDateStr(year = null, month = null) {
 | 
			
		||||
        let myYear = year;
 | 
			
		||||
        let myMonth = month;
 | 
			
		||||
        let daycount;
 | 
			
		||||
        if (!myYear) {
 | 
			
		||||
            myYear = new Date().getFullYear();
 | 
			
		||||
        }
 | 
			
		||||
        if (!myMonth) {
 | 
			
		||||
            myMonth = new Date().getMonth();
 | 
			
		||||
        }
 | 
			
		||||
        daycount = this.getMonthDayCount(year, month);
 | 
			
		||||
        let myMonthLastDate = myYear + "/"
 | 
			
		||||
            + (myMonth < 10) ? "0" : "" + myMonth + "/"
 | 
			
		||||
            + (daycount < 10) ? "0" : "" + daycount;
 | 
			
		||||
 | 
			
		||||
        return myMonthLastDate;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
YourTeam.Utility.DateHelper = YourTeam.Utility.DateHelper || DateHelper;
 | 
			
		||||
 | 
			
		||||
class File {
 | 
			
		||||
    constructor() {
 | 
			
		||||
    }
 | 
			
		||||
    readAndPreviewImages(files, containerId, imgWidth = null, imgHeight = null, frontHtml = null, backHtml = null, funDoSomeThing = null, limitMaxSize = null, limitMinSize = 0,limitFun = null) {
 | 
			
		||||
        let htmlImg = "";
 | 
			
		||||
        let container = document.getElementById(containerId);
 | 
			
		||||
        let width = imgWidth ? imgWidth + "px" : "auto";
 | 
			
		||||
        let height = imgHeight ? imgHeight + "px" : "auto";
 | 
			
		||||
        let myMath = new YourTeam.Utility.Math();
 | 
			
		||||
        let myFile = new YourTeam.Utility.File();
 | 
			
		||||
        let strExtName = "",strOrgName="";
 | 
			
		||||
        for (let i = 0; i < files.length; i++) {
 | 
			
		||||
            let file = files[i];
 | 
			
		||||
            if (limitMaxSize != null) {
 | 
			
		||||
                if (file.size / 1024 < limitMinSize || file.size / 1024 > limitMaxSize) {
 | 
			
		||||
                    limitFun ? limitFun() : "";
 | 
			
		||||
                    return false
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            htmlImg = "";
 | 
			
		||||
            if (/\.(jpe?g|png|gif)$/i.test(file.name)) {
 | 
			
		||||
 | 
			
		||||
                let reader = new FileReader();
 | 
			
		||||
                reader.addEventListener("load", function () {
 | 
			
		||||
                    let image = new Image();
 | 
			
		||||
                    let src = this.result;
 | 
			
		||||
                    image.src = this.result;
 | 
			
		||||
 | 
			
		||||
                    image.onload = function () {
 | 
			
		||||
                        strExtName = myFile.getFileExtension(file.name);
 | 
			
		||||
                        strOrgName = (strExtName === null || strExtName === "") ? file.name : file.name.replace('.' + strExtName, '');
 | 
			
		||||
                        htmlImg = frontHtml + '<img data-filename="' + file.name + '" data-orgname="' + strOrgName + '" data-savename="' + myMath.guid().replace(' ', '') + '" data-extname="' + strExtName
 | 
			
		||||
                            + '" data-size="' + file.size + '" width="' + width + '" height="' + height + '" src="' + src + '">'
 | 
			
		||||
                            + backHtml;
 | 
			
		||||
                        container.insertAdjacentHTML("afterBegin", htmlImg);
 | 
			
		||||
                        //$("[name=" + removeClickTagName + "]").on("click", function (e) {
 | 
			
		||||
                        //    e.preventDefault();
 | 
			
		||||
                        //    $(this).closest(removeTag).remove();
 | 
			
		||||
                        //});
 | 
			
		||||
                        if (i === files.length - 1 && funDoSomeThing) {
 | 
			
		||||
                            funDoSomeThing();
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
                reader.readAsDataURL(file);
 | 
			
		||||
            } else {
 | 
			
		||||
                if (showAlert) { 
 | 
			
		||||
                    showAlert("danger", "只支援圖片格式");
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    alert("只支援圖片格式");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    readAndPreviewFiles(files, containerId, imgWidth = null, imgHeight = null, frontHtml = null, backHtml = null, funDoSomeThing = null) {
 | 
			
		||||
        let htmlImg = "";
 | 
			
		||||
        let container = document.getElementById(containerId);
 | 
			
		||||
        let width = imgWidth ? imgWidth + "px" : "128px";
 | 
			
		||||
        let height = imgHeight ? imgHeight + "px" : "86px";
 | 
			
		||||
        let myMath = new YourTeam.Utility.Math();
 | 
			
		||||
        let myFile = new YourTeam.Utility.File();
 | 
			
		||||
        let strExtName = "", strOrgName = "", strSaveName = "";
 | 
			
		||||
        
 | 
			
		||||
        for (let i = 0; i < files.length; i++) {
 | 
			
		||||
            let file = files[i];
 | 
			
		||||
            htmlImg = "";
 | 
			
		||||
            //alert(/\.(xls?x|doc?x|ptt?x|pdf|zip|rar|7zip|txt|odt|xml|rtf|ods|odp|pps?x)$/i.test(file.name));
 | 
			
		||||
            if (/\.(xls?x|doc?x|ptt?x|pdf|zip|rar|7zip|txt|odt|xml|rtf|ods|odp|pps?x)$/i.test(file.name)) {
 | 
			
		||||
 | 
			
		||||
                if (file.size == 0) {  //檔案大小為0時不會產生base64,需防呆
 | 
			
		||||
                    showAlert("danger", "無法上傳大小為0的檔案");
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                //先新增a標籤 在套上src 可能解決多檔案上傳時無法讀取到最後上傳檔案的問題
 | 
			
		||||
                strSaveName = myMath.guid().replace(' ', '');
 | 
			
		||||
                strExtName = myFile.getFileExtension(file.name);
 | 
			
		||||
                strOrgName = (strExtName === null || strExtName === "") ? file.name : file.name.replace('.' + strExtName, '');
 | 
			
		||||
   
 | 
			
		||||
                htmlImg = frontHtml + '<a id="' + strSaveName +'" data-filename="' + file.name + '" data-orgname="' + strOrgName + '" data-savename="' + strSaveName + '" data-extname="' + strExtName
 | 
			
		||||
                    + '" data-size="' + file.size + '" width="' + width + '" height="' + height +'" download="' + strOrgName + '.' + strExtName + '" target="_blank">' + strOrgName + '.' + strExtName + '</a>'
 | 
			
		||||
                    + backHtml;
 | 
			
		||||
                container.insertAdjacentHTML("afterBegin", htmlImg);
 | 
			
		||||
                let reader = new FileReader();
 | 
			
		||||
 | 
			
		||||
                reader.addEventListener("load", function (event) {
 | 
			
		||||
                    $($(container).find("a")[i]).attr("href", this.result);
 | 
			
		||||
                    if (i === files.length - 1 && funDoSomeThing) {
 | 
			
		||||
                        funDoSomeThing();
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
                reader.readAsDataURL(file);
 | 
			
		||||
      
 | 
			
		||||
            } else {
 | 
			
		||||
                if (showAlert) {
 | 
			
		||||
                    showAlert("danger", "只支援文件格式");
 | 
			
		||||
                } else {
 | 
			
		||||
                    alert("只支援文件格式");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    async getBase64Image(path, callback) {
 | 
			
		||||
        //生成canvas  
 | 
			
		||||
        var canvas = document.createElement('canvas');
 | 
			
		||||
        var ctx = canvas.getContext('2d');
 | 
			
		||||
        var img = new Image();
 | 
			
		||||
        img.src = path;
 | 
			
		||||
        img.setAttribute("crossOrigin", "Anonymous");
 | 
			
		||||
        img.onload = await function () {
 | 
			
		||||
            return new Promise((resolve) => { 
 | 
			
		||||
                //默認按比例壓縮  
 | 
			
		||||
                var w = this.width,
 | 
			
		||||
                    h = this.height;
 | 
			
		||||
                var quality = 0.95; // 默認圖片質量為0.7  
 | 
			
		||||
 | 
			
		||||
                // 創建屬性節點  
 | 
			
		||||
                canvas.setAttribute("width", w);
 | 
			
		||||
                canvas.setAttribute("height", h);
 | 
			
		||||
 | 
			
		||||
                ctx.drawImage(this, 0, 0, w, h);
 | 
			
		||||
                // quality值越小,所繪制出的圖像越模糊  
 | 
			
		||||
                var base64 = canvas.toDataURL('image/jpeg', quality);
 | 
			
		||||
                // 回調函數返回base64的值  
 | 
			
		||||
                callback(base64);
 | 
			
		||||
                resolve();
 | 
			
		||||
            })
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getFileExtension(filename) {
 | 
			
		||||
        return filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
YourTeam.Utility.File = YourTeam.Utility.File || File;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* @deprecated since version 0.1 
 | 
			
		||||
*  @description jQuery Ajax Cors Setings (JSONP)
 | 
			
		||||
*  @return 
 | 
			
		||||
*  @author Darren Chen
 | 
			
		||||
*  @date   2018/07/24
 | 
			
		||||
*/
 | 
			
		||||
///// <reference path="/Scripts/YourTeam/js/yourteam.jq.ajax.cors.js" />
 | 
			
		||||
//var script = document.createElement("script"); //Make a script DOM node
 | 
			
		||||
//script.src = "/Scripts/YourTeam/js/yourteam.jq.ajax.cors.js"; //Set it's src to the provided URL
 | 
			
		||||
//document.head.appendChild(script); //Add it to the end of the head section of the page (could change 'head' to 'body' to add it to the end of the body section instead)
 | 
			
		||||
 | 
			
		||||
///* @deprecated since version 0.2
 | 
			
		||||
//*  @description get the param value
 | 
			
		||||
//*  @param {String} sName url param name
 | 
			
		||||
//*  @return {String}
 | 
			
		||||
//*  @author Darren Chen
 | 
			
		||||
//*  @date   2018/04/18
 | 
			
		||||
//*/
 | 
			
		||||
//function fnGetUrlParam(sName) {
 | 
			
		||||
//    this._sName = sName;
 | 
			
		||||
//    let sReg = new RegExp("(^|&)" + _sName + "=([^&]*)(&|$)"); //創建一個含有目標参数的正則表達式對象
 | 
			
		||||
//    let sMatchTarget = window.location.search.substr(1).match(sReg);  //匹配目標参數
 | 
			
		||||
//    if (sMatchTarget !== null) {
 | 
			
		||||
//        return unescape(sMatchTarget[2]);
 | 
			
		||||
//    }
 | 
			
		||||
//    return null; //返回参數值
 | 
			
		||||
//}
 | 
			
		||||
///* @deprecated since version 0.2 
 | 
			
		||||
//*  @description get the param value form the page`s url
 | 
			
		||||
//*  @param {String} sName url param name
 | 
			
		||||
//*  @param {String} sPageName url page name
 | 
			
		||||
//*  @return {String}
 | 
			
		||||
//*  @author Darren Chen
 | 
			
		||||
//*  @date   2018/04/18
 | 
			
		||||
//*/
 | 
			
		||||
//function fnGetUrlParamForPage(sName, sPageName) {
 | 
			
		||||
//    this.prototype = fnGetUrlParam;
 | 
			
		||||
//    let str = this.prototype(sName);
 | 
			
		||||
//    this._sPageName = sPageName;
 | 
			
		||||
//    if (str !== null && window.location.href.indexOf(_sPageName) !== -1) {
 | 
			
		||||
//        return str;
 | 
			
		||||
//    }
 | 
			
		||||
//    //if (location.pathname) {
 | 
			
		||||
//    //    var sReg = new RegExp("(^|&)" + sName + "=([^&]*)(&|$)"); //創建一個含有目標参数的正則表達式對象
 | 
			
		||||
//    //    var sMatchTarget = window.location.search.substr(1).match(sReg);  //匹配目標参數
 | 
			
		||||
//    //    if (sMatchTarget !== null && window.location.href.indexOf(sPageName) !== -1) {
 | 
			
		||||
//    //        return unescape(sMatchTarget[2]);
 | 
			
		||||
//    //    }
 | 
			
		||||
//    //}
 | 
			
		||||
//    return null; //返回参數值
 | 
			
		||||
//}
 | 
			
		||||
///* @deprecated since version 0.1 
 | 
			
		||||
//*  @description disabled all element in the page (close out some element)
 | 
			
		||||
//*  @param {Array} aOutElementId close out element array
 | 
			
		||||
//*  @return 
 | 
			
		||||
//*  @author Darren Chen
 | 
			
		||||
//*  @date   2018/04/22
 | 
			
		||||
//*/
 | 
			
		||||
//function fnDisabledAllElement(aOutElementId) {
 | 
			
		||||
//    let aElement = document.getElementsByTagName("input");
 | 
			
		||||
//    fnSetAllElementDisabled(aElement, aOutElementId);
 | 
			
		||||
 | 
			
		||||
//    aElement = document.getElementsByTagName("textarea");
 | 
			
		||||
//    fnSetAllElementDisabled(aElement, aOutElementId);
 | 
			
		||||
 | 
			
		||||
//    aElement = document.getElementsByTagName("select");
 | 
			
		||||
//    fnSetAllElementDisabled(aElement, aOutElementId);
 | 
			
		||||
 | 
			
		||||
//    aElement = document.getElementsByTagName("button");
 | 
			
		||||
//    fnSetAllElementDisabled(aElement, aOutElementId);
 | 
			
		||||
 | 
			
		||||
//    //aElement = document.getElementsByTagName("label");
 | 
			
		||||
//    //for (var i = 0; i < aElement.length; i++) {
 | 
			
		||||
//    //    for (var ii = 0; ii < aOutElementId.length; ii++) {
 | 
			
		||||
//    //        if (aElement[i] != aOutElementId[ii])
 | 
			
		||||
//    //            aElement[i].setAttribute("style", "pointer-events:none;display:block;");
 | 
			
		||||
//    //    }
 | 
			
		||||
//    //}
 | 
			
		||||
//}
 | 
			
		||||
///* @deprecated since version 0.1 
 | 
			
		||||
//*  @description  set all element disabled (close out some element)
 | 
			
		||||
//*  @param {Array} aElement element array
 | 
			
		||||
//*  @param {Array} aOutElementId close out element array
 | 
			
		||||
//*  @return 
 | 
			
		||||
//*  @author Darren Chen
 | 
			
		||||
//*  @date   2018/04/22
 | 
			
		||||
//*/
 | 
			
		||||
//function fnSetAllElementDisabled(aElement, aOutElementId) {
 | 
			
		||||
//    for (let i = 0; i < aElement.length; i++) {
 | 
			
		||||
 | 
			
		||||
//        for (let ii = 0; ii < aOutElementId.length; ii++) {
 | 
			
		||||
//            if (aElement[i] !== aOutElementId[ii])
 | 
			
		||||
//                aElement[i].disabled = true;
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
//    }
 | 
			
		||||
//}
 | 
			
		||||
///* @deprecated since version 0.1 
 | 
			
		||||
//*  @description get checked checkboxs 
 | 
			
		||||
//*  @param {String} checkBoxName  the delete checkbox`s element name
 | 
			
		||||
//*  @return 
 | 
			
		||||
//*  @author Darren Chen
 | 
			
		||||
//*  @date   2018/07/24
 | 
			
		||||
//*/
 | 
			
		||||
//function fnGetCheckedValue(checkBoxName) {
 | 
			
		||||
//    return $('input:checkbox[name=' + checkBoxName + ']:checked').map(function () {
 | 
			
		||||
//        return $(this).val();
 | 
			
		||||
//    }).get().join(',');
 | 
			
		||||
//}
 | 
			
		||||
///* @deprecated since version 0.1 
 | 
			
		||||
//*  @description Create a simple cookie  (The duration is preset to 2 days)
 | 
			
		||||
//*  @param {String} name  name with the cookie
 | 
			
		||||
//*  @param {String} value  value with the cookie
 | 
			
		||||
//*  @return 
 | 
			
		||||
//*  @author Darren Chen
 | 
			
		||||
//*  @date   2018/07/24
 | 
			
		||||
//*/
 | 
			
		||||
//function fnCreateCookie(name, value) {
 | 
			
		||||
//    let expires = new Date();
 | 
			
		||||
//    //有效時間保存 2 天 2*24*60*60*1000
 | 
			
		||||
//    expires.setTime(expires.getTime() + 172800000);
 | 
			
		||||
//    document.cookie = name + "=" + escape(value) + ";expires=" + expires.toGMTString();
 | 
			
		||||
//}
 | 
			
		||||
///* @deprecated since version 0.1 
 | 
			
		||||
//*  @description Get the cookie value by cookie name
 | 
			
		||||
//*  @param {String} name  name with the cookie
 | 
			
		||||
//*  @return 
 | 
			
		||||
//*  @author Darren Chen
 | 
			
		||||
//*  @date   2018/07/24
 | 
			
		||||
//*/
 | 
			
		||||
//function fnGetCookie(name) {
 | 
			
		||||
//    let arg = escape(name) + "=";
 | 
			
		||||
//    let nameLen = arg.length;
 | 
			
		||||
//    let cookieLen = document.cookie.length;
 | 
			
		||||
//    let i = 0;
 | 
			
		||||
//    while (i < cookieLen) {
 | 
			
		||||
//        let j = i + nameLen;
 | 
			
		||||
//        if (document.cookie.substring(i, j) === arg) return getCookieValueByIndex(j);
 | 
			
		||||
//        i = document.cookie.indexOf(" ", i) + 1;
 | 
			
		||||
//        if (i === 0) break;
 | 
			
		||||
//    }
 | 
			
		||||
//    return null;
 | 
			
		||||
//}
 | 
			
		||||
///* @deprecated since version 0.1 
 | 
			
		||||
//*  @description Get the cookie value by index
 | 
			
		||||
//*  @param {Number} index  name with the cookie
 | 
			
		||||
//*  @return 
 | 
			
		||||
//*  @author Darren Chen
 | 
			
		||||
//*  @date   2018/07/24
 | 
			
		||||
//*/
 | 
			
		||||
//function fnGetCookieValueByIndex(startIndex) {
 | 
			
		||||
//    let endIndex = document.cookie.indexOf(";", startIndex);
 | 
			
		||||
//    if (endIndex === -1) endIndex = document.cookie.length;
 | 
			
		||||
//    return unescape(document.cookie.substring(startIndex, endIndex));
 | 
			
		||||
//}
 | 
			
		||||
///*
 | 
			
		||||
//* @deprecated since version 0.1
 | 
			
		||||
//* @description 取得隨機值
 | 
			
		||||
//* @param {Number} min 最小值
 | 
			
		||||
//* @param {Number} max 最大值
 | 
			
		||||
//* @returns {Number} 
 | 
			
		||||
//*/
 | 
			
		||||
//function fnGetRandom(min, max) {
 | 
			
		||||
//    return Math.floor(Math.random() * max) + min;
 | 
			
		||||
//}
 | 
			
		||||
///*
 | 
			
		||||
// * @deprecated since version 0.1
 | 
			
		||||
// * @description 取得現在時間(yyyy-MM-dd)
 | 
			
		||||
// * @param {Boolean} isTwYear it`s Taiwan year?
 | 
			
		||||
// * @returns {String} 
 | 
			
		||||
// */
 | 
			
		||||
//function fnGetNow(isTwYear = false) {
 | 
			
		||||
//    let d = new Date();
 | 
			
		||||
//    let year = isTwYear ? d.getFullYear() - 1911 : d.getFullYear();
 | 
			
		||||
//    let month = d.getMonth() + 1;
 | 
			
		||||
//    let day = d.getDate();
 | 
			
		||||
 | 
			
		||||
//    let now = year + '-' +
 | 
			
		||||
//        (month < 10 ? '0' : '') + month + '-' +
 | 
			
		||||
//        (day < 10 ? '0' : '') + day;
 | 
			
		||||
 | 
			
		||||
//    return now;
 | 
			
		||||
//}
 | 
			
		||||
///*
 | 
			
		||||
// * @deprecated since version 0.1
 | 
			
		||||
// * @description 取得日期時間(2020/02/02 PM 18:05:25)
 | 
			
		||||
// * @param {Boolean} isTwYear it`s Taiwan year?
 | 
			
		||||
// * @param {String} dateInterval 最小值
 | 
			
		||||
// * @param {Boolean} isPadZero 最大值
 | 
			
		||||
// * @param {Number} timeTagType 時間前戳標記 1:AM/PM  2:上午/下午
 | 
			
		||||
// * @returns {String} 
 | 
			
		||||
// */
 | 
			
		||||
//function fnShowDateTimeNow(isTwYear = false, dateInterval = '/', isPadZero = true, timeTagType = 1) {
 | 
			
		||||
//    let now = new Date();
 | 
			
		||||
//    let years = isTwYear ? now.getFullYear() - 1911 : now.getFullYear();
 | 
			
		||||
//    let months = now.getMonth();
 | 
			
		||||
//    let days = now.getDay();
 | 
			
		||||
//    let hours = now.getHours();
 | 
			
		||||
//    let minutes = now.getMinutes();
 | 
			
		||||
//    let seconds = now.getSeconds();
 | 
			
		||||
 | 
			
		||||
//    let dateValue = years;
 | 
			
		||||
//    let timeValue = ((hours >= 12) ? "下午 " : "上午 ");
 | 
			
		||||
//    if (timeTagType === 2) timeValue = ((hours >= 12) ? "AM " : "PM ");
 | 
			
		||||
//    if (isPadZero) {
 | 
			
		||||
//        dateValue += (dateInterval + ((months < 10) ? "0" : "") + months);
 | 
			
		||||
//        dateValue += (dateInterval + ((days < 10) ? "0" : "") + days);
 | 
			
		||||
//        timeValue += ((hours > 12) ? "0" + (hours - 12) : hours);
 | 
			
		||||
//        timeValue += ((minutes < 10) ? ":0" : ":") + minutes;
 | 
			
		||||
//        timeValue += ((seconds < 10) ? ":0" : ":") + seconds;
 | 
			
		||||
//    }
 | 
			
		||||
//    else {
 | 
			
		||||
//        dateValue += (dateInterval + months);
 | 
			
		||||
//        dateValue += (dateInterval + days);
 | 
			
		||||
//        timeValue += ((hours > 12) ? hours - 12 : hours);
 | 
			
		||||
//        timeValue += minutes;
 | 
			
		||||
//        timeValue += seconds;
 | 
			
		||||
//    }
 | 
			
		||||
//    return dateValue + " " + timeValue;
 | 
			
		||||
//}
 | 
			
		||||
///*
 | 
			
		||||
// * @deprecated since version 0.1
 | 
			
		||||
// * @description 取得日期時間(2020/02/02 18:05:25)
 | 
			
		||||
// * @param {Boolean} isTwYear it`s Taiwan year?
 | 
			
		||||
// * @param {String} dateInterval 日期間隔字元
 | 
			
		||||
// * @param {Boolean} isPadZero   是否補0
 | 
			
		||||
// * @returns {string} 回傳時間字串
 | 
			
		||||
// */
 | 
			
		||||
//function fnGetDateTimeNow(isTwYear = false, dateInterval = '/', isPadZero = true) {
 | 
			
		||||
//    let today = new Date();
 | 
			
		||||
//    let year = isTwYear ? today.getFullYear() - 1911 : today.getFullYear();
 | 
			
		||||
//    let currentDateTime =
 | 
			
		||||
//        year + dateInterval + ((isPadZero && today.getMonth() + 1 < 10) ? '0' : '') +
 | 
			
		||||
//        (today.getMonth() + 1) + dateInterval + ((isPadZero && today.getDate() < 10) ? '0' : '') +
 | 
			
		||||
//        today.getDate() + ' ' + ((isPadZero && today.getHours() < 10) ? '0' : '') +
 | 
			
		||||
//        today.getHours() + ':' + ((isPadZero && today.getMinutes() < 10) ? '0' : '') +
 | 
			
		||||
//        today.getMinutes();
 | 
			
		||||
//    return currentDateTime;
 | 
			
		||||
//}
 | 
			
		||||
///*
 | 
			
		||||
// * @deprecated since version 0.1
 | 
			
		||||
// * @description 取得加減的日期時間(2020/02/02 18:05:25)
 | 
			
		||||
// * @param {Boolean} isTwYear it`s Taiwan year?
 | 
			
		||||
// * @param {String} dateInterval 日期間隔字元
 | 
			
		||||
// * @param {Boolean} isPadZero   是否補0
 | 
			
		||||
// * @returns {string} 回傳時間字串
 | 
			
		||||
// */
 | 
			
		||||
//function fnGetDate(isTwYear = false, dateInterval = '/', addYears = 0, addMonths = 0, addDays = 0, isPadZero = true) {
 | 
			
		||||
//    let today = new Date();
 | 
			
		||||
//    let year = isTwYear ? today.getFullYear() - 1911 : today.getFullYear();
 | 
			
		||||
//    if (addYears > year || addMonths > today.getMonth() || addDays > today.getDate()) {
 | 
			
		||||
//        return false;
 | 
			
		||||
//    }
 | 
			
		||||
//    let date =
 | 
			
		||||
//        (year + addYears) + dateInterval + ((isPadZero && today.getMonth() + addMonths + 1 < 10) ? '0' : '') +
 | 
			
		||||
//        (today.getMonth() + addMonths + 1) + dateInterval + ((isPadZero && today.getDate() + addDays < 10) ? '0' : '') +
 | 
			
		||||
//        (today.getDate() + addDays);
 | 
			
		||||
//    return date;
 | 
			
		||||
//}
 | 
			
		||||
///*
 | 
			
		||||
// * @deprecated since version 0.1
 | 
			
		||||
// * @description 取得禮拜/週幾(禮拜五)
 | 
			
		||||
// * @param {String} dayPreString 前置詞 (禮拜/週/周)
 | 
			
		||||
// * @returns {string} 回傳時間字串
 | 
			
		||||
// */
 | 
			
		||||
//function fnGetDay(dayPreString = "") {
 | 
			
		||||
//    let day = "";
 | 
			
		||||
//    let day_list = ['日', '一', '二', '三', '四', '五', '六'];
 | 
			
		||||
 | 
			
		||||
//    let today = new Date();
 | 
			
		||||
//    let dayGet = today.getDay(); // or "new Date().getDay()";
 | 
			
		||||
//    if (dayPreString === "") {
 | 
			
		||||
//        day = "(" + day_list[dayGet] + ")";
 | 
			
		||||
//    } else {
 | 
			
		||||
//        day = dayPreString + day_list[dayGet];
 | 
			
		||||
//    }
 | 
			
		||||
//    return day;
 | 
			
		||||
//}
 | 
			
		||||
///* @deprecated since version 0.1
 | 
			
		||||
//*  @description Convrt Int To Float
 | 
			
		||||
//*  @param {String} number ori number
 | 
			
		||||
//*  @param {String} keepNum keep number after .
 | 
			
		||||
//*  @return {String}
 | 
			
		||||
//*  @author Darren Chen
 | 
			
		||||
//*  @date   2019/12/31
 | 
			
		||||
//*/
 | 
			
		||||
//function fnConvrtIntToFloat(number, keepNum) {
 | 
			
		||||
//    let zeroNumber = fnPaddingRight("1", keepNum + 1, "0");
 | 
			
		||||
//    zeroNumber = parseInt(zeroNumber);
 | 
			
		||||
//    return Math.round(parseFloat(number) * zeroNumber) / zeroNumber;
 | 
			
		||||
//}
 | 
			
		||||
///* @deprecated since version 0.1
 | 
			
		||||
//*  @description The string Padding Left char
 | 
			
		||||
//*  @param {String} str ori string
 | 
			
		||||
//*  @param {Number} lenght will get string`s lenght
 | 
			
		||||
//*  @param {String} add char
 | 
			
		||||
//*  @return {String}
 | 
			
		||||
//*  @author Darren Chen
 | 
			
		||||
//*  @date   2019/12/31
 | 
			
		||||
//*/
 | 
			
		||||
//function fnPaddingLeft(str, lenght, char) {
 | 
			
		||||
//    if (str.length >= lenght)
 | 
			
		||||
//        return str;
 | 
			
		||||
//    else
 | 
			
		||||
//        return fnPaddingLeft(char + str, lenght);
 | 
			
		||||
//}
 | 
			
		||||
///* @deprecated since version 0.1
 | 
			
		||||
//*  @description The string Padding Right char
 | 
			
		||||
//*  @param {String} str ori string
 | 
			
		||||
//*  @param {Number} lenght will get string`s lenght
 | 
			
		||||
//*  @param {String} add char 
 | 
			
		||||
//*  @return {String}
 | 
			
		||||
//*  @author Darren Chen
 | 
			
		||||
//*  @date   2019/12/31
 | 
			
		||||
//*/
 | 
			
		||||
//function fnPaddingRight(str, lenght, char) {
 | 
			
		||||
//    if (str.length >= lenght)
 | 
			
		||||
//        return str;
 | 
			
		||||
//    else
 | 
			
		||||
//        return fnPaddingRight(str + char, lenght);
 | 
			
		||||
//}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user