webxoss-client/Dialog.js

455 lines
12 KiB
JavaScript
Raw Permalink Normal View History

2016-10-23 07:28:51 +02:00
'use strict';
function Dialog (game) {
this.game = game;
this.searcher = new Searcher();
this.warpDiv = this.newElement('div');
this.dialogDiv = this.newElement('div');
this.titleDiv = this.newElement('div');
this.closeIcon = this.newElement('div');
this.bodyDiv = this.newElement('div');
this.footerDiv = this.newElement('div');
this.footSpan = this.newElement('span');
this.okBtn = this.newElement('button');
this.cancelBtn = this.newElement('button');
this.okBtn.textContent = Localize('common','OK');
this.cancelBtn.textContent = Localize('common','CANCEL');
this.closeIcon.onclick = this.close.bind(this);
this.warpDiv.classList.add('warp');
this.dialogDiv.classList.add('dialog');
this.titleDiv.classList.add('title');
this.closeIcon.classList.add('closeIcon');
this.bodyDiv.classList.add('body');
this.footerDiv.classList.add('footer');
this.okBtn.classList.add('okBtn');
this.cancelBtn.classList.add('cancelBtn');
this.warpDiv.appendChild(this.dialogDiv);
this.dialogDiv.appendChild(this.closeIcon);
this.dialogDiv.appendChild(this.titleDiv);
this.dialogDiv.appendChild(this.bodyDiv);
this.dialogDiv.appendChild(this.footerDiv);
this.footerDiv.appendChild(this.footSpan);
this.footerDiv.appendChild(this.okBtn);
this.footerDiv.appendChild(this.cancelBtn);
this.warpDiv.style.display = 'none';
game.stage.canvas.parentElement.appendChild(this.warpDiv);
}
Dialog.prototype.newElement = function (tag) {
return document.createElement(tag);
};
Dialog.prototype.newCardImg = function (pid) {
var img = this.newElement('img');
img.src = this.game.imageManager.getUrlByPid(pid);
return img;
};
Dialog.prototype.mouseover = function (el,pid) {
el.onmouseover = this.game.cardDetail.show.bind(this.game.cardDetail,pid);
};
Dialog.prototype.center = function (element) {
var parent = element.parentElement;
element.style.top = '0';
element.style.left = '0';
element.style.top = (parent.offsetHeight - element.offsetHeight)/2 + 'px';
element.style.left = (parent.offsetWidth - element.offsetWidth)/2 + 'px';
};
Dialog.prototype.pop = function (title,body,foot,canClose,callback,callbackCancel) {
var dialog = this;
// 构筑DOM
this.titleDiv.textContent = title;
this.footSpan.innerHTML = '';
if (foot) this.footSpan.appendChild(foot);
this.bodyDiv.innerHTML = '';
this.bodyDiv.style.width = '';
this.bodyDiv.appendChild(body);
this.closeIcon.style.display = canClose? '' : 'none';
if (!callback) {
this.okBtn.onclick = null;
this.footerDiv.style.display = 'none';
} else {
this.okBtn.onclick = function (event) {
dialog.close();
callback();
};
// this.okBtn.disabled = false;
this.footerDiv.style.display = '';
}
if (!callbackCancel) {
this.cancelBtn.onclick = null;
this.cancelBtn.style.display = 'none';
} else {
this.cancelBtn.onclick = function (event) {
dialog.close();
callbackCancel();
};
// this.cancelBtn.disabled = false;
this.cancelBtn.style.display = '';
}
// 渲染,但完全透明,用于计算元素尺寸和位置.
this.warpDiv.style.opacity = '0';
this.warpDiv.style.display = '';
// 加上滚动条宽度
// this.bodyDiv.style.width = 2*this.bodyDiv.offsetWidth - this.bodyDiv.clientWidth + 'px';
// 居中
this.center(this.dialogDiv);
// 显示
this.warpDiv.style.opacity = '1';
};
Dialog.prototype.close = function () {
this.okBtn.disabled = false;
this.warpDiv.style.display = 'none';
};
Dialog.prototype.showText = function (title,text,callback) {
var body = document.createTextNode(text);
this.pop(title,body,null,false,callback);
};
Dialog.prototype.confirm = function (title,text,callback) {
var body = document.createTextNode(text);
this.pop(title,body,null,false,callback.bind(null,true),callback.bind(null,false));
};
// 从多个文本选项选择一个.
Dialog.prototype.selectText = function (title,options,canClose,callback) {
var dialog = this;
var body = this.newElement('div');
options.forEach(function (option,idx) {
var opt = this.newElement('div');
opt.classList.add('option');
opt.textContent = option;
body.appendChild(opt);
opt.onclick = function (event) {
dialog.close();
callback(idx);
}
},this);
this.pop(title,body,null,canClose,null);
};
Dialog.prototype.selectNumber = function (title,min,max,defaultValue,canClose,callback) {
var dialog = this;
var body = this.newElement('div');
var sel = this.newElement('select');
for (var i = min; i <= max; i++) {
var opt = this.newElement('option');
opt.value = i;
opt.textContent = i;
sel.appendChild(opt);
}
sel.value = defaultValue;
body.appendChild(sel);
this.pop(title,body,null,canClose,function () {
callback(sel.value);
});
};
Dialog.prototype.showCards = function (title,cards,callback) {
var body = this.newElement('div');
if (!cards.length) {
body.textContent = Localize('common','NO_CARDS');
} else {
cards.forEach(function (card) {
var crd = this.newElement('div');
var img = this.newCardImg(card.pid);
crd.appendChild(img);
crd.classList.add('card');
this.mouseover(crd,card.pid);
body.appendChild(crd);
},this);
}
this.pop(title,body,null,false,callback);
};
Dialog.prototype.selectCardId = function (title,callback) {
var dialog = this;
var searcher = this.searcher;
var body = this.newElement('div');
body.style.textAlign = 'center';
var searchBar = this.newElement('input');
searchBar.setAttribute('placeholder','Search...');
searchBar.type = 'text';
searchBar.style.textAlign = 'center';
searchBar.style.width = '90%';
var container = this.newElement('div');
container.style.maxHeight = '450px';
container.style['overflow-y'] = 'auto';
container.style.textAlign = 'left';
var elShowMore = this.newElement('div');
elShowMore.textContent = 'Show More...';
elShowMore.style.color = 'blue';
elShowMore.style.cursor = 'pointer';
elShowMore.style.margin = '1em 0';
body.appendChild(searchBar);
body.appendChild(container);
body.appendChild(elShowMore);
var results = [];
var RESULTS_LENGTH = 9;
var _shown = 0;
elShowMore.onclick = showMore;
searchBar.onchange = searchBar.onkeyup = search;
function search () {
var q = searchBar.value;
results = searcher.search(q);
showResults();
};
search();
function showResults () {
_shown = 0;
container.innerHTML = '';
showMore();
}
function showMore () {
for (var i = 0; i < RESULTS_LENGTH; i++) {
var idx = _shown;
if (idx >= results.length) break;
var pid = results[idx].pid;
var opt = dialog.newElement('div');
var img = dialog.newCardImg(pid);
opt.appendChild(img);
opt.classList.add('card');
dialog.mouseover(opt,pid);
opt.onclick = function (pid) {
dialog.close();
callback(pid);
}.bind(null,pid);
container.appendChild(opt);
_shown++;
}
// if (_shown < results.length) {
// show(elShowMore);
// } else {
// hide(elShowMore);
// }
}
this.pop(title,body,null,false,null);
// 固定宽度
body.style.minWidth = body.offsetWidth + 'px';
searchBar.focus();
};
// 选择一张.
Dialog.prototype.selectCard = function (title,cards,canClose,callback) {
var dialog = this;
var body = this.newElement('div');
cards.forEach(function (card,idx) {
var opt = this.newElement('div');
var img = this.newCardImg(card.pid);
opt.appendChild(img);
opt.classList.add('card');
this.mouseover(opt,card.pid);
opt.onclick = function (event) {
dialog.close();
callback(idx);
}
body.appendChild(opt);
},this);
this.pop(title,body,null,canClose,null);
};
Dialog.prototype.selectCardAdvanced = function (title,cards,texts,canClose,careOrder,onchanged,callback,callbackCancel) {
if (!texts) texts = [];
var dialog = this;
var selectedIndexes = [];
var datas = [];
var body = this.newElement('div');
cards.forEach(function (card,idx) {
var opt = this.newElement('div');
var img = this.newCardImg(card.pid);
var txt = this.newElement('div');
txt.textContent = texts[idx] || '';
var msk = this.newElement('div');
var num = this.newElement('div');
opt.appendChild(img);
opt.appendChild(txt);
opt.appendChild(msk);
opt.appendChild(num);
opt.classList.add('card');
txt.classList.add('txt');
msk.classList.add('msk');
num.classList.add('num');
this.mouseover(opt,card.pid);
var data = {
opt: opt,
txt: txt,
msk: msk,
num: num,
};
datas[idx] = data;
opt.onclick = function (event) {
if (!opt.classList.contains('selected') && opt.classList.contains('disabled')) return;
if (opt.classList.contains('selected')) {
removeFromArr(idx,selectedIndexes);
} else {
selectedIndexes.push(idx);
}
opt.classList.toggle('selected');
handleSelectChanged();
};
body.appendChild(opt);
},this);
handleSelectChanged();
dialog.pop(title,body,null,canClose,callback.bind(null,selectedIndexes),callbackCancel);
datas.forEach(function (data) {
this.center(data.txt);
},this);
function handleSelectChanged () {
datas.forEach(function (data,idx) {
data.opt.classList.remove('disabled');
},this);
var ok = onchanged(selectedIndexes,disable);
dialog.okBtn.disabled = !ok;
if (careOrder) {
datas.forEach(function (data,idx) {
var order = selectedIndexes.indexOf(idx) + 1;
data.num.textContent = order || '';
dialog.center(data.num);
},this);
}
}
function disable (idx) {
datas[idx].opt.classList.add('disabled');
}
};
// 选择若干张.
Dialog.prototype.selectSomeCards = function (title,cards,arg,callback) {
var min = arg.min || 0;
// var max = arg.max || cards.length;
var max = arg.max;
if (!max) {
max = arg.targets? arg.targets.length : cards.length;
}
var texts = arg.texts;
var canClose = arg.canClose;
var careOrder = arg.careOrder;
var targets = arg.targets;
var callbackCancel;
if (min) {
callbackCancel = null;
} else {
callbackCancel = callback.bind(null,[]);
}
this.selectCardAdvanced(title,cards,texts,canClose,careOrder,function (selectedIndexes,disable) {
if (targets && targets.length) {
cards.forEach(function (card,idx) {
if (!inArr(card,targets)) disable(idx);
},this);
}
var len = selectedIndexes.length;
if (len >= max) {
cards.forEach(function (card,idx) {
disable(idx);
},this);
return true;
}
return len && (len >= min);
},function (selectedIndexes) {
if (targets && targets.length && (targets.length !== cards.length)) {
selectedIndexes = selectedIndexes.map(function (idx) {
return targets.indexOf(cards[idx]);
});
}
callback(selectedIndexes);
},callbackCancel);
};
2017-08-05 17:15:32 +02:00
Dialog.prototype.selectEner = function (title,cards,integers,cost,callback,onCancel) {
function checkRequirements(items, requirements) {
var n = requirements.length
var len = 1 << n
var arr = (typeof Uint8Array === 'undefined') ? new Array(len) : new Uint8Array(len)
// 第 i 条不等式。
// 假设 n == 4即有 4 种元需求:
// i 为从 0000 到 1111从右到左分别称为第 1,2,3,4 位
// 当 i == 0110 时,代表不等式左边为第 2、3 个集合的并集
for (var i = 0; i < len; i++) {
var filters = []
for (var j = 0; j < n; j++) {
if (i & (1 << j)) {
filters.push(requirements[j].filter)
// 不等式的右边(先把需求数加上去,满足的时候减 1减至 0 则满足该不等式)
arr[i] += requirements[j].count
}
2016-10-23 07:28:51 +02:00
}
2017-08-05 17:15:32 +02:00
// 遍历能量区,满足条件的减 1
for (var j = 0; j < items.length; j++) {
var item = items[j]
if (filters.some(function (filter) {
return filter(item)
})) {
// 减至 0该不等式成立
if (!--arr[i]) break
2016-10-23 07:28:51 +02:00
}
}
2017-08-05 17:15:32 +02:00
if (arr[i]) return false
}
return true
}
2016-10-23 07:28:51 +02:00
2017-08-05 17:15:32 +02:00
var total = 0;
var requirements = cost.requirements.map(function (requirement) {
total += requirement.count;
return {
count: requirement.count,
mask: requirement.mask,
filter: function (int) {
2017-08-23 16:17:04 +02:00
return !requirement.mask || (int & requirement.mask);
2017-08-05 17:15:32 +02:00
},
};
});
function onSelectChange (selectedIndexes,disable) {
var selectedIntegers = selectedIndexes.map(function (index) {
return integers[index]
});
var ok = (selectedIndexes.length === total) && checkRequirements(selectedIntegers,requirements);
if (ok) {
integers.forEach(function (_,index) {
disable(index);
});
}
return ok;
};
2016-10-23 07:28:51 +02:00
2017-08-05 17:15:32 +02:00
var texts = cards.map(function (card) {
return card.sid === cost.source ? 'WARN' : '';
},this);
this.selectCardAdvanced(title,cards,texts,false,false,onSelectChange,callback,onCancel);
2016-10-23 07:28:51 +02:00
};