mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-11 17:57:19 +10:00
396 lines
15 KiB
JavaScript
396 lines
15 KiB
JavaScript
(function(global) {
|
||
"use strict";
|
||
|
||
// 基类:提供 element 管理与基础 dispose 行为
|
||
function PMAppBarBaseMember() {
|
||
var _element = null;
|
||
Object.defineProperty(this, "element", {
|
||
configurable: true, // <- 关键:允许子类重定义该属性
|
||
enumerable: false,
|
||
get: function() { return _element; },
|
||
set: function(value) {
|
||
_element = value;
|
||
try {
|
||
if (_element) {
|
||
// 让 DOM 节点可以反查到对应的 member
|
||
_element.appBarMember = this;
|
||
}
|
||
} catch (e) {}
|
||
}
|
||
});
|
||
// 可被子类或外部调用来从 DOM 中移除自身
|
||
this.dispose = function() {
|
||
try {
|
||
if (this.element && this.element.parentNode) {
|
||
this.element.parentNode.removeChild(this.element);
|
||
}
|
||
} catch (e) {}
|
||
};
|
||
}
|
||
|
||
function PMAppBarCommand() {
|
||
PMAppBarBaseMember.call(this);
|
||
var _button = document.createElement("button");
|
||
var _iconcontainer = document.createElement("span");
|
||
var _iconnode = document.createElement("span");
|
||
var _labelnode = document.createElement("span");
|
||
_button.appendChild(_iconcontainer);
|
||
_iconcontainer.appendChild(_iconnode);
|
||
_button.appendChild(_labelnode);
|
||
_button.classList.add("win-command");
|
||
_button.setAttribute("role", "menuitem");
|
||
_iconcontainer.classList.add("win-commandicon");
|
||
_iconcontainer.classList.add("win-commandring");
|
||
_iconnode.classList.add("win-commandimage");
|
||
_labelnode.classList.add("win-label");
|
||
_iconcontainer.tabIndex = -1;
|
||
_iconnode.tabIndex = -1;
|
||
_labelnode.tabIndex = -1;
|
||
_button.classList.add("win-global");
|
||
Windows.UI.Event.Util.addEvent(_button, "keydown", function(event) {
|
||
if (event.keyCode === 13) {
|
||
_button.click();
|
||
}
|
||
});
|
||
Object.defineProperty(this, "element", {
|
||
get: function() { return _button; },
|
||
set: function(value) { _button = value; }
|
||
});
|
||
Object.defineProperty(this, "icon", {
|
||
get: function() { return _iconnode.innerHTML; },
|
||
set: function(value) { _iconnode.innerHTML = value; }
|
||
});
|
||
Object.defineProperty(this, "label", {
|
||
get: function() { return _labelnode.textContent; },
|
||
set: function(value) { _labelnode.textContent = value; }
|
||
});
|
||
Object.defineProperty(this, "onclick", {
|
||
get: function() { return _button.onclick; },
|
||
set: function(value) { _button.onclick = value; }
|
||
});
|
||
Object.defineProperty(this, "selectable", {
|
||
get: function() { return _button.classList.contains("win-selectable"); },
|
||
set: function(value) {
|
||
try { Windows.UI.Event.Util.removeEvent(this.element, "click", selectHandler); } catch (e) {}
|
||
_button.classList.toggle("win-selectable", value);
|
||
if (!value) {
|
||
if (_button.classList.contains("win-selected")) {
|
||
_button.classList.remove("win-selected");
|
||
}
|
||
}
|
||
if (value) Windows.UI.Event.Util.addEvent(this.element, "click", selectHandler);
|
||
else Windows.UI.Event.Util.removeEvent(this.element, "click", selectHandler);
|
||
}
|
||
});
|
||
Object.defineProperty(this, "selected", {
|
||
get: function() { return _button.classList.contains("win-selected"); },
|
||
set: function(value) { _button.classList.toggle("win-selected", value); }
|
||
});
|
||
Object.defineProperty(this, "disabled", {
|
||
get: function() { try { return this.element.disabled; } catch (e) { return false; } },
|
||
set: function(value) { try { this.element.disabled = value; } catch (e) {} }
|
||
});
|
||
// global 或 selection (始终显示或有选择时显示)
|
||
Object.defineProperty(this, "section", {
|
||
get: function() {
|
||
if (_button.classList.contains("win-global")) return "global";
|
||
if (_button.classList.contains("win-selection")) return "selection";
|
||
return "none";
|
||
},
|
||
set: function(value) {
|
||
_button.classList.remove("win-global");
|
||
_button.classList.remove("win-selection");
|
||
if (value == "global") _button.classList.add("win-global");
|
||
if (value == "selection") _button.classList.add("win-selection");
|
||
}
|
||
});
|
||
|
||
function selectHandler(event) {
|
||
_button.classList.toggle("win-selected");
|
||
}
|
||
this.addEventListener = function(type, listener) {
|
||
try { Windows.UI.Event.Util.addEvent(this.element, type, listener); } catch (e) {}
|
||
};
|
||
this.removeEventListener = function(type, listener) {
|
||
try { Windows.UI.Event.Util.removeEvent(this.element, type, listener); } catch (e) {}
|
||
};
|
||
|
||
}
|
||
|
||
function PMAppBarSeparator() {
|
||
PMAppBarBaseMember.call(this);
|
||
var _hr = document.createElement("hr");
|
||
_hr.classList.add("win-command");
|
||
_hr.classList.add("win-global");
|
||
_hr.setAttribute("role", "separator");
|
||
Object.defineProperty(this, "element", {
|
||
get: function() { return _hr; },
|
||
set: function(value) { _hr = value; }
|
||
});
|
||
}
|
||
|
||
function PMAppBar(container) {
|
||
var _container = container;
|
||
var _enable = true;
|
||
|
||
function init(node) {
|
||
var classNames = [
|
||
"win-overlay",
|
||
"win-commandlayout",
|
||
"win-appbar",
|
||
"appbar"
|
||
]
|
||
try {
|
||
for (var i = 0; i < classNames.length; i++) {
|
||
if (!node.classList.contains(classNames[i]))
|
||
node.classList.add(classNames[i]);
|
||
}
|
||
} catch (e) {}
|
||
try {
|
||
node.appBarControl = this;
|
||
} catch (e) {}
|
||
}
|
||
Object.defineProperty(this, "element", {
|
||
get: function() { return _container; },
|
||
set: function(value) {
|
||
_container = value;
|
||
init(value);
|
||
// 将已有成员渲染到新的容器中
|
||
try {
|
||
// 先移除所有成员 DOM(如果之前挂载过)
|
||
for (var i = 0; i < this._members.length; i++) {
|
||
try {
|
||
var mEl = this._members[i].element;
|
||
if (mEl && mEl.parentNode === _container) {
|
||
_container.removeChild(mEl);
|
||
}
|
||
} catch (e) {}
|
||
}
|
||
// 重新挂载所有成员,按数组顺序
|
||
for (i = 0; i < this._members.length; i++) {
|
||
try {
|
||
var el = this._members[i].element;
|
||
if (el) _container.appendChild(el);
|
||
} catch (e) {}
|
||
}
|
||
} catch (e) {}
|
||
}
|
||
});
|
||
|
||
// 成员管理
|
||
this._members = [];
|
||
|
||
// 返回内部数组引用(只读语义上)
|
||
Object.defineProperty(this, "members", {
|
||
get: function() { return this._members; }
|
||
});
|
||
|
||
// 添加成员到末尾,返回索引;若失败返回 -1
|
||
this.add = function(member) {
|
||
if (!member || !member.element) return -1;
|
||
this._members.push(member);
|
||
try {
|
||
if (_container) _container.appendChild(member.element);
|
||
} catch (e) {}
|
||
this._updateSelectionVisibility();
|
||
return this._members.length - 1;
|
||
};
|
||
this.addMember = this.add; // alias
|
||
|
||
// 在指定索引处插入(如果 index 为 undefined 或超范围,则 append)
|
||
this.insertAt = function(member, index) {
|
||
if (!member || !member.element) return -1;
|
||
var len = this._members.length;
|
||
if (typeof index !== "number" || index < 0 || index > len) {
|
||
return this.add(member);
|
||
}
|
||
this._members.splice(index, 0, member);
|
||
try {
|
||
if (_container) {
|
||
var refNode = _container.childNodes[index] || null;
|
||
_container.insertBefore(member.element, refNode);
|
||
}
|
||
} catch (e) {}
|
||
this._updateSelectionVisibility();
|
||
return index;
|
||
};
|
||
|
||
// remove 接受成员对象或索引
|
||
this.remove = function(memberOrIndex) {
|
||
var idx = -1;
|
||
if (typeof memberOrIndex === "number") {
|
||
idx = memberOrIndex;
|
||
} else {
|
||
idx = this._members.indexOf(memberOrIndex);
|
||
}
|
||
if (idx < 0 || idx >= this._members.length) return false;
|
||
var removed = this._members.splice(idx, 1)[0];
|
||
try {
|
||
if (removed && removed.element && removed.element.parentNode) {
|
||
removed.element.parentNode.removeChild(removed.element);
|
||
}
|
||
} catch (e) {}
|
||
this._updateSelectionVisibility();
|
||
return true;
|
||
};
|
||
|
||
// 替换指定索引的成员,返回 true/false
|
||
this.replaceAt = function(index, member) {
|
||
if (!member || !member.element) return false;
|
||
if (typeof index !== "number" || index < 0 || index >= this._members.length) return false;
|
||
var old = this._members[index];
|
||
this._members[index] = member;
|
||
try {
|
||
if (_container && old && old.element) {
|
||
// 如果 old.element 在容器中,直接 replaceChild
|
||
if (old.element.parentNode === _container) {
|
||
_container.replaceChild(member.element, old.element);
|
||
} else {
|
||
// 备用:在位置 index 插入
|
||
var ref = _container.childNodes[index] || null;
|
||
_container.insertBefore(member.element, ref);
|
||
}
|
||
} else if (_container) {
|
||
// 没有 old 元素,直接 append
|
||
_container.appendChild(member.element);
|
||
}
|
||
} catch (e) {}
|
||
this._updateSelectionVisibility();
|
||
return true;
|
||
};
|
||
|
||
this.getMember = function(index) {
|
||
return this._members[index];
|
||
};
|
||
|
||
this.indexOf = function(member) {
|
||
return this._members.indexOf(member);
|
||
};
|
||
|
||
this.clear = function() {
|
||
while (this._members.length) {
|
||
var m = this._members.shift();
|
||
try {
|
||
if (m && m.element && m.element.parentNode) {
|
||
m.element.parentNode.removeChild(m.element);
|
||
}
|
||
} catch (e) {}
|
||
}
|
||
};
|
||
|
||
var timer = null;
|
||
var isupdating = false;
|
||
|
||
function waitTimer(ms) {
|
||
clearTimeout(timer);
|
||
isupdating = true;
|
||
timer = setTimeout(function(t) {
|
||
isupdating = false;
|
||
t = null;
|
||
}, ms, timer);
|
||
}
|
||
Object.defineProperty(this, "isupdating", {
|
||
get: function() { return isupdating; }
|
||
});
|
||
var touchHide = document.createElement("div");
|
||
touchHide.classList.add("appbar-touchhide");
|
||
touchHide.style.display = "none";
|
||
Windows.UI.Event.Util.addEvent(touchHide, "click", function(event) {
|
||
touchHide.style.display = "none";
|
||
this.hide();
|
||
}.bind(this));
|
||
document.body.appendChild(touchHide);
|
||
|
||
function showTouchHide() {
|
||
if (touchHide == null || touchHide == void 0) {
|
||
touchHide = document.createElement("div");
|
||
touchHide.classList.add("appbar-touchhide");
|
||
}
|
||
touchHide.style.display = "";
|
||
}
|
||
|
||
function hideTouchHide() {
|
||
touchHide.style.display = "none";
|
||
}
|
||
this.show = function() {
|
||
try {
|
||
if (!_enable) return;
|
||
if (!this.element.classList.contains("show"))
|
||
this.element.classList.add("show");
|
||
waitTimer(500);
|
||
showTouchHide();
|
||
} catch (e) {}
|
||
};
|
||
this.hide = function() {
|
||
try {
|
||
if (this.element.classList.contains("show"))
|
||
this.element.classList.remove("show");
|
||
waitTimer(500);
|
||
hideTouchHide();
|
||
} catch (e) {}
|
||
};
|
||
this.setSelectionActive = function(active) {
|
||
this._hasSelection = !!active;
|
||
this._updateSelectionVisibility();
|
||
};
|
||
this._updateSelectionVisibility = function() {
|
||
for (var i = 0; i < this._members.length; i++) {
|
||
var el = this._members[i].element;
|
||
if (el && el.classList && el.classList.contains("win-selection")) {
|
||
el.style.display = this._hasSelection ? "" : "none";
|
||
}
|
||
}
|
||
};
|
||
Object.defineProperty(this, "enabled", {
|
||
get: function() { return _enable; },
|
||
set: function(value) {
|
||
_enable = value;
|
||
if (!value) {
|
||
this.hide();
|
||
}
|
||
}
|
||
});
|
||
Object.defineProperty(this, "isshowing", {
|
||
get: function() { return this.element.classList.contains("show"); },
|
||
set: function(value) {
|
||
if (value) {
|
||
this.show();
|
||
} else {
|
||
this.hide();
|
||
}
|
||
}
|
||
});
|
||
this._eventShowHandler = function(event) {
|
||
if (!this.isshowing) this.show();
|
||
else this.hide();
|
||
};
|
||
this._eventHideHandler = function(event) {
|
||
this.hide();
|
||
};
|
||
var EventUtil = Windows.UI.Event.Util;
|
||
var self = this;
|
||
EventUtil.addEvent(document, "contextmenu", function(event) {
|
||
self._eventShowHandler(event);
|
||
event.preventDefault();
|
||
});
|
||
var pressTimer = null;
|
||
|
||
EventUtil.addEvent(document, "mousedown", function(event) {
|
||
if (!self._enable) return;
|
||
pressTimer = setTimeout(function(e) {
|
||
self._eventShowHandler(e);
|
||
event.preventDefault();
|
||
}, 600, event);
|
||
});
|
||
|
||
EventUtil.addEvent(document, "mouseup", function() {
|
||
clearTimeout(pressTimer);
|
||
});
|
||
}
|
||
global.AppBar = {
|
||
AppBar: PMAppBar,
|
||
Command: PMAppBarCommand,
|
||
Separator: PMAppBarSeparator,
|
||
BaseMember: PMAppBarBaseMember
|
||
};
|
||
})(this); |