mirror of
https://github.com/webxoss/webxoss-client.git
synced 2024-11-20 05:49:55 +01:00
455 lines
No EOL
12 KiB
JavaScript
455 lines
No EOL
12 KiB
JavaScript
'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);
|
||
};
|
||
|
||
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
|
||
}
|
||
}
|
||
// 遍历能量区,满足条件的减 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
|
||
}
|
||
}
|
||
if (arr[i]) return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
var total = 0;
|
||
var requirements = cost.requirements.map(function (requirement) {
|
||
total += requirement.count;
|
||
return {
|
||
count: requirement.count,
|
||
mask: requirement.mask,
|
||
filter: function (int) {
|
||
return !requirement.mask || (int & requirement.mask);
|
||
},
|
||
};
|
||
});
|
||
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;
|
||
};
|
||
|
||
var texts = cards.map(function (card) {
|
||
return card.sid === cost.source ? 'WARN' : '';
|
||
},this);
|
||
this.selectCardAdvanced(title,cards,texts,false,false,onSelectChange,callback,onCancel);
|
||
}; |