Ported array and html funcs from Misuzu.

This commit is contained in:
flash 2025-02-20 19:19:55 +00:00
parent d6a6683bfa
commit 4638c60af4
35 changed files with 441 additions and 535 deletions

View file

@ -14,7 +14,8 @@ const exec = require('util').promisify(require('child_process').exec);
debug: isDebug,
swc: {
es: 'es5',
jsx: 'er',
jsx: '$element',
jsxf: '$fragment',
},
housekeep: [
pathJoin(__dirname, 'public', 'assets'),

11
public/polyfill/symbol.js Normal file

File diff suppressed because one or more lines are too long

View file

@ -23,6 +23,7 @@
</div>
</div>
</noscript>
<script src="{ami.js}" type="text/javascript" charset="utf-8"></script>
<script src="/polyfill/symbol.js" type="text/javascript"></script>
<script src="{ami.js}" type="text/javascript"></script>
</body>
</html>

27
src/ami.js/array.js Normal file
View file

@ -0,0 +1,27 @@
const $arrayRemoveAt = function(array, index) {
array.splice(index, 1);
};
const $arrayRemoveValue = function(array, item) {
let index;
while(array.length > 0 && (index = array.indexOf(item)) >= 0)
$arrayRemoveAt(array, index);
};
const $arrayRemoveAny = function(array, predicate) {
let index;
while(array.length > 0 && (index = array.findIndex(predicate)) >= 0)
$arrayRemoveAt(array, index);
};
const $arrayShuffle = function(array) {
if(array.length < 2)
return;
for(let i = array.length - 1; i > 0; --i) {
const j = Math.floor(Math.random() * (i + 1));
const tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
};

View file

@ -1,21 +1,16 @@
#include utility.js
var AmiOptionButtons = function(parent) {
var container = $e({ attrs: { id: 'bbCodeContainer' } }),
buttons = new Map;
var container = $element('div', { id: 'bbCodeContainer' });
var buttons = new Map;
parent.appendChild(container);
var createBtn = function(name, title, languageKey, style, onclick) {
var pub = {};
var elem = $e({
tag: 'input',
attrs: {
type: 'button',
name: typeof languageKey === 'string' ? languageKey : ';;',
value: title,
style: style,
onclick: function(ev) { performClick(ev); },
},
var elem = $element('input', {
type: 'button',
name: typeof languageKey === 'string' ? languageKey : ';;',
value: title,
style: style,
onclick: function(ev) { performClick(ev); },
});
var hide = function() { elem.classList.add('hidden'); };
@ -62,7 +57,7 @@ var AmiOptionButtons = function(parent) {
},
clear: function() {
buttons.clear();
$rc(container);
$removeChildren(container);
},
hide: hide,
show: show,

View file

@ -8,10 +8,9 @@
#include status.js
#include submitbox.js
#include title.js
#include utility.js
var AmiChat = function(chat, title, parent) {
var container = $e({ attrs: { id: 'chat' } });
var container = $element('div', { id: 'chat' });
var pub = {
getElement: function() { return container; },
@ -76,7 +75,7 @@ var AmiChat = function(chat, title, parent) {
pub.appendTo(parent);
optionIcons.create('unembed', 'Unembed any embedded media', 'unembed', function() {
var buttons = $c('js-unembed-btn');
var buttons = $queryAll('.js-unembed-btn');
while(buttons.length > 0)
buttons[0].click();
});

View file

@ -1,10 +1,9 @@
#include colour.js
#include utility.js
#include colpick/picker.jsx
var AmiColourPicker = function(parent) {
var container = $e({ attrs: { id: 'pickerNew', className: 'hidden' } }),
callback = undefined;
var container = $element('div', { id: 'pickerNew', className: 'hidden' });
var callback = undefined;
parent.appendChild(container);
var picker = new FwColourPicker(

View file

@ -1,5 +1,3 @@
#include utility.js
if(!('WebSocket' in window) && 'MozWebSocket' in window)
window.WebSocket = window.MozWebSocket;
@ -35,8 +33,8 @@ if(!('Map' in window))
var index = keys.indexOf(key);
if(key < 0) return false;
$ar(keys, index);
$ar(values, index);
$arrayRemoveAt(keys, index);
$arrayRemoveAt(values, index);
--obj.size;
};

View file

@ -1,7 +1,5 @@
#include utility.js
var AmiCopyright = function(parent) {
var container = $e({ attrs: { id: 'copyright' } });
var container = $element('div', { id: 'copyright' });
parent.appendChild(container);
return {
@ -13,20 +11,13 @@ var AmiCopyright = function(parent) {
if(typeof section === 'string')
children.push(section);
else if(Array.isArray(section))
children.push({
tag: 'a',
attrs: {
href: section[1],
target: '_blank',
},
child: section[0],
});
children.push($element('a', {
href: section[1],
target: '_blank',
}, section[0]));
}
container.appendChild($e({
tag: 'p',
child: children,
}))
container.appendChild($element('p', {}, ...children));
},
};
};

View file

@ -12,7 +12,6 @@
#include styles.js
#include title.js
#include txtrigs.js
#include utility.js
var AmiContext = function(title, auth, loading) {
var pub = {};

View file

@ -1,23 +1,20 @@
#include watcher.js
var AmiEmoticonList = function(parent) {
var container = $e({ attrs: { id: 'emotes' } }),
watcher = new AmiWatcher;
var container = $element('div', { id: 'emotes' });
var watcher = new AmiWatcher;
parent.appendChild(container);
var clear = function() {
$rc(container);
$removeChildren(container);
};
var add = function(emote) {
container.appendChild($e({
tag: 'img',
attrs: {
src: emote.url,
alt: emote.strings[0],
title: emote.strings[0],
onclick: function() { watcher.call(emote, [emote]); },
},
container.appendChild($element('img', {
src: emote.url,
alt: emote.strings[0],
title: emote.strings[0],
onclick: function() { watcher.call(emote, [emote]); },
}));
};

139
src/ami.js/html.js Normal file
View file

@ -0,0 +1,139 @@
const $id = document.getElementById.bind(document);
const $query = document.querySelector.bind(document);
const $queryAll = document.querySelectorAll.bind(document);
const $text = document.createTextNode.bind(document);
const $insertBefore = function(target, element) {
target.parentNode.insertBefore(element, target);
};
const $appendChild = function(element, child) {
switch(typeof child) {
case 'undefined':
break;
case 'string':
element.appendChild($text(child));
break;
case 'function':
$appendChild(element, child());
break;
case 'object':
if(child === null)
break;
if(child instanceof Node)
element.appendChild(child);
else if(child?.element instanceof Node)
element.appendChild(child.element);
else if(typeof child?.toString === 'function')
element.appendChild($text(child.toString()));
break;
default:
element.appendChild($text(child.toString()));
break;
}
};
const $appendChildren = function(element, ...children) {
for(const child of children)
$appendChild(element, child);
};
const $removeChildren = function(element) {
while(element.lastChild)
element.removeChild(element.lastChild);
};
const $fragment = function(props, ...children) {
const fragment = document.createDocumentFragment();
$appendChildren(fragment, ...children);
return fragment;
};
const $element = function(type, props, ...children) {
if(typeof type === 'function')
return new type(props ?? {}, ...children);
const element = document.createElement(type ?? 'div');
if(props)
for(let key in props) {
const prop = props[key];
if(prop === undefined || prop === null)
continue;
switch(typeof prop) {
case 'function':
if(key.substring(0, 2) === 'on')
key = key.substring(2).toLowerCase();
element.addEventListener(key, prop);
break;
case 'object':
if(prop instanceof Array) {
if(key === 'class')
key = 'classList';
const attr = element[key];
let addFunc = null;
if(attr instanceof Array)
addFunc = attr.push.bind(attr);
else if(attr instanceof DOMTokenList)
addFunc = attr.add.bind(attr);
if(addFunc !== null) {
for(let j = 0; j < prop.length; ++j)
addFunc(prop[j]);
} else {
if(key === 'classList')
key = 'class';
element.setAttribute(key, prop.toString());
}
} else {
if(key === 'class' || key === 'className')
key = 'classList';
let setFunc = null;
if(element[key] instanceof DOMTokenList)
setFunc = (ak, av) => { if(av) element[key].add(ak); };
else if(element[key] instanceof CSSStyleDeclaration)
setFunc = (ak, av) => {
if(ak.indexOf('-') >= 0)
element[key].setProperty(ak, av, '');
else
element[key][ak] = av;
};
else
setFunc = (ak, av) => { element[key][ak] = av; };
for(const attrKey in prop) {
const attrValue = prop[attrKey];
if(attrValue)
setFunc(attrKey, attrValue);
}
}
break;
case 'boolean':
if(prop)
element.setAttribute(key, '');
break;
default:
if(key === 'className')
key = 'class';
element.setAttribute(key, prop.toString());
break;
}
}
$appendChildren(element, ...children);
return element;
};

View file

@ -1,21 +1,14 @@
#include utility.js
#include watcher.js
var AmiInputBox = function(parent) {
var watchers = new AmiWatcherCollection,
input = $e({
tag: 'textarea',
attrs: {
cols: '2',
id: 'message',
autofocus: 'autofocus',
maxlength: '0',
},
}),
container = $e({
attrs: { id: 'inputFieldContainer' },
child: input,
});
var watchers = new AmiWatcherCollection;
var input = $element('textarea', {
cols: '2',
id: 'message',
autofocus: 'autofocus',
maxlength: '0',
});
var container = $element('div', { id: 'inputFieldContainer' }, input);
parent.appendChild(container);
@ -145,7 +138,7 @@ var AmiInputBox = function(parent) {
if(split[0] === value)
input.style[name] = null;
} else if(split.length > 1) {
$ari(split, value);
$arrayRemoveValue(split, value);
input.style[name] = split.join(' ');
}
}

View file

@ -1,23 +1,23 @@
#include utility.js
var AmiLoadingOverlay = function(parent, indicatorShown) {
var text = $e({
attrs: { id: 'conntxt' },
child: 'Loading Sock Chat...',
});
var indicator = $e({ attrs: { id: 'indicator' } });
var container = $e({
attrs: { id: 'connmsg' },
child: {
attrs: { id: 'info' },
child: [text, indicator],
},
});
var text = $element(
'div',
{ id: 'conntxt' },
'Loading Sock Chat...',
);
var indicator = $element('div', { id: 'indicator' });
var container = $element(
'div',
{ id: 'connmsg' },
$element(
'div',
{ id: 'info' },
text,
indicator
),
);
var appendTo = function(parent) { parent.appendChild(container); };
var destroy = function() { $r(container); };
var destroy = function() { container.parentNode.removeChild(container); };
var showIndicator = function() { indicator.classList.remove('hidden'); };
var hideIndicator = function() { indicator.classList.add('hidden'); };

View file

@ -1,6 +1,9 @@
#vars self build
#include compat.js
#include array.js
#include html.js
#include common.js
#include ctx.js
#include loadoverlay.js

View file

@ -1,11 +1,10 @@
#include utility.js
#include watcher.js
var AmiMessageList = function(parent) {
var container = $e({ attrs: { id: 'chatList', className: 'fullWidth' } }),
isEven = true,
idPfx = 'sock_msg_',
watchers = new AmiWatcherCollection;
var container = $element('div', { id: 'chatList', className: 'fullWidth' });
var isEven = true;
var idPfx = 'sock_msg_';
var watchers = new AmiWatcherCollection;
parent.appendChild(container);
watchers.define(['nameInsert', 'delete']);
@ -29,90 +28,80 @@ var AmiMessageList = function(parent) {
var nameBody = msgInfo.sender.username;
if(msgInfo.sender.isBot())
nameBody = {
tag: 'span',
attrs: { className: 'botName' },
child: nameBody,
};
nameBody = $element(
'span',
{ className: 'botName' },
nameBody,
);
var messageBody = [
{
tag: 'span',
attrs: { className: 'date' },
child: '(' + msgInfo.created.toLocaleTimeString() + ')',
},
$element(
'span',
{ className: 'date' },
'(' + msgInfo.created.toLocaleTimeString() + ')',
),
' ',
{
tag: 'span',
attrs: {
style: nameStyle,
onclick: function() {
watchers.call('nameInsert', msgInfo, [msgInfo]);
},
$element('span', {
style: nameStyle,
onclick: function() {
watchers.call('nameInsert', msgInfo, [msgInfo]);
},
child: nameBody,
},
}, nameBody),
];
if(msgInfo.showColon)
messageBody.push({
tag: 'span',
attrs: { className: 'msgColon' },
child: ':',
});
messageBody.push($element(
'span',
{ className: 'msgColon' },
':',
));
if(msgInfo.isAction) {
if(msgInfo.bodyText.indexOf("'") !== 0 || (msgInfo.bodyText.match(/\'/g).length % 2) === 0)
messageBody.push(' ');
} else {
messageBody.push(' ');
messageBody.push({
tag: 'span',
attrs: { className: 'msgBreak' },
child: { tag: 'br' },
});
messageBody.push($element(
'span',
{ className: 'msgBreak' },
$element('br'),
));
}
if(msgInfo.isPM) {
if(msgInfo.pmTargetName)
messageBody.push({
tag: 'i',
child: AmiStrings.getMenuString('whisperto', msgInfo.pmTargetName),
});
messageBody.push($element(
'i', {},
AmiStrings.getMenuString('whisperto', msgInfo.pmTargetName),
));
else
messageBody.push({
tag: 'i',
child: AmiStrings.getMenuString('whisper'),
});
messageBody.push($element(
'i', {},
AmiStrings.getMenuString('whisper'),
));
messageBody.push(' ');
}
var message = $e({
attrs: {
id: idPfx + msgInfo.id,
className: isEven ? 'rowEven' : 'rowOdd'
},
child: messageBody,
});
var message = $element('div', {
id: idPfx + msgInfo.id,
className: isEven ? 'rowEven' : 'rowOdd'
}, ...messageBody);
let msgBodyTarget = message;
if(msgInfo.isAction)
message.appendChild(msgBodyTarget = $e({ tag: 'i' }));
message.appendChild(msgBodyTarget = $element('i'));
msgBodyTarget.insertAdjacentHTML('beforeend', msgInfo.bodyRaw);
if(msgInfo.canDelete)
message.appendChild($e({
tag: 'a',
attrs: {
title: 'Delete this message',
className: 'sprite-small sprite-delete',
style: {
float: 'right',
margin: '2px 0 0 0',
},
onclick: function() {
watchers.call('delete', msgInfo, [msgInfo]);
},
message.appendChild($element('a', {
title: 'Delete this message',
className: 'sprite-small sprite-delete',
style: {
float: 'right',
margin: '2px 0 0 0',
},
onclick: function() {
watchers.call('delete', msgInfo, [msgInfo]);
},
}));
@ -122,11 +111,13 @@ var AmiMessageList = function(parent) {
return message;
},
remove: function(msgId) {
$ri(idPfx + msgId);
const elem = $id(idPfx + msgId);
if(elem)
elem.parentNode.removeChild(elem);
reflow();
},
clear: function() {
$rc(container);
$removeChildren(container);
isEven = true;
},
reflow: reflow,

View file

@ -1,20 +1,15 @@
#include utility.js
var AmiOptionIcons = function(parent) {
var container = $e({ attrs: { id: 'optionsContainer' } }),
icons = new Map;
var container = $element('div', { id: 'optionsContainer' });
var icons = new Map;
parent.appendChild(container);
var createIcon = function(name, title, icon, onclick, enabled) {
var pub = {};
var elem = $e({
tag: 'a',
attrs: {
href: 'javascript:void(0);',
title: title,
className: 'optIcon sprite sprite-' + icon,
onclick: function(ev) { performClick(ev); },
},
var elem = $element('a', {
href: 'javascript:void(0);',
title: title,
className: 'optIcon sprite sprite-' + icon,
onclick: function(ev) { performClick(ev); },
});
var hasState = typeof enabled === 'boolean';
@ -61,7 +56,7 @@ var AmiOptionIcons = function(parent) {
},
clear: function() {
icons.clear();
$rc(container);
$removeChildren(container);
},
};
};

View file

@ -1,5 +1,3 @@
#include utility.js
var AmiReconnecter = function(parent) {
var handler = new AmiReconnectHandler,
indicator = new AmiReconnectIndicator(parent, handler);
@ -128,47 +126,35 @@ var AmiReconnectHandler = function() {
};
var AmiReconnectIndicator = function(parent, handler) {
var counterTime = $e({
tag: 'span',
attrs: {
id: 'reconnectCounterTime',
},
child: '0.0',
});
var counterBody = $e({
attrs: {
var counterTime = $element('span', { id: 'reconnectCounterTime' }, '0.0');
var counterBody = $element(
'div', {
id: 'reconnectCounter',
className: 'hidden',
},
child: ['Reconnecting in ', counterTime, ' seconds.'],
});
'Reconnecting in ', counterTime, ' seconds.'
);
var connectEllipsis = $e({
tag: 'span',
attrs: {
id: 'reconnectConnectEllipsis',
},
child: '...',
});
var connectBody = $e({
attrs: {
var connectEllipsis = $element('span', { id: 'reconnectConnectEllipsis' }, '...');
var connectBody = $element(
'div',
{
id: 'reconnectConnect',
className: 'hidden',
},
child: ['Attempting to reconnect', connectEllipsis],
});
'Attempting to reconnect', connectEllipsis,
);
var body = $e({
attrs: {
var body = $element(
'div',
{
id: 'reconnectIndicator',
className: 'hidden',
},
child: [
{ child: 'WARNING: Connection Problem' },
counterBody,
connectBody,
],
});
$element('div', {}, 'WARNING: Connection Problem'),
counterBody,
connectBody,
);
parent.appendChild(body);

View file

@ -1,11 +1,10 @@
#include common.js
#include utility.js
var AmiServers = function() {
var servers = futami.get('servers').slice(0),
index = 0xFFFF;
$as(servers);
$arrayShuffle(servers);
return {
getServer: function(callback) {

View file

@ -1,5 +1,4 @@
#include cookies.js
#include utility.js
#include watcher.js
// really need to replace null with undefined where possible, in mami too
@ -47,7 +46,7 @@ var AmiSettings = function() {
else AmiCookies.removeCookie(cookieName);
callWatchers();
$ari(locked, name);
$arrayRemoveValue(locked, name);
};
var setValue = function(value) {
@ -68,7 +67,7 @@ var AmiSettings = function() {
else AmiCookies.setCookie(cookieName, value);
callWatchers();
$ari(locked, name);
$arrayRemoveValue(locked, name);
};
pub.getName = function() { return name; };
@ -113,7 +112,7 @@ var AmiSettings = function() {
else AmiCookies.setCookie(cookieName, value);
callWatchers();
$ari(locked, name);
$arrayRemoveValue(locked, name);
};
pub.watch = function(watcher) {

View file

@ -1,4 +1,3 @@
#include utility.js
#include watcher.js
var AmiSidebars = function(container) {
@ -21,14 +20,15 @@ var AmiSidebars = function(container) {
var classes = ['sidebar', 'hidden'];
if(wide) classes.push('widebar');
var titleElem = $e({ attrs: { className: 'top' } }),
elem = $e({
attrs: {
id: name,
classList: classes,
},
child: [titleElem, body],
});
var titleElem = $element('div', { className: 'top' });
var elem = $element(
'div',
{
id: name,
classList: classes,
},
titleElem, body,
);
var hide = function() {
elem.classList.add('hidden');

View file

@ -1,9 +1,7 @@
#include utility.js
var AmiChannelsSidebar = function() {
var sbName = 'chanList',
body = $e(),
activeChannel = undefined;
var sbName = 'chanList';
var body = $element('div');
var activeChannel = undefined;
var setTitle;
var rowEven = false;
@ -23,16 +21,14 @@ var AmiChannelsSidebar = function() {
return str;
};
var nameElem = $e({
attrs: { style: { display: 'black' } },
child: toString(),
}),
elem = $e({
attrs: {
className: (rowEven ? 'rowEven' : 'rowOdd'),
},
child: [nameElem],
});
var nameElem = $element(
'div',
{ style: { display: 'black' } },
toString(),
);
var elem = $element('div', {
className: (rowEven ? 'rowEven' : 'rowOdd'),
}, nameElem);
rowEven = !rowEven;

View file

@ -1,10 +1,9 @@
#include strings.js
#include utility.js
var AmiHelpSidebar = function() {
var sbName = 'helpList',
list = $e({ tag: 'table' }),
body = $e({ child: list });
var sbName = 'helpList';
var list = $element('table');
var body = $element('div', {}, list);
var setTitle;
@ -35,7 +34,7 @@ var AmiHelpSidebar = function() {
title.textContent = helpInfo.title + ':';
var example = row.insertCell(1);
example.appendChild($e({ tag: 'i', child: helpInfo.format }));
example.appendChild($element('i', {}, helpInfo.format));
rowEven = !rowEven;
});

View file

@ -1,8 +1,6 @@
#include utility.js
var AmiSettingsSidebar = function() {
var sbName = 'settingsList',
body = $e({ child: { tag: 'table' } });
var sbName = 'settingsList';
var body = $element('div', {}, $element('table'));
var setTitle;

View file

@ -1,42 +1,26 @@
#include utility.js
var AmiUploadsSidebar = function() {
var sbName = 'uploadList',
body = $e({
child: [
{
attrs: {
className: 'eepromForm',
},
child: [
{
tag: 'input',
attrs: {
id: 'uploadSelector',
type: 'file',
class: 'hidden',
multiple: true,
},
},
{
tag: 'input',
attrs: {
id: 'uploadButton',
type: 'button',
value: 'Select file',
},
},
],
},
{
tag: 'table',
attrs: {
id: 'uploadHistory',
class: 'eepromHistory',
},
},
],
});
var sbName = 'uploadList';
var body = $element(
'div', {},
$element(
'div', { className: 'eepromForm' },
$element('input', {
id: 'uploadSelector',
type: 'file',
class: 'hidden',
multiple: true,
}),
$element('input', {
id: 'uploadButton',
type: 'button',
value: 'Select file',
}),
),
$element('table', {
id: 'uploadHistory',
class: 'eepromHistory',
}),
);
var setTitle;

View file

@ -1,8 +1,6 @@
#include utility.js
var AmiUsersSidebar = function() {
var sbName = 'userList',
body = $e();
var sbName = 'userList';
var body = $element('div');
var setTitle;

View file

@ -1,5 +1,3 @@
#include utility.js
var AmiSound = function() {
var playing = [];
var isMuted = false,
@ -74,7 +72,7 @@ var AmiSound = function() {
};
(function() {
var elem = $e('audio');
var elem = $element('audio');
for(var name in formats) {
var format = formats[name],
support = elem.canPlayType(format);
@ -128,10 +126,7 @@ var AmiSound = function() {
if(rate === undefined) rate = 1.0;
else rate = Math.min(4.0, Math.max(0.25, rate));
var audio = $e({
tag: 'audio',
attrs: { src: url },
});
var audio = $element('audio', { src: url });
audio.volume = Math.max(0.0, Math.min(1.0, volume * localVolume));
audio.muted = isMuted;
audio.preservesPitch = false;
@ -139,7 +134,7 @@ var AmiSound = function() {
playing.push(audio);
audio.addEventListener('ended', function() {
$ari(playing, audio);
$arrayRemoveValue(playing, audio);
});
audio.addEventListener('loadeddata', function() {

View file

@ -1,7 +1,5 @@
#include utility.js
var AmiStatusIndicator = function(parent) {
var icon = $e({ attrs: { id: 'statusIconContainer' } });
var icon = $element('div', { id: 'statusIconContainer' });
parent.appendChild(icon);
var setState = function(colour, text) {

View file

@ -1,43 +1,32 @@
#include utility.js
#include watcher.js
var AmiSubmitBox = function(parent) {
var pub = {},
watcher = new AmiWatcher,
maxLengthValue = 0,
click = function(ev) {
watcher.call(pub, [ev]);
};
var pub = {};
var watcher = new AmiWatcher;
var maxLengthValue = 0;
var click = function(ev) {
watcher.call(pub, [ev]);
};
var button = $e({
tag: 'input',
attrs: {
type: 'button',
value: 'Send',
id: 'sendmsg',
onclick: function(ev) { click(ev); },
},
}),
curLength = $e({
tag: 'span',
child: '0',
}),
maxLength = $e({
tag: 'span',
child: maxLengthValue.toString(),
}),
container = $e({
attrs: { id: 'submitButtonContainer' },
child: [
{
tag: 'span',
attrs: { id: 'messageLengthCounter' },
child: [curLength, '/', maxLength],
},
' ',
button,
],
});
var button = $element('input', {
type: 'button',
value: 'Send',
id: 'sendmsg',
onclick: function(ev) { click(ev); },
});
var curLength = $element('span', {}, '0');
var maxLength = $element('span', {}, maxLengthValue.toString());
var container = $element(
'div',
{ id: 'submitButtonContainer' },
$element(
'span',
{ id: 'messageLengthCounter' },
curLength, '/', maxLength
),
' ',
button,
);
parent.appendChild(container);

View file

@ -1,8 +1,7 @@
#include common.js
#include utility.js
var AmiChatTitle = function(parent, title) {
var elem = $e({ attrs: { id: 'chatTitle' }, child: title});
var elem = $element('div', { id: 'chatTitle' }, title);
parent.appendChild(elem);
return {
@ -13,8 +12,8 @@ var AmiChatTitle = function(parent, title) {
};
var AmiWindowTitle = function(title) {
var baseTitle = '',
activeFlash = undefined;
var baseTitle = '';
var activeFlash = undefined;
var setTitle = function(text) {
document.title = text;

View file

@ -5,7 +5,6 @@
#include ts_utils.js
#include title.js
#include strings.js
#include utility.js
var UI = (function () {
function UI() {}
@ -252,7 +251,7 @@ var UI = (function () {
msgDiv.id = "sock_user_" + u.id;
msgDiv.innerHTML = "<a style='color:" + u.color + "; display: block;' href='javascript:UI.ToggleUserMenu(" + u.id + ");'>" + u.username + "</a>";
msgDiv.appendChild(UI.GenerateContextMenu(u));
$i('userList').getElementsByClassName('body')[0].appendChild(msgDiv);
$id('userList').getElementsByClassName('body')[0].appendChild(msgDiv);
this.rowEven[1] = !this.rowEven[1];
}
if (addToContext) {
@ -281,54 +280,53 @@ var UI = (function () {
};
UI.SwitchChannel = function(name) {
var channels = $c('js-sidebar-channel');
var channels = $queryAll('.js-sidebar-channel');
for(var i = 0; i < channels.length; ++i) {
var channel = channels[i];
if(channel.style.fontWeight === 'bold')
channel.style.fontWeight = null;
}
$i('sock_chan_' + name).style.fontWeight = 'bold';
$id('sock_chan_' + name).style.fontWeight = 'bold';
};
UI.AddChannel = function (name, ispwd, istemp, iscurr) {
var displayName = UI.MakeChannelDisplayName(name, ispwd, istemp);
var html = $e({
attrs: {
var html = $element(
'div',
{
classList: ['js-sidebar-channel', this.rowEven[2] ? "rowEven" : "rowOdd"],
id: 'sock_chan_' + name,
},
child: {
tag: 'a',
child: displayName,
attrs: {
style: { display: 'block' },
href: 'javascript:void(0);',
onclick: function() {
var cmd = '/join ' + name;
if(ispwd && !UserContext.self.canModerate())
cmd += ' ' + prompt(AmiStrings.getMenuString('chanpwd', [name]));
ami.sockChat.sendMessage(cmd);
},
$element('a', {
style: { display: 'block' },
href: 'javascript:void(0);',
onclick: function() {
var cmd = '/join ' + name;
if(ispwd && !UserContext.self.canModerate())
cmd += ' ' + prompt(AmiStrings.getMenuString('chanpwd', [name]));
ami.sockChat.sendMessage(cmd);
},
}
});
}, displayName),
);
if(iscurr)
html.style.fontWeight = 'bold';
$i('chanList').getElementsByClassName('body')[0].appendChild(html);
$id('chanList').getElementsByClassName('body')[0].appendChild(html);
this.rowEven[2] = !this.rowEven[2];
};
UI.ModifyChannel = function (oldname, newname, ispwd, istemp) {
var displayName = UI.MakeChannelDisplayName(newname, ispwd, istemp);
$i('sock_chat_' + oldname).children[0].textContent = displayName;
$id('sock_chat_' + oldname).children[0].textContent = displayName;
};
UI.RemoveChannel = function (name) {
$ri('sock_chat_' + oldname);
const elem = $id('sock_chat_' + oldname);
if(elem)
elem.parentNode.removeChild(elem);
};
UI.RemoveUser = function (id) {
@ -337,14 +335,14 @@ var UI = (function () {
};
UI.RedrawChannelList = function() {
$i('chanList').getElementsByClassName('top')[0].innerHTML = AmiStrings.getMenuString('chans');
$i('chanList').getElementsByClassName('body')[0].innerHTML = '';
$id('chanList').getElementsByClassName('top')[0].innerHTML = AmiStrings.getMenuString('chans');
$id('chanList').getElementsByClassName('body')[0].innerHTML = '';
this.rowEven[2] = false;
};
UI.RedrawUserList = function () {
$i('userList').getElementsByClassName('top')[0].innerHTML = AmiStrings.getMenuString('online');
$i('userList').getElementsByClassName('body')[0].innerHTML = '';
$id('userList').getElementsByClassName('top')[0].innerHTML = AmiStrings.getMenuString('online');
$id('userList').getElementsByClassName('body')[0].innerHTML = '';
this.rowEven[1] = false;
if(UserContext.self !== undefined)
this.AddUser(UserContext.self, false);

View file

@ -1,7 +1,6 @@
#include ts_20_ui.js
#include ts_10_user.js
#include z_eepromv1.js
#include utility.js
#include sidebars/channelssb.js
#include sidebars/helpsb.js
#include sidebars/settingssb.js
@ -17,14 +16,10 @@ var Chat = (function () {
type: "select",
load: function(input) {
ami.styles.forEach(function(style) {
input.appendChild($e({
tag: 'option',
child: style.getTitle(),
attrs: {
value: style.getName(),
className: style.getOptionClass(),
},
}));
input.appendChild($element('option', {
value: style.getName(),
className: style.getOptionClass(),
}, style.getTitle()));
if(style.isDefault() && !ami.settings.has('style'))
ami.settings.set('style', style.getName());
@ -475,7 +470,7 @@ var Chat = (function () {
ami.settings.set('soundPack', sounds.packs[0].name);
}
var soundPackSetting = $i('chatSetting-spack');
var soundPackSetting = $id('chatSetting-spack');
if(soundPackSetting) {
while(soundPackSetting.options.length > 0)
soundPackSetting.options.remove(0);

View file

@ -1,163 +0,0 @@
window.$i = document.getElementById.bind(document);
window.$c = document.getElementsByClassName.bind(document);
window.$q = document.querySelector.bind(document);
window.$qa = document.querySelectorAll.bind(document);
window.$t = document.createTextNode.bind(document);
window.$r = function(element) {
if(element && element.parentNode)
element.parentNode.removeChild(element);
};
window.$ri = function(name) {
$r($i(name));
};
window.$ib = function(ref, elem) {
ref.parentNode.insertBefore(elem, ref);
};
window.$rc = function(element) {
while(element.lastChild)
element.removeChild(element.lastChild);
};
window.$e = function(info, attrs, child, created) {
info = info || {};
if(typeof info === 'string') {
info = {tag: info};
if(attrs)
info.attrs = attrs;
if(child)
info.child = child;
if(created)
info.created = created;
}
var elem = document.createElement(info.tag || 'div');
if(info.attrs) {
var attrs = info.attrs,
keys = Object.keys(attrs);
for(var key in attrs) {
var attr = attrs[key];
if(attr === undefined || attr === null)
continue;
switch(typeof attr) {
case 'function':
if(key.substring(0, 2) === 'on')
key = key.substring(2).toLowerCase();
elem.addEventListener(key, attr);
break;
case 'object':
if(attr instanceof Array) {
if(key === 'class')
key = 'classList';
var addFunc = null,
prop = elem[key];
if(prop instanceof Array)
addFunc = prop.push.bind(prop);
else if(prop instanceof DOMTokenList)
addFunc = prop.add.bind(prop);
if(addFunc !== null) {
for(var j = 0; j < attr.length; ++j)
addFunc(attr[j]);
} else {
if(key === 'classList')
key = 'class';
elem.setAttribute(key, attr.toString());
}
} else {
for(var attrKey in attr)
elem[key][attrKey] = attr[attrKey];
}
break;
case 'boolean':
if(attr)
elem.setAttribute(key, '');
break;
default:
if(key === 'className')
key = 'class';
elem.setAttribute(key, attr.toString());
break;
}
}
}
if(info.child) {
var children = info.child;
if(!Array.isArray(children))
children = [children];
for(var i in children) {
var child = children[i];
switch(typeof child) {
case 'string':
elem.appendChild($t(child));
break;
case 'object':
if(child instanceof Element)
elem.appendChild(child);
else if(child.getElement) {
var childElem = child.getElement();
if(childElem instanceof Element)
elem.appendChild(childElem);
else
elem.appendChild($e(child));
} else
elem.appendChild($e(child));
break;
default:
elem.appendChild($t(child.toString()));
break;
}
}
}
if(info.created)
info.created(elem);
return elem;
};
window.$er = (type, props, ...children) => $e({ tag: type, attrs: props, child: children });
window.$ar = function(array, index) {
array.splice(index, 1);
};
window.$ari = function(array, item) {
var index;
while(array.length > 0 && (index = array.indexOf(item)) >= 0)
$ar(array, index);
};
window.$arf = function(array, predicate) {
var index;
while(array.length > 0 && (index = array.findIndex(predicate)) >= 0)
$ar(array, index);
};
window.$as = function(array) {
if(array.length < 2)
return;
for(var i = array.length - 1; i > 0; --i) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
};

View file

@ -1,5 +1,3 @@
#include utility.js
var AmiWatcher = function() {
var watchers = [];
@ -26,7 +24,7 @@ var AmiWatcher = function() {
}
},
unwatch: function(watcher) {
$ari(watchers, watcher);
$arrayRemoveValue(watchers, watcher);
},
call: function(thisArg, args) {
if(!Array.isArray(args)) {

View file

@ -1,6 +1,5 @@
#include common.js
#include eeprom.js
#include utility.js
var eepromAppl = 1,
eepromSupportImageEmbed = true,
@ -10,13 +9,13 @@ var eepromInitialise = function(auth) {
window.eepromHistory = {};
window.eepromClient = new AmiEEPROM(futami.get('eeprom2'), auth.getHttpAuth);
window.eepromUploadsTable = $i('uploadHistory');
$i('uploadSelector').onchange = function() {
window.eepromUploadsTable = $id('uploadHistory');
$id('uploadSelector').onchange = function() {
for(var i = 0; i < this.files.length; ++i)
eepromFileUpload(this.files[i]);
};
$i('uploadButton').onclick = function() {
$i('uploadSelector').click();
$id('uploadButton').onclick = function() {
$id('uploadSelector').click();
};
ami.chat.inputBox.watch('paste', function(ev) {