289 lines
8.1 KiB
JavaScript
289 lines
8.1 KiB
JavaScript
/**
|
|
* YourTeam Notice 訊息彈出小視窗 (on base bootstrap v4 toast)
|
|
*
|
|
* 使用方式:
|
|
* <div id="noticeBlock" style="position: fixed; top: 70px; right: 0px; padding: 20px; transition: 0.2s; z-index: 50000; height:100%; ">
|
|
|
|
</div>
|
|
*
|
|
* <script>
|
|
* $("#noticeBlock").YTNotice("add", { option... });
|
|
* </script>
|
|
* */
|
|
|
|
|
|
class YTNotice {
|
|
constructor(option = {}) {
|
|
this.id = option.id ?? null;
|
|
this.title = option.title ?? "";
|
|
this.content = option.content ?? "";
|
|
this.type = option.type ?? null;
|
|
this.hasCloseBtn = option.hasCloseBtn ?? true;
|
|
this.keepTime = 0;
|
|
this.timeText = option.timeText ?? "剛剛";
|
|
this.iconClass = option.iconClass ?? "";
|
|
this.container = "";
|
|
this.eIcon = "";
|
|
this.eTitle = "";
|
|
this.eTimeAgo = "";
|
|
this.eCloseBtn = "";
|
|
this.eContent = "";
|
|
this.init();
|
|
}
|
|
|
|
init = function () {
|
|
this.setNoticeId();
|
|
this.setIconClass();
|
|
this.setContainer();
|
|
|
|
if (this.title) {
|
|
this.setTitle(this.title);
|
|
}
|
|
if (this.content) {
|
|
this.setContent(this.content);
|
|
}
|
|
if (this.timeText) {
|
|
this.setTimeAgo(this.timeText);
|
|
}
|
|
|
|
$(this.container)[0]._ytNotice = this;
|
|
}
|
|
|
|
setNoticeId = function () {
|
|
if (this.id == null) {
|
|
this.id = YT.Math.Random(10000000, 99999999);
|
|
}
|
|
}
|
|
|
|
setContainer = function () {
|
|
this.container = $(`<div class="toast fade" role="alert" aria-live="assertive" aria-atomic="true" data-autohide="false">
|
|
<div class="toast-header">
|
|
|
|
</div>
|
|
<div class="toast-body">
|
|
|
|
</div>
|
|
</div>`);
|
|
|
|
this.setIcon(this.iconClass);
|
|
this.eTitle = $(`<strong class="mr-auto notice-title"></strong>`);
|
|
this.eTimeAgo = $(`<small class="text-muted notice-ago ml-4"></small>`);
|
|
this.eCloseBtn = $(`<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close"><span aria-hidden="true">×</span></button>`);
|
|
this.eContent = $(`<div class="notice-content"></div>`);
|
|
if (this.type != null) {
|
|
this.container.find(".toast-header").append(this.eIcon);
|
|
this.eIcon.addClass("text-" + this.type);
|
|
}
|
|
this.container.find(".toast-header").append(this.eTitle);
|
|
this.container.find(".toast-header").append(this.eTimeAgo);
|
|
if (this.hasCloseBtn) {
|
|
this.container.find(".toast-header").append(this.eCloseBtn);
|
|
}
|
|
this.container.find(".toast-body").append(this.eContent);
|
|
}
|
|
|
|
setIconClass = function () {
|
|
if (this.type == "success") {
|
|
this.iconClass = `fas fa-check`;
|
|
} else if (this.type == "warning") {
|
|
this.iconClass = `fas fa-exclamation-triangle`;
|
|
} else if (this.type == "danger") {
|
|
this.iconClass = `fas fa-times`;
|
|
}
|
|
}
|
|
|
|
setIcon = function (iconClass) {
|
|
this.eIcon = $(`<i class="mr-2"></i>`);
|
|
this.eIcon.addClass(iconClass);
|
|
}
|
|
|
|
setTitle = function (title = "") {
|
|
this.eTitle.html(title);
|
|
}
|
|
|
|
setTimeAgo = function (timeAgo = "") {
|
|
this.eTimeAgo.text(timeAgo);
|
|
}
|
|
|
|
setContent = function (content = "") {
|
|
this.eContent.html(content);
|
|
}
|
|
|
|
}
|
|
|
|
class YTNoticeBlock {
|
|
constructor(option = {}) {
|
|
this.element = option.element;
|
|
this.offsetBottom = 200;
|
|
this.noticeArr = [];
|
|
this.eScroll = $(`<div class="yt-notice-block-scrollbody"></div>`);
|
|
this.noticeContainer = "";
|
|
this.scrollY = option.scrollY ?? true;
|
|
|
|
this.init();
|
|
}
|
|
|
|
init = function () {
|
|
this.drawInitScroll();
|
|
this.drawElement();
|
|
|
|
if (this.scrollY) {
|
|
this.noticeContainer = this.eScroll;
|
|
} else {
|
|
this.noticeContainer = this.element;
|
|
}
|
|
|
|
this.updEleObj();
|
|
}
|
|
|
|
drawInitScroll = function () {
|
|
if (this.scrollY) {
|
|
$(this.eScroll).css("height", "100%");
|
|
$(this.eScroll).css("overflow-y", "auto");
|
|
$(this.element).append(this.eScroll);
|
|
}
|
|
}
|
|
|
|
drawElement = function () {
|
|
$(this.element).addClass("yt-notice-block");
|
|
}
|
|
|
|
showOneNotice = function (obj = null,append = "prepend") {
|
|
if (obj) {
|
|
if (append == "prepend") {
|
|
$(this.noticeContainer).prepend(obj.container);
|
|
} else if (append == "append") {
|
|
$(this.noticeContainer).append(obj.container);
|
|
}
|
|
$(obj.container).toast("show");
|
|
}
|
|
}
|
|
|
|
hideOneNotice = function (obj = null) {
|
|
if (obj) {
|
|
let toast = "";
|
|
if (obj.is("div.toast")) {
|
|
toast = obj;
|
|
} else {
|
|
toast = obj.container;
|
|
}
|
|
|
|
$(toast).toast('dispose');
|
|
|
|
setTimeout(() => {
|
|
$(toast).remove();
|
|
|
|
let tarNoticeId = $(toast)[0]._ytNotice.id
|
|
let tarNoticeIdx = this.noticeArr.findIndex(x => x.obj.id == tarNoticeId);
|
|
if (tarNoticeIdx != -1) {
|
|
this.noticeArr[tarNoticeIdx].canShow = false;
|
|
}
|
|
|
|
this.showNotices();
|
|
}, 100)
|
|
|
|
|
|
}
|
|
this.updEleObj();
|
|
}
|
|
|
|
checkCanShow = function (notice = null) {
|
|
let lastNoticeOffset = $(this.noticeContainer).find(".toast").last().offset();
|
|
if ($(this.noticeContainer).find(".toast").last().length == 0) {
|
|
return true;
|
|
}
|
|
|
|
if ($(notice.obj.container).is(":visible")) {
|
|
return false;
|
|
}
|
|
|
|
if (!notice.canShow) {
|
|
return false;
|
|
}
|
|
|
|
if (lastNoticeOffset.top + this.offsetBottom > $(window).height()) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
showNotices = function () {
|
|
$.each(this.noticeArr, (idx, notice) => {
|
|
if (this.checkCanShow(notice)) {
|
|
this.showOneNotice(notice.obj,"append");
|
|
}
|
|
})
|
|
}
|
|
|
|
pushNotice = function (option = {}) {
|
|
if (this.noticeArr.findIndex(x => x.obj.id == option.id) == -1) {
|
|
let notice = new YTNotice(option);
|
|
this.noticeArr.push({ obj: notice, time: (new Date()).getTime(), canShow: true });
|
|
this.setEvent(notice);
|
|
}
|
|
this.updEleObj();
|
|
}
|
|
|
|
updEleObj = function () {
|
|
$(this.element)[0]._noticeBlock = this;
|
|
}
|
|
|
|
setEvent = function (notice) {
|
|
let _this = this;
|
|
$(notice.container).on("hidden.bs.toast", function () {
|
|
setTimeout(() => {
|
|
$(notice.container).remove();
|
|
|
|
let tarNoticeId = $(notice.container)[0]._ytNotice.id
|
|
let tarNoticeIdx = _this.noticeArr.findIndex(x => x.obj.id == tarNoticeId);
|
|
if (tarNoticeIdx != -1) {
|
|
_this.noticeArr[tarNoticeIdx].canShow = false;
|
|
}
|
|
_this.showNotices();
|
|
}, 100)
|
|
})
|
|
}
|
|
|
|
}
|
|
|
|
$.fn.YTNotice = function (method = "init", ...args) {
|
|
let _this = this;
|
|
|
|
if (method == "init") {
|
|
initNoticeBlock();
|
|
}
|
|
|
|
let noticeBlock = _this[0]._noticeBlock;
|
|
if (!noticeBlock) {
|
|
initNoticeBlock();
|
|
noticeBlock = _this[0]._noticeBlock;
|
|
}
|
|
|
|
if (method == "add") {
|
|
|
|
noticeBlock.pushNotice(args[0] ?? {});
|
|
noticeBlock.showNotices();
|
|
|
|
} else if (method == "add_many") {
|
|
|
|
args[0].forEach((arg, idx) => {
|
|
noticeBlock.pushNotice(arg);
|
|
})
|
|
|
|
noticeBlock.showNotices();
|
|
} else if (method == "hide") {
|
|
if (args.length == 0) {
|
|
noticeBlock = $(_this).parents(".yt-notice-block")[0]._noticeBlock;
|
|
noticeBlock.hideOneNotice(this);
|
|
}
|
|
}
|
|
|
|
function initNoticeBlock() {
|
|
let option = {};
|
|
option.element = _this;
|
|
let noticeBlock = new YTNoticeBlock(option);
|
|
}
|
|
|
|
}
|