topmostfriend-website/public/simulator.js

898 lines
28 KiB
JavaScript
Raw Normal View History

2023-11-19 16:57:31 +00:00
// An attempt was made to make this entirely function in IE8, I gave up at the polishing stage
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if(!Object.keys) {
Object.keys = (function() {
'use strict';
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
return function(obj) {
if (typeof obj !== 'function' && (typeof obj !== 'object' || obj === null)) {
throw new TypeError('Object.keys called on non-object');
}
var result = [], prop, i;
for (prop in obj) {
if (hasOwnProperty.call(obj, prop)) {
result.push(prop);
}
}
if (hasDontEnumBug) {
for (i = 0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) {
result.push(dontEnums[i]);
}
}
}
return result;
};
}());
}
var tmfBindEvent = function(subject, name, callback) {
if(document.attachEvent)
return subject.attachEvent('on' + name, callback);
return subject.addEventListener(name, callback);
};
var tmfOnReady = function(callback) {
if(document.attachEvent)
document.attachEvent('onreadystatechange', function() {
if(document.readyState === 'complete')
callback();
});
else
document.addEventListener('DOMContentLoaded', function() {
callback();
});
};
var tmfCreateElement = function(elemInfo) {
elemInfo = elemInfo || {};
var elem = document.createElement(elemInfo.tag || 'div');
if(elemInfo.props) {
var propKeys = Object.keys(elemInfo.props);
for(var i = 0; i < propKeys.length; i++) {
var propKey = propKeys[i];
if(elemInfo.props[propKey] === undefined
|| elemInfo.props[propKey] === null)
continue;
switch(typeof elemInfo.props[propKey]) {
case 'function':
tmfBindEvent(
elem,
propKey.substring(0, 2) === 'on'
? propKey.substring(2).toLowerCase()
: propKey,
elemInfo.props[propKey]
);
break;
default:
elem.setAttribute(propKey === 'className' ? 'class' : propKey, elemInfo.props[propKey]);
break;
}
}
}
if(elemInfo.children) {
var children = elemInfo.children;
if(Object.prototype.toString.call(children) !== '[object Array]')
children = [children];
for(var i = 0; i < children.length; i++) {
var child = children[i];
if(typeof child === 'undefined')
continue;
switch(typeof child) {
case 'string':
elem.appendChild(document.createTextNode(child));
break;
case 'object':
if(child instanceof Element)
elem.appendChild(child);
else if(child.getElement)
elem.appendChild(child.getElement());
else
elem.appendChild(tmfCreateElement(child));
break;
default:
elem.appendChild(document.createTextNode(child.toString()));
break;
}
}
}
if(elemInfo.created)
elemInfo.created(elem);
return elem;
};
var tmfClientRectangle = function() {
if(typeof window.innerWidth !== 'undefined')
return [window.innerWidth, window.innerHeight];
if(typeof document.documentElement !== 'undefined'
&& typeof document.documentElement.clientWidth !== 'undefined'
&& document.documentElement.clientWidth !== 0)
return [document.documentElement.clientWidth, document.documentElement.clientHeight];
var body = document.getElementsByTagName('body')[0];
return [body.clientWidth, body.clientHeight];
};
var tmfIs12HourClockValue = null;
var tmfIs12Hour = function() {
if(typeof window.tmfIs12HourClockValue === 'boolean')
return window.tmfIs12HourClockValue;
var d = new Date;
return window.tmfIs12HourClockValue = !!(d.toLocaleTimeString().match(/am|pm/i) || d.toString().match(/am|pm/i));
};
var tmfTimeString = function() {
var date = new Date,
str = '',
stupid = tmfIs12Hour(),
dumb = '',
hours = date.getHours(),
mins = date.getMinutes();
if(stupid) {
dumb = hours > 11 ? 'pm' : 'am';
if(hours === 0)
hours = 12;
}
str = hours.toString() + ':';
if(mins < 10)
str += '0';
str += mins.toString();
if(stupid)
str += ' ' + dumb;
return str;
};
var tmfSetElemText = function(elem, text) {
if(typeof elem.textContent !== 'undefined')
elem.textContent = text;
else if(typeof elem.innerText !== 'undefined')
elem.innerText = text;
else {
elem.innerHTML = '';
elem.appendChild(document.createTextNode(text));
}
};
var tmfCreateMenuItem = function(name, icon, click) {
var item = tmfCreateElement({
props: { className: 'tmfs-menu-item' },
children: [
{
props: { className: 'tmfs-menu-item-icon' },
children: {
tag: 'img',
props: {
src: icon,
alt: name,
},
},
},
{
props: { className: 'tmfs-menu-item-text' },
children: name,
},
],
});
tmfBindEvent(item, 'click', click);
return item;
};
var tmfRemoveElement = function(elem) {
if(elem && elem.parentNode)
elem.parentNode.removeChild(elem);
};
var tmfGetCentrePosition = function(width, height) {
var rect = tmfClientRectangle();
rect[0] /= 2;
rect[1] /= 2;
rect[0] -= Math.ceil(width / 2);
rect[1] -= Math.ceil(height / 2);
return rect;
};
var tmfGetCentrePositionStyle = function(width, height) {
var rect = tmfGetCentrePosition(width, height);
return 'top: ' + rect[1].toString() + 'px; left: ' + rect[0].toString() + 'px;';
};
var tmfShowAbout = function() {
var about = tmfCreateElement({
props: {
className: 'tmfs-about',
style: tmfGetCentrePositionStyle(445, 120),
},
children: [
{
props: {
className: 'tmfs-about-drag',
onmousedown: function() {
tmfSetDragging(about);
},
},
},
{
props: { className: 'tmfs-about-version' },
children: [
'v1.5.1',
{ tag: 'br' },
'Simulator',
],
},
{
tag: 'input',
props: {
className: 'tmfs-about-button tmfs-about-button-donate',
type: 'button',
value: 'Donate',
onClick: function() {
tmfRemoveElement(about);
document.getElementById('_nav_donate').click();
},
},
},
{
tag: 'input',
props: {
className: 'tmfs-about-button tmfs-about-button-website',
type: 'button',
value: 'Website',
onClick: function() {
tmfRemoveElement(about);
// should this do anything? we're already there lol
},
},
},
{
tag: 'input',
props: {
className: 'tmfs-about-button tmfs-about-button-close',
type: 'button',
value: 'Close',
onClick: function() {
tmfRemoveElement(about);
},
},
},
{
tag: 'a',
props: {
className: 'tmfs-about-credit',
href: '//flash.moe',
target: '_blank',
rel: 'noopener',
},
},
{
tag: 'a',
props: {
className: 'tmfs-about-credit tmfs-about-credit-fff',
href: 'http://www.famfamfam.com/lab/icons/silk/',
target: '_blank',
rel: 'noopener',
},
},
],
});
document.body.appendChild(about);
};
var tmfCtxMenu = null;
var tmfShowCtxMenu = function(xpos, ypos) {
tmfDestroyCtxMenu();
var refresh = tmfCreateMenuItem('Refresh', './arrow_refresh.gif', function() {
// can this do anything?
}), settings = tmfCreateMenuItem('Settings', './cog.gif', function() {
tmfDestroyCtxMenu();
tmfShowSettings();
}), about = tmfCreateMenuItem('About', './help.gif', function() {
tmfDestroyCtxMenu();
tmfShowAbout();
}), quit = tmfCreateMenuItem('Quit', './door_in.gif', function() {
tmfDestroyCtxMenu();
tmfDestroySysIcon();
});
tmfCtxMenu = tmfCreateElement({
props: {
className: 'tmfs-menu',
},
children: [
refresh,
settings,
about,
quit,
],
});
document.body.appendChild(tmfCtxMenu);
xpos -= tmfCtxMenu.offsetWidth;
ypos -= tmfCtxMenu.offsetHeight;
tmfCtxMenu.style.top = ypos.toString() + 'px';
tmfCtxMenu.style.left = xpos.toString() + 'px';
};
var tmfDestroyCtxMenu = function() {
if(tmfCtxMenu)
tmfRemoveElement(tmfCtxMenu);
tmfCtxMenu = null;
};
var tmfSysIcon = null;
var tmfDestroySysIcon = function() {
if(tmfSysIcon)
tmfRemoveElement(tmfSysIcon);
tmfSysIcon = null;
};
var tmfDragging = null, tmfDragLastX = 0, tmfDragLastY = 0;
var tmfSetDragging = function(elem) {
//tmfDragging = elem;
};
var tmfStopDragging = function() {
tmfDragging = null;
};
var tmfDragHandler = function(ev) {
var movX = ev.screenX - tmfDragLastX,
movY = ev.screenY - tmfDragLastY;
tmfDragLastX = ev.screenX;
tmfDragLastY = ev.screenY;
if(tmfDragging === null)
return;
var xpos = tmfDragging.offsetLeft + movX,
ypos = tmfDragging.offsetTop + movY;
tmfDragging.style.left = xpos.toString() + 'px';
tmfDragging.style.top = ypos.toString() + 'px';
};
var tmfCreateWindow = function(title, className, width, height, closeHandler) {
var frame, body = tmfCreateElement({
props: { className: 'tmfs-window-body' },
});
if(!closeHandler)
closeHandler = function() {
tmfRemoveElement(frame);
};
frame = tmfCreateElement({
props: {
className: 'tmfs-window ' + className,
style: tmfGetCentrePositionStyle(width, height),
},
children: [
{
props: {
className: 'tmfs-window-title',
onmousedown: function() {
tmfSetDragging(frame);
},
},
children: [
{
tag: 'img',
props: {
className: 'tmfs-window-title-icon',
alt: 'ico',
src: './icon.gif',
},
},
{
props: {
className: 'tmfs-window-title-close',
onclick: closeHandler,
},
children: 'X',
},
{
props: {
className: 'tmfs-window-title-text',
},
children: title.toString(),
},
],
},
body,
],
});
document.body.appendChild(frame);
return {
frame: frame,
body: body,
};
};
var tmfCreateFieldset = function(title, className) {
var body = tmfCreateElement({
props: {
className: 'tmfs-fieldset-body',
}
});
var frame = tmfCreateElement({
tag: 'fieldset',
props: {
className: 'tmfs-fieldset ' + className,
},
children: [
{
tag: 'legend',
props: {
className: 'tmfs-fieldset-title',
},
children: title.toString()
},
body,
],
});
return {
frame: frame,
body: body,
};
};
var tmfCreateCheckbox = function(className, label, state, enabled, onChange) {
return tmfCreateElement({
tag: 'label',
props: {
className: 'tmfs-checkbox ' + className,
},
children: [
{
tag: 'input',
props: {
type: 'checkbox',
className: 'tmfs-checkbox-input',
checked: state ? true : undefined,
disabled: enabled ? undefined : true,
onchange: function(ev) { onChange(ev.target.checked) },
},
},
{
props: {
className: 'tmfs-checkbox-label',
},
children: label.toString(),
}
],
});
};
var tmfSettingsWindow = null;
var tmfCloseSettings = function() {
if(tmfSettingsWindow === null)
return;
tmfRemoveElement(tmfSettingsWindow);
tmfSettingsWindow = null;
};
var tmfShowSettings = function() {
tmfCloseSettings();
var wnd = tmfCreateWindow('Top Most Friend Settings', 'tmfs-settings', 436, 323),
settings = tmfConfig;
tmfSettingsWindow = wnd.frame;
var hotkeys = tmfCreateFieldset('Hotkeys', 'tmfs-settings-fieldset tmfs-settings-hotkeys'),
flags = tmfCreateFieldset('Flags', 'tmfs-settings-fieldset tmfs-settings-flags'),
blacklist = tmfCreateFieldset('Blacklist', 'tmfs-settings-fieldset tmfs-settings-blacklist');
var hotKeyChar = String.fromCharCode((settings.ForegroundHotKey & 0xFFFF0000) >> 16);
hotkeys.body.appendChild(tmfCreateElement({
props: {
className: 'tmfs-settings-hotkey-label',
},
children: 'Toggle always on top status on active window',
}));
hotkeys.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
id: '_settings_hotkey_key',
type: 'text',
value: hotKeyChar,
className: 'tmfs-settings-hotkey-key',
onkeydown: function(ev) {
var keyCode = (typeof ev.key !== 'undefined')
? ev.key.toUpperCase().charCodeAt(0)
: ev.keyCode;
settings.ForegroundHotKey &= 0xFFFF;
settings.ForegroundHotKey |= keyCode << 16;
ev.target.value = String.fromCharCode(keyCode);
if(ev.preventDefault)
ev.preventDefault();
return false;
},
}
}));
hotkeys.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
id: '_settings_hotkey_ctrl',
type: 'button',
value: 'CTRL',
className: 'tmfs-settings-hotkey-mod tmfs-settings-hotkey-mod-ctrl' + ((settings.ForegroundHotKey & 0x2) ? ' pressed' : ''),
onclick: function(ev) {
if(settings.ForegroundHotKey & 0x2) {
ev.target.className = ev.target.className.replace(' pressed', '');
settings.ForegroundHotKey &= ~0x2;
} else {
ev.target.className += ' pressed';
settings.ForegroundHotKey |= 0x2;
}
},
}
}));
hotkeys.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
id: '_settings_hotkey_alt',
type: 'button',
value: 'ALT',
className: 'tmfs-settings-hotkey-mod tmfs-settings-hotkey-mod-alt' + ((settings.ForegroundHotKey & 0x1) ? ' pressed' : ''),
onclick: function(ev) {
if(settings.ForegroundHotKey & 0x1) {
ev.target.className = ev.target.className.replace(' pressed', '');
settings.ForegroundHotKey &= ~0x1;
} else {
ev.target.className += ' pressed';
settings.ForegroundHotKey |= 0x1;
}
},
}
}));
hotkeys.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
id: '_settings_hotkey_shift',
type: 'button',
value: 'SHIFT',
className: 'tmfs-settings-hotkey-mod tmfs-settings-hotkey-mod-shift' + ((settings.ForegroundHotKey & 0x4) ? ' pressed' : ''),
onclick: function(ev) {
if(settings.ForegroundHotKey & 0x4) {
ev.target.className = ev.target.className.replace(' pressed', '');
settings.ForegroundHotKey &= ~0x4;
} else {
ev.target.className += ' pressed';
settings.ForegroundHotKey |= 0x4;
}
},
}
}));
hotkeys.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
id: '_settings_hotkey_win',
type: 'button',
value: 'WIN',
className: 'tmfs-settings-hotkey-mod tmfs-settings-hotkey-mod-win' + ((settings.ForegroundHotKey & 0x8) ? ' pressed' : ''),
onclick: function(ev) {
if(settings.ForegroundHotKey & 0x8) {
ev.target.className = ev.target.className.replace(' pressed', '');
settings.ForegroundHotKey &= ~0x8;
} else {
ev.target.className += ' pressed';
settings.ForegroundHotKey |= 0x8;
}
},
}
}));
hotkeys.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
type: 'button',
value: 'Reset',
className: 'tmfs-settings-hotkey-reset',
onclick: function(ev) {
settings.ForegroundHotKey = 0;
document.getElementById('_settings_hotkey_key').value = '';
var meow = ['ctrl', 'alt', 'shift', 'win'];
for(var i = 0; i < meow.length; ++i) {
var mewow = document.getElementById('_settings_hotkey_' + meow[i]);
mewow.className = mewow.className.replace(' pressed', '');
}
},
}
}));
flags.body.appendChild(tmfCreateCheckbox('tmfs-settings-checkbox tmfs-settings-checkbox-admin', 'Always run as administrator', settings.RunAsAdministrator, true, function(state) { settings.RunAsAdministrator = state; }));
flags.body.appendChild(tmfCreateCheckbox('tmfs-settings-checkbox tmfs-settings-checkbox-hotkey', 'Show notification when using toggle hotkey', settings.ShowNotificationOnHotKey, true, function(state) { settings.ShowNotificationOnHotKey = state; }));
flags.body.appendChild(tmfCreateCheckbox('tmfs-settings-checkbox tmfs-settings-checkbox-shiftclick', 'SHIFT+CLICK items in the list to add to the title blacklist', settings.ShiftClickToBlacklist, true, function(state) { settings.ShiftClickToBlacklist = state; }));
flags.body.appendChild(tmfCreateCheckbox('tmfs-settings-checkbox tmfs-settings-checkbox-icon', 'Show icon of window affected by hotkey', settings.ShowHotkeyIcon, true, function(state) { settings.ShowHotkeyIcon = state; }));
flags.body.appendChild(tmfCreateCheckbox('tmfs-settings-checkbox tmfs-settings-checkbox-list', 'Show list of open windows in the task bar context menu', settings.ShowWindowList, false, function(state) { settings.ShowWindowList = state; }));
blacklist.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
type: 'button',
value: 'Manage...',
className: 'tmfs-settings-button tmfs-settings-blacklist-button',
onclick: function() {
tmfShowBlacklist();
},
},
}));
wnd.body.appendChild(hotkeys.frame);
wnd.body.appendChild(flags.frame);
wnd.body.appendChild(blacklist.frame);
wnd.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
type: 'button',
className: 'tmfs-settings-button tmfs-settings-button-ok',
value: 'OK',
onclick: function() {
tmfConfig = settings;
tmfCloseSettings();
},
}
}));
wnd.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
type: 'button',
className: 'tmfs-settings-button tmfs-settings-button-cancel',
value: 'Cancel',
onclick: function() {
tmfCloseSettings();
},
}
}));
wnd.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
type: 'button',
className: 'tmfs-settings-button tmfs-settings-button-apply',
value: 'Apply',
onclick: function() {
tmfConfig = settings;
},
}
}));
//tmfShowBlacklist();
};
var tmfBlacklistWindow = null;
var tmfCloseBlacklist = function() {
if(tmfBlacklistWindow === null)
return;
tmfRemoveElement(tmfBlacklistWindow);
tmfBlacklistWindow = null;
};
var tmfShowBlacklist = function() {
tmfCloseBlacklist();
var wnd = tmfCreateWindow('Title Blacklist', 'tmfs-blacklist', 418, 230),
blacklist = tmfConfig.TitleBlacklist,
listView = tmfCreateElement({
tag: 'select',
props: {
className: 'tmfs-blacklist-list',
size: 15,
},
});
tmfBlacklistWindow = wnd.frame;
wnd.body.appendChild(listView);
var refreshList = function() {
listView.innerHTML = '';
for(var i = 0; i < blacklist.length; ++i)
listView.appendChild(tmfCreateElement({
tag: 'option',
children: blacklist[i].toString(),
}));
};
refreshList();
wnd.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
type: 'button',
className: 'tmfs-blacklist-button tmfs-blacklist-button-add',
value: 'Add',
onclick: function() {
var title = prompt('Add new entry...');
if(title && blacklist.indexOf(title) < 0)
blacklist.push(title);
refreshList();
},
},
}));
wnd.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
type: 'button',
className: 'tmfs-blacklist-button tmfs-blacklist-button-edit',
value: 'Edit',
onclick: function() {
var selected = blacklist.indexOf(listView.value);
if(selected < 0)
return;
var title = prompt('Editing ' + listView.value + '...');
if(title && blacklist.indexOf(title) < 0) {
blacklist.splice(selected, 1);
blacklist.push(title);
}
refreshList();
},
},
}));
wnd.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
type: 'button',
className: 'tmfs-blacklist-button tmfs-blacklist-button-remove',
value: 'Remove',
onclick: function() {
var selected = blacklist.indexOf(listView.value);
if(selected < 0)
return;
blacklist.splice(selected, 1);
refreshList();
},
},
}));
wnd.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
type: 'button',
className: 'tmfs-blacklist-button tmfs-blacklist-button-done',
value: 'Done',
onclick: function() {
tmfConfig.TitleBlacklist = blacklist;
tmfCloseBlacklist();
},
},
}));
wnd.body.appendChild(tmfCreateElement({
tag: 'input',
props: {
type: 'button',
className: 'tmfs-blacklist-button tmfs-blacklist-button-cancel',
value: 'Cancel',
onclick: function() {
tmfCloseBlacklist();
},
},
}));
};
var tmfConfig = {
ForegroundHotKey: 0,
RunAsAdministrator: false,
ShowNotificationOnHotKey: true,
ShiftClickToBlacklist: true,
ShowHotkeyIcon: true,
ShowWindowList: false,
TitleBlacklist: [
'Start',
'Program Manager',
'Windows Shell Experience Host',
],
};
tmfOnReady(function(ev) {
var rect = tmfClientRectangle();
if(rect[1] > rect[0]) // height is larger than width, we're presemably running on a phone
return;
var clock = tmfCreateElement({
props: { className: 'tmfs-clock' },
children: tmfTimeString(),
});
tmfSysIcon = tmfCreateElement({
tag: 'img',
props: {
className: 'tmfs-icon',
alt: 'TopMostFriend',
title: 'Top Most Application Manager',
src: './icon.gif',
},
});
var taskbar = tmfCreateElement({
props: { className: 'tmfs' },
children: {
props: { className: 'tmfs-inner' },
children: [
{
props: { className: 'tmfs-left' },
children: {
props: { className: 'tmfs-start' },
children: [
{
tag: 'img',
props: {
alt: '',
src: './start.gif',
},
},
'Start',
],
},
},
{
props: { className: 'tmfs-right' },
children: {
props: { className: 'tmfs-systray' },
children: [
tmfSysIcon,
clock,
],
},
},
{ props: { className: 'tmf-clear' } },
]
},
});
document.getElementById('_tmf').style.paddingBottom = '30px';
document.body.appendChild(taskbar);
/*tmfBindEvent(tmfSysIcon, 'click', function(ev) {
if(ev.shiftKey)
return true;
tmfShowCtxMenu(ev.clientX, ev.clientY);
if(ev.preventDefault)
ev.preventDefault();
return false;
});*/
tmfBindEvent(tmfSysIcon, 'contextmenu', function(ev) {
if(ev.shiftKey)
return true;
tmfShowCtxMenu(ev.clientX, ev.clientY);
if(ev.preventDefault)
ev.preventDefault();
return false;
});
tmfBindEvent(document, 'mousemove', tmfDragHandler);
tmfBindEvent(document, 'mouseup', tmfStopDragging);
setInterval(function() {
tmfSetElemText(clock, tmfTimeString());
}, 1000);
});