mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-11 17:57:19 +10:00
184 lines
5.9 KiB
JavaScript
184 lines
5.9 KiB
JavaScript
(function(global) {
|
||
"use strict";
|
||
|
||
/**
|
||
* TransitionPanel
|
||
* axis: 'x' | 'y' | 'both'
|
||
* speed: 'fast' | 'medium' | 'slow'
|
||
* el: DOM 元素
|
||
*/
|
||
function TransitionPanel(el, options) {
|
||
if (!el) throw new Error("TransitionPanel requires a DOM element.");
|
||
|
||
this.el = el;
|
||
this.opts = options || {};
|
||
this.axis = this.opts.axis || 'y';
|
||
this.speed = this.opts.speed || 'medium';
|
||
|
||
// 初始化状态
|
||
this._shown = false;
|
||
this._events = {};
|
||
|
||
// 确保基础类 statusbar
|
||
if (!el.classList.contains('statusbar')) el.classList.add('statusbar');
|
||
|
||
// 确保 axis 类存在(x/y/both)
|
||
if (this.axis === 'x' && !el.classList.contains('x')) el.classList.add('x');
|
||
else if (this.axis === 'y' && !el.classList.contains('y')) el.classList.add('y');
|
||
else if (this.axis === 'both' && !el.classList.contains('both')) el.classList.add('both');
|
||
|
||
// 添加速度类
|
||
if (this.speed === 'fast') el.classList.add('fast');
|
||
else if (this.speed === 'medium') el.classList.add('medium');
|
||
else el.classList.add('slow');
|
||
|
||
// 内容变化自动刷新
|
||
this._bindContentChange();
|
||
}
|
||
|
||
function maxWidth(el) {
|
||
var cw = 0;
|
||
var ow = 0;
|
||
var rw = 0;
|
||
var sw = 0;
|
||
try { cw = el.clientWidth; } catch (e) {}
|
||
try { ow = el.offsetWidth; } catch (e) {}
|
||
try { rw = el.getBoundingClientRect().width; } catch (e) {}
|
||
try { sw = el.scrollWidth; } catch (e) {}
|
||
return Math.max(cw, ow, rw, sw);
|
||
}
|
||
|
||
function maxHeight(el) {
|
||
var ch = 0;
|
||
var oh = 0;
|
||
var rh = 0;
|
||
var sh = 0;
|
||
try { ch = el.clientHeight; } catch (e) {}
|
||
try { oh = el.offsetHeight; } catch (e) {}
|
||
try { rh = el.getBoundingClientRect().height; } catch (e) {}
|
||
try { sh = el.scrollHeight; } catch (e) {}
|
||
return Math.max(ch, oh, rh, sh);
|
||
}
|
||
// 显示
|
||
TransitionPanel.prototype.show = function() {
|
||
if (this._shown) return;
|
||
this._emit('beforeshow');
|
||
this._shown = true;
|
||
|
||
var el = this.el;
|
||
|
||
setTimeout(function() {
|
||
this._emit('show');
|
||
|
||
if (this.axis !== 'x') el.style.height = maxHeight(el) + 'px';
|
||
if (this.axis !== 'y') el.style.width = maxWidth(el) + 'px';
|
||
if (this.axis === 'both') {
|
||
el.style.height = maxHeight(el) + 'px';
|
||
el.style.width = maxWidth(el) + 'px';
|
||
}
|
||
this._afterTransition('aftershow');
|
||
}.bind(this), 16);
|
||
};
|
||
|
||
// 隐藏
|
||
TransitionPanel.prototype.hide = function() {
|
||
if (!this._shown) return;
|
||
this._emit('beforehide');
|
||
this._shown = false;
|
||
|
||
var el = this.el;
|
||
|
||
// 锁定当前尺寸
|
||
if (this.axis !== 'x') el.style.height = maxHeight(el) + 'px';
|
||
if (this.axis !== 'y') el.style.width = maxWidth(el) + 'px';
|
||
if (this.axis === 'both') {
|
||
el.style.height = maxHeight(el) + 'px';
|
||
el.style.width = maxWidth(el) + 'px';
|
||
}
|
||
setTimeout(function() {
|
||
this._emit('hide');
|
||
|
||
// 回到折叠状态尺寸(依赖 x/y/both 类)
|
||
if (this.axis !== 'x') el.style.height = '';
|
||
if (this.axis !== 'y') el.style.width = '';
|
||
if (this.axis === 'both') {
|
||
el.style.height = '';
|
||
el.style.width = '';
|
||
}
|
||
this._afterTransition('afterhide');
|
||
}.bind(this), 16);
|
||
};
|
||
|
||
// 刷新尺寸(显示中)
|
||
TransitionPanel.prototype.refresh = function() {
|
||
if (!this._shown) return;
|
||
var el = this.el;
|
||
if (this.axis !== 'x') el.style.height = el.scrollHeight + 'px';
|
||
if (this.axis !== 'y') el.style.width = el.scrollWidth + 'px';
|
||
};
|
||
|
||
// 内容变化自动刷新
|
||
TransitionPanel.prototype._bindContentChange = function() {
|
||
if (!global.setTextChangeEvent) return;
|
||
var self = this;
|
||
global.setTextChangeEvent(this.el, function() {
|
||
if (self._shown) self.refresh();
|
||
});
|
||
};
|
||
|
||
// transitionend 回调处理
|
||
TransitionPanel.prototype._afterTransition = function(evt) {
|
||
var el = this.el;
|
||
var called = false;
|
||
var duration = this.speed === 'fast' ? 300 : (this.speed === 'medium' ? 500 : 700);
|
||
|
||
function done() {
|
||
if (called) return;
|
||
called = true;
|
||
el.removeEventListener('transitionend', done);
|
||
if (evt) this._emit(evt);
|
||
}
|
||
el.addEventListener('transitionend', done.bind(this));
|
||
setTimeout(done.bind(this), duration + 30);
|
||
};
|
||
|
||
// 生命周期事件绑定
|
||
TransitionPanel.prototype.on = function(name, fn) {
|
||
(this._events[name] || (this._events[name] = [])).push(fn);
|
||
};
|
||
|
||
// 事件触发
|
||
TransitionPanel.prototype._emit = function(name) {
|
||
var list = this._events[name];
|
||
if (!list) return;
|
||
for (var i = 0; i < list.length; i++) {
|
||
try { list[i].call(this); } catch (e) { console.error(e); }
|
||
}
|
||
};
|
||
|
||
// 只读属性 shown
|
||
Object.defineProperty(TransitionPanel.prototype, 'shown', {
|
||
get: function() { return this._shown; }
|
||
});
|
||
|
||
// 销毁
|
||
TransitionPanel.prototype.dispose = function() {
|
||
// 移除所有事件回调
|
||
this._events = {};
|
||
// 清理 el 内联样式
|
||
if (this.el) {
|
||
this.el.style.height = '';
|
||
this.el.style.width = '';
|
||
}
|
||
this._shown = false;
|
||
// 可选:删除内容变化监听(如果使用全局 setTextChangeEvent)
|
||
if (global.Windows && global.Windows.UI && global.Windows.UI.Event && global.Windows.UI.Event.Monitor) {
|
||
// 这里可以 detach 所有回调
|
||
// 视具体实现可扩展
|
||
}
|
||
};
|
||
|
||
// 全局暴露
|
||
global.TransitionPanel = TransitionPanel;
|
||
|
||
})(this); |