Update Reader.

This commit is contained in:
Bruce
2026-04-02 11:33:57 +08:00
parent 880a834296
commit f9f4db3f6c
41 changed files with 3921 additions and 663 deletions

View File

@@ -39,6 +39,7 @@ var MBRET = {
Object.freeze(MBFLAGS);
Object.freeze(MBRET);
// ==================== 资源加载部分(保持不变) ====================
(function(global) {
try {
var storage = Bridge.External.Storage;
@@ -53,15 +54,197 @@ Object.freeze(MBRET);
} catch (e) {}
})(this);
function GetLocaleStringFromResId(resId) { try { return getPublicRes(resId); } catch (e) {} }
function GetLocaleStringFromResId(resId) {
try { return getPublicRes(resId); } catch (e) { return ""; }
}
// ==================== 全局结果存储 ====================
var msgboxResult = {};
function MessageBox(_lpText, _lpCaption, _uType, _objColor) {
var id = MessageBoxForJS(_lpText, _lpCaption, _uType, _objColor, function(valueReturn) {
getRes = valueReturn;
msgboxResult[id] = valueReturn;
function ClearAllMessageBoxResults() {
msgboxResult = {};
}
// ==================== 辅助函数 ====================
var _msgboxIdCounter = 0;
function _generateMsgBoxId() {
return "msgbox_" + new Date().getTime() + "_" + (++_msgboxIdCounter);
}
// 根据 MBFLAGS 生成命令列表(返回 { commands, defaultIndex }
function _buildCommandsFromFlags(uType) {
var commands = [];
var baseType = uType & 0xF;
var defaultIndex = 0;
var hasHelp = (uType & MBFLAGS.MB_HELP) === MBFLAGS.MB_HELP;
// 辅助添加命令
function addCommand(resId, returnValue) {
var label = GetLocaleStringFromResId(resId);
if (!label) label = "Button";
commands.push({ label: label, value: returnValue });
}
// 先处理帮助按钮(原实现中帮助按钮总是在最前面)
if (hasHelp) {
addCommand(808, MBRET.IDHELP);
}
// 根据基础类型添加按钮
switch (baseType) {
case MBFLAGS.MB_OK:
addCommand(800, MBRET.IDOK);
break;
case MBFLAGS.MB_OKCANCEL:
addCommand(800, MBRET.IDOK);
addCommand(801, MBRET.IDCANCEL);
break;
case MBFLAGS.MB_ABORTRETRYIGNORE:
addCommand(802, MBRET.IDABORT);
addCommand(803, MBRET.IDRETRY);
addCommand(804, MBRET.IDIGNORE);
break;
case MBFLAGS.MB_YESNOCANCEL:
addCommand(805, MBRET.IDYES);
addCommand(806, MBRET.IDNO);
addCommand(801, MBRET.IDCANCEL);
break;
case MBFLAGS.MB_YESNO:
addCommand(805, MBRET.IDYES);
addCommand(806, MBRET.IDNO);
break;
case MBFLAGS.MB_RETRYCANCEL:
addCommand(803, MBRET.IDRETRY);
addCommand(801, MBRET.IDCANCEL);
break;
case MBFLAGS.MB_CANCELTRYCONTINUE:
addCommand(801, MBRET.IDCANCEL);
addCommand(803, MBRET.IDRETRY);
addCommand(810, MBRET.IDCONTINUE);
break;
default:
addCommand(800, MBRET.IDOK);
break;
}
// 确定默认按钮索引(考虑帮助按钮占位)
var defFlag = uType & 0x300; // MB_DEFBUTTON1~4
var defButtonNumber = 0;
if (defFlag === MBFLAGS.MB_DEFBUTTON2) defButtonNumber = 1;
else if (defFlag === MBFLAGS.MB_DEFBUTTON3) defButtonNumber = 2;
else if (defFlag === MBFLAGS.MB_DEFBUTTON4) defButtonNumber = 3;
else defButtonNumber = 0;
// 默认索引需要加上帮助按钮的偏移
var finalDefaultIndex = (hasHelp ? 1 : 0) + defButtonNumber;
if (finalDefaultIndex >= commands.length) finalDefaultIndex = commands.length - 1;
if (finalDefaultIndex < 0) finalDefaultIndex = 0;
return { commands: commands, defaultIndex: finalDefaultIndex };
}
// 创建 ContentDialog 并应用公共属性
function _createContentDialog(title, content, bgColor, commands, defaultIndex, callback) {
var container = document.createElement("div");
document.body.appendChild(container);
var dialog = new WinJS.UI.ContentDialog(container, {
//title: typeof title === "string" ? title : "",
//content: typeof content === "string" ? content : "",
autoShow: false
});
return id;
dialog.title = title;
dialog.content = content;
// 处理标题为 HTMLElement
if (title instanceof HTMLElement) {
var titleContainer = container.querySelector(".win-contentdialog-title");
if (titleContainer) {
while (titleContainer.firstChild) titleContainer.removeChild(titleContainer.firstChild);
titleContainer.appendChild(title);
}
}
// 处理内容为 HTMLElement
if (content instanceof HTMLElement) {
var contentContainer = container.querySelector(".win-contentdialog-content");
if (contentContainer) {
while (contentContainer.firstChild) contentContainer.removeChild(contentContainer.firstChild);
contentContainer.appendChild(content);
}
}
// 背景色
if (!IsBlackLabel(bgColor)) {
dialog.backgroundColor = bgColor;
}
// 添加命令
for (var i = 0; i < commands.length; i++) {
var cmd = commands[i];
var dialogCmd = new WinJS.UI.ContentDialogCommand(cmd.label, function(evt) {
// 阻止多次点击
if (dialog._isClosing) return;
dialog._isClosing = true;
// 调用回调传递返回值
if (callback) callback(cmd.value);
// 关闭并移除对话框
dialog.hide().then(function() {
try { document.body.removeChild(container); } catch (e) {}
dialog._isClosing = false;
});
// 返回 false 会阻止关闭,但我们手动关闭,所以返回 undefined 即可
}, cmd.value.toString());
dialog.commands.push(dialogCmd);
}
// 设置默认按钮
if (defaultIndex >= 0 && defaultIndex < dialog.commands.length) {
dialog.primaryCommandIndex = defaultIndex;
}
return dialog;
}
// ==================== 核心 API 实现 ====================
// 新版 MessageBoxForJS完全基于 ContentDialog
function MessageBoxForJS(_lpText, _lpCaption, _uType, _objColor, _callback) {
var dialogId = _generateMsgBoxId();
var commandsInfo = _buildCommandsFromFlags(_uType);
var dialog = _createContentDialog(
_lpCaption,
_lpText,
_objColor,
commandsInfo.commands,
commandsInfo.defaultIndex,
function(returnValue) {
if (_callback) _callback(returnValue);
}
);
// 存储 dialog 引用以便可能的后续操作(如 GetMessageBoxResult 不需要,但保留)
if (!window._activeDialogs) window._activeDialogs = {};
window._activeDialogs[dialogId] = dialog;
dialog.element.id = dialogId;
// 显示对话框
dialog.show().then(null, function(err) { console.error("ContentDialog show error:", err); });
return dialogId;
}
// MessageBox返回 ID结果通过 GetMessageBoxResult 获取
function MessageBox(_lpText, _lpCaption, _uType, _objColor) {
var msgboxId = _generateMsgBoxId();
MessageBoxForJS(_lpText, _lpCaption, _uType, _objColor, function(valueReturn) {
msgboxResult[msgboxId] = valueReturn;
if (window._activeDialogs) delete window._activeDialogs[msgboxId];
});
return msgboxId;
}
function GetMessageBoxResult(msgboxId) {
@@ -71,201 +254,84 @@ function GetMessageBoxResult(msgboxId) {
return result;
}
function ClearAllMessageBoxResults() {
msgboxResult = null;
msgboxResult = {};
}
// 注意callback 函数无返回值,传入参数:整数型 按下的按钮值。
/*
使用示例:
MessageBoxForJS("请选择一个按钮", "", MBFLAGS.MB_OKCANCEL, "#0078d7", function(value) {
console.log("MessageBoxForJS callback value: " + value);
})
*/
function MessageBoxForJS(_lpText, _lpCaption, _uType, _objColor, _callback) {
var msgbox = document.createElement("div");
msgbox.classList.add("notice-back");
msgbox.classList.add("win-ui-dark");
var uniqueId = "msgbox_" + new Date().getTime();
msgbox.id = uniqueId;
var msgbody = document.createElement("div");
msgbody.classList.add("notice-body");
if (!IsBlackLabel(_objColor)) {
msgbody.style.backgroundColor = _objColor;
// 异步版本(返回 Promise
function messageBoxAsync(swText, swTitle, uType, swColor, pfCallback) {
if (typeof Promise === "undefined") {
console.error("Promise is not supported in this environment.");
MessageBoxForJS(swText, swTitle, uType, swColor, pfCallback);
return null;
}
msgbox.appendChild(msgbody);
var msgcontainter = document.createElement("div");
msgcontainter.style.height = "100%";
msgcontainter.style.width = "100%";
msgcontainter.style.maxHeight = "100%";
msgcontainter.style.minHeight = "0px";
msgcontainter.style.boxSizing = "border-box";
msgbody.appendChild(msgcontainter);
var msgcaption = document.createElement("div");
msgcontainter.appendChild(msgcaption);
msgcontainter.style.display = "flex";
msgcontainter.style.flexDirection = "column";
var msgcontent = document.createElement("div");
msgcontent.style.flex = "1 1 auto";
msgcontent.style.marginRight = "3px";
msgcontent.style.overflowX = "hidden";
msgcontent.style.overflowY = "auto";
msgcontent.style.minHeight = "0px";
msgcontainter.appendChild(msgcontent);
if (_lpCaption instanceof HTMLElement) {
msgcaption.appendChild(_lpCaption);
msgcaption.classList.add("notice-title");
} else {
if (!IsBlackLabel(_lpCaption)) {
var msgtitle = document.createElement("h2");
msgtitle.textContent = _lpCaption;
msgtitle.classList.add("notice-title");
msgcaption.appendChild(msgtitle);
} else {
var msgtitle = document.createElement("h2");
msgtitle.textContent = "";
msgtitle.classList.add("notice-title");
msgcaption.appendChild(msgtitle);
}
}
if (_lpText instanceof HTMLElement || _lpText instanceof HTMLDivElement || typeof _lpText !== "string") {
return new Promise(function(resolve, reject) {
try {
_lpText.classList.add("notice-text");
msgcontent.appendChild(_lpText);
} catch (e) {
if (!IsBlackLabel(_lpText)) {
var msgtext = document.createElement("p");
msgtext.textContent = _lpText;
msgtext.classList.add("notice-text");
if (IsBlackLabel(_lpCaption)) {
msgtext.style.marginTop = "0";
}
msgcontent.appendChild(msgtext);
} else {
var msgtext = document.createElement("p");
msgtext.innerText = "";
msgtext.classList.add("notice-text");
if (IsBlackLabel(_lpCaption)) {
msgtext.style.marginTop = "0";
}
msgcontent.appendChild(msgtext);
}
MessageBoxForJS(swText, swTitle, uType, swColor, function(valueReturn) {
if (pfCallback) pfCallback(valueReturn);
resolve(valueReturn);
});
} catch (ex) {
reject(ex);
}
} else {
if (!IsBlackLabel(_lpText)) {
var msgtext = document.createElement("p");
msgtext.textContent = _lpText;
msgtext.classList.add("notice-text");
if (IsBlackLabel(_lpCaption)) {
msgtext.style.marginTop = "0";
}
msgcontent.appendChild(msgtext);
} else {
var msgtext = document.createElement("p");
msgtext.innerText = "";
msgtext.classList.add("notice-text");
if (IsBlackLabel(_lpCaption)) {
msgtext.style.marginTop = "0";
}
msgcontent.appendChild(msgtext);
}
}
var msgctrls = document.createElement("div");
msgctrls.classList.add("notice-controls");
msgcontainter.appendChild(msgctrls);
var cnt = 0;
var cbFuncPress = function(valueReturn) {
getRes = valueReturn;
msgbox.style.opacity = 0;
setTimeout(function() {
document.body.removeChild(msgbox);
}, 500);
if (_callback) {
_callback(valueReturn);
}
};
var pfCreateButton = function(displayNameResId, valueReturn) {
var btn = document.createElement("button");
btn.innerHTML = GetLocaleStringFromResId(displayNameResId);
btn.classList.add("notice-btn");
btn.addEventListener("click", function() {
cbFuncPress(valueReturn);
});
msgctrls.appendChild(btn);
};
if ((_uType & MBFLAGS.MB_HELP) === MBFLAGS.MB_HELP) {
pfCreateButton(808, MBRET.IDHELP);
}
for (cnt = 0; cnt <= MBFLAGS.MB_RETRYCANCEL; cnt++) {
if ((_uType & 0xF) === cnt) {
switch (cnt) {
case MBFLAGS.MB_OK:
{
pfCreateButton(800, MBRET.IDOK);
}
break;
case MBFLAGS.MB_OKCANCEL:
{
pfCreateButton(800, MBRET.IDOK);
pfCreateButton(801, MBRET.IDCANCEL);
}
break;
case MBFLAGS.MB_ABORTRETRYIGNORE:
{
pfCreateButton(802, MBRET.IDABORT);
pfCreateButton(803, MBRET.IDRETRY);
pfCreateButton(804, MBRET.IDIGNORE);
}
break;
case MBFLAGS.MB_YESNOCANCEL:
{
pfCreateButton(805, MBRET.IDYES);
pfCreateButton(806, MBRET.IDNO);
pfCreateButton(801, MBRET.IDCANCEL);
}
break;
case MBFLAGS.MB_YESNO:
{
pfCreateButton(805, MBRET.IDYES);
pfCreateButton(806, MBRET.IDNO);
}
break;
case MBFLAGS.MB_RETRYCANCEL:
{
pfCreateButton(803, MBRET.IDRETRY);
pfCreateButton(801, MBRET.IDCANCEL);
}
break;
case MBFLAGS.MB_CANCELTRYCONTINUE:
{
pfCreateButton(801, MBRET.IDCANCEL);
pfCreateButton(803, MBRET.IDRETRY);
pfCreateButton(810, MBRET.IDCONTINUE);
}
break;
}
}
}
var btns = msgctrls.querySelectorAll("button");
var defaultBtnCnt = 0;
if ((_uType & MBFLAGS.MB_DEFBUTTON1) === MBFLAGS.MB_DEFBUTTON1) defaultBtnCnt = 0;
if ((_uType & MBFLAGS.MB_DEFBUTTON2) === MBFLAGS.MB_DEFBUTTON2) defaultBtnCnt = 1;
if ((_uType & MBFLAGS.MB_DEFBUTTON3) === MBFLAGS.MB_DEFBUTTON3) defaultBtnCnt = 2;
if ((_uType & MBFLAGS.MB_DEFBUTTON4) === MBFLAGS.MB_DEFBUTTON4) defaultBtnCnt = 3;
for (cnt = 0; cnt < btns.length; cnt++) {
if (cnt === defaultBtnCnt) {
btns[cnt].focus();
break;
}
}
document.body.appendChild(msgbox);
setTimeout(function() {
msgbox.style.opacity = 1;
}, 1);
return msgbox.id;
});
}
// MessageBoxButton 类(保持不变)
function MessageBoxButton(swDisplayName, nValueReturn) {
this.displayName = swDisplayName;
this.value = nValueReturn;
}
// 高级自定义按钮对话框
function messageBoxAdvance(swText, swCaption, aCommands, swColor, pfCallback) {
var dialogId = _generateMsgBoxId();
// 转换 aCommands 为内部格式
var commands = [];
for (var i = 0; i < aCommands.length; i++) {
var cmd = aCommands[i];
commands.push({
label: cmd.displayName,
value: cmd.value
});
}
if (commands.length === 0) {
commands.push({ label: GetLocaleStringFromResId(800) || "OK", value: MBRET.IDOK });
}
var dialog = _createContentDialog(
swCaption,
swText,
swColor,
commands,
0, // 默认第一个按钮为默认
function(returnValue) {
if (pfCallback) pfCallback(returnValue);
}
);
dialog.element.id = dialogId;
if (!window._activeDialogs) window._activeDialogs = {};
window._activeDialogs[dialogId] = dialog;
dialog.show();
return dialogId;
}
function messageBoxAdvanceAsync(swText, swCaption, aCommands, swColor) {
if (typeof Promise === "undefined") {
console.error("Promise is not supported in this environment.");
messageBoxAdvance(swText, swCaption, aCommands, swColor);
return null;
}
return new Promise(function(resolve, reject) {
try {
messageBoxAdvance(swText, swCaption, aCommands, swColor, function(valueReturn) {
resolve(valueReturn);
});
} catch (ex) {
reject(ex);
}
});
}
// ==================== MsgBoxObj 类(保持原接口,内部已适配) ====================
function MsgBoxObj() {
this.elementId = "";
this.callback = null;
@@ -274,28 +340,31 @@ function MsgBoxObj() {
this._text = "";
this._title = "";
this._color = "#0078d7";
this.show = function() {
var self = this;
this.elementId = MessageBoxForJS(
this._text,
this._title,
this.type,
this._color,
this._boundCallback
function(valueReturn) {
self._boundCallback(valueReturn);
}
);
setTimeout(function() {
var element = document.getElementById(this.elementId);
var element = document.getElementById(self.elementId);
if (element) {
var bodyElement = element.querySelector(".notice-body");
if (bodyElement) {
bodyElement.style.transition = "all 0.5s linear";
}
}
}.bind(this), 100);
}
}, 100);
};
Object.defineProperty(this, "text", {
get: function() {
return this._text;
},
get: function() { return this._text; },
set: function(value) {
this._text = value;
if (this.elementId) {
@@ -314,10 +383,9 @@ function MsgBoxObj() {
}
}
});
Object.defineProperty(this, "title", {
get: function() {
return this._title;
},
get: function() { return this._title; },
set: function(value) {
this._title = value;
if (this.elementId) {
@@ -331,10 +399,9 @@ function MsgBoxObj() {
}
}
});
Object.defineProperty(this, "color", {
get: function() {
return this._color;
},
get: function() { return this._color; },
set: function(value) {
this._color = value;
if (this.elementId) {
@@ -348,6 +415,7 @@ function MsgBoxObj() {
}
}
});
this.getElement = function() {
return document.getElementById(this.elementId);
};
@@ -357,176 +425,4 @@ MsgBoxObj.prototype._internalCallback = function(returnValue) {
if (typeof this.callback === "function") {
this.callback(returnValue);
}
};
/**
* 异步显示消息框,返回一个 Promise 对象。
* @param {string | HTMLElement} swText 内容
* @param {string} swTitle 标题
* @param {MBFLAGS} uType 标志,使用 MBFLAGS 常量
* @param {string} swColor 背景颜色文本。
* @returns {Promise}
*/
function messageBoxAsync(swText, swTitle, uType, swColor, pfCallback) {
if (typeof Promise === "undefined") {
console.error("Promise is not supported in this environment.");
MessageBoxForJS(swText, swTitle, uType, swColor, pfCallback);
}
return new Promise(function(resolve, reject) {
try {
MessageBoxForJS(swText, swTitle, uType, swColor, function(valueReturn) {
if (resolve) resolve(valueReturn);
});
} catch (ex) {
if (reject) reject(ex);
}
});
}
function MessageBoxButton(swDisplayName, nValueReturn) {
this.displayName = swDisplayName;
this.value = nValueReturn;
}
function messageBoxAdvance(swText, swCaption, aCommands, swColor, pfCallback) {
var _lpText = swText;
var _lpCaption = swCaption;
var msgbox = document.createElement("div");
msgbox.classList.add("notice-back");
msgbox.classList.add("win-ui-dark");
var uniqueId = "msgbox_" + new Date().getTime();
msgbox.id = uniqueId;
var msgbody = document.createElement("div");
msgbody.classList.add("notice-body");
if (!IsBlackLabel(swColor)) {
msgbody.style.backgroundColor = swColor;
}
msgbox.appendChild(msgbody);
var msgcontainter = document.createElement("div");
msgcontainter.style.height = "100%";
msgcontainter.style.width = "100%";
msgcontainter.style.maxHeight = "100%";
msgcontainter.style.minHeight = "0px";
msgcontainter.style.boxSizing = "border-box";
msgbody.appendChild(msgcontainter);
var msgcaption = document.createElement("div");
msgcontainter.appendChild(msgcaption);
msgcontainter.style.display = "flex";
msgcontainter.style.flexDirection = "column";
var msgcontent = document.createElement("div");
msgcontent.style.flex = "1 1 auto";
msgcontent.style.marginRight = "3px";
msgcontent.style.overflowX = "hidden";
msgcontent.style.overflowY = "auto";
msgcontent.style.minHeight = "0px";
msgcontainter.appendChild(msgcontent);
if (_lpCaption instanceof HTMLElement) {
msgcaption.appendChild(_lpCaption);
msgcaption.classList.add("notice-title");
} else {
if (!IsBlackLabel(_lpCaption)) {
var msgtitle = document.createElement("h2");
msgtitle.textContent = _lpCaption;
msgtitle.classList.add("notice-title");
msgcaption.appendChild(msgtitle);
} else {
var msgtitle = document.createElement("h2");
msgtitle.textContent = "";
msgtitle.classList.add("notice-title");
msgcaption.appendChild(msgtitle);
}
}
if (_lpText instanceof HTMLElement || _lpText instanceof HTMLDivElement || typeof _lpText !== "string") {
try {
_lpText.classList.add("notice-text");
msgcontent.appendChild(_lpText);
} catch (e) {
if (!IsBlackLabel(_lpText)) {
var msgtext = document.createElement("p");
msgtext.textContent = _lpText;
msgtext.classList.add("notice-text");
if (IsBlackLabel(_lpCaption)) {
msgtext.style.marginTop = "0";
}
msgcontent.appendChild(msgtext);
} else {
var msgtext = document.createElement("p");
msgtext.innerText = "";
msgtext.classList.add("notice-text");
if (IsBlackLabel(_lpCaption)) {
msgtext.style.marginTop = "0";
}
msgcontent.appendChild(msgtext);
}
}
} else {
if (!IsBlackLabel(_lpText)) {
var msgtext = document.createElement("p");
msgtext.textContent = _lpText;
msgtext.classList.add("notice-text");
if (IsBlackLabel(_lpCaption)) {
msgtext.style.marginTop = "0";
}
msgcontent.appendChild(msgtext);
} else {
var msgtext = document.createElement("p");
msgtext.innerText = "";
msgtext.classList.add("notice-text");
if (IsBlackLabel(_lpCaption)) {
msgtext.style.marginTop = "0";
}
msgcontent.appendChild(msgtext);
}
}
var msgctrls = document.createElement("div");
msgctrls.classList.add("notice-controls");
msgcontainter.appendChild(msgctrls);
if (aCommands.length <= 0) {
aCommands.push(new MessageBoxButton(GetLocaleStringFromResId(800) || "OK", MBRET.IDOK));
}
for (var i = 0; i < aCommands.length; i++) {
var cmd = aCommands[i];
var btn = document.createElement("button");
btn.textContent = cmd.displayName;
btn.setAttribute("data-msgbox-value", cmd.value);
Windows.UI.Event.Util.addEvent(btn, "click", function(event) {
var btns = this.parentNode.querySelectorAll("button");
var lastbtnstatus = [];
for (var j = 0; j < btns.length; j++) {
lastbtnstatus.push(btns[j].disabled);
btns[j].disabled = true;
}
try {
pfCallback(this.getAttribute("data-msgbox-value"));
} catch (e) {}
msgbox.style.opacity = 0;
setTimeout(function(nodes, laststatus) {
for (var k = 0; k < nodes.length; k++) {
nodes[k].disabled = laststatus[k];
}
document.body.removeChild(msgbox);
}, 500, btns, lastbtnstatus);
});
msgctrls.appendChild(btn);
}
document.body.appendChild(msgbox);
setTimeout(function() {
msgbox.style.opacity = 1;
}, 1);
return msgbox.id;
}
function messageBoxAdvanceAsync(swText, swCaption, aCommands, swColor) {
if (typeof Promise === "undefined") {
console.error("Promise is not supported in this environment.");
messageBoxAdvance(swText, swCaption, aCommands, swColor);
}
return new Promise(function(resolve, reject) {
try {
messageBoxAdvance(swText, swCaption, aCommands, swColor, function(valueReturn) {
if (resolve) resolve(valueReturn);
});
} catch (ex) {
if (reject) reject(ex);
}
});
}
};