misuzu/assets/misuzu.js/forum/editor.js

437 lines
19 KiB
JavaScript

#include forum/forum.js
Misuzu.Forum.Editor = {};
Misuzu.Forum.Editor.allowWindowClose = false;
Misuzu.Forum.Editor.init = function() {
const postingForm = $q('.js-forum-posting');
if(!postingForm)
return;
const postingButtons = postingForm.querySelector('.js-forum-posting-buttons'),
postingText = postingForm.querySelector('.js-forum-posting-text'),
postingParser = postingForm.querySelector('.js-forum-posting-parser'),
postingPreview = postingForm.querySelector('.js-forum-posting-preview'),
postingMode = postingForm.querySelector('.js-forum-posting-mode'),
previewButton = document.createElement('button'),
bbcodeButtons = $q('.forum__post__actions--bbcode'),
markdownButtons = $q('.forum__post__actions--markdown'),
markupButtons = $qa('.forum__post__action--tag');
// Initialise EEPROM, code sucks ass but it's getting nuked soon again anyway
if(typeof peepPath === 'string')
document.body.appendChild($e({
tag: 'script',
attrs: {
src: peepPath + '/eeprom.js',
charset: 'utf-8',
type: 'text/javascript',
onload: function() {
const eepromClient = new EEPROM(peepApp, peepPath + '/uploads', '');
const eepromHistory = $e({
attrs: {
className: 'eeprom-widget-history-items',
},
});
const eepromHandleFileUpload = function(file) {
const uploadElemNameValue = $e({
attrs: {
className: 'eeprom-widget-file-name-value',
title: file.name,
},
child: file.name,
});
const uploadElemName = $e({
tag: 'a',
attrs: {
className: 'eeprom-widget-file-name',
target: '_blank',
},
child: uploadElemNameValue,
});
const uploadElemProgressText = $e({
attrs: {
className: 'eeprom-widget-file-progress',
},
child: 'Please wait...',
});
const uploadElemProgressBarValue = $e({
attrs: {
className: 'eeprom-widget-file-bar-fill',
style: {
width: '0%',
},
},
});
const uploadElem = $e({
attrs: {
className: 'eeprom-widget-file',
},
child: [
{
attrs: {
className: 'eeprom-widget-file-info',
},
child: [
uploadElemName,
uploadElemProgressText,
],
},
{
attrs: {
className: 'eeprom-widget-file-bar',
},
child: uploadElemProgressBarValue,
},
],
});
if(eepromHistory.children.length > 0)
$ib(eepromHistory.firstChild, uploadElem);
else
eepromHistory.appendChild(uploadElem);
const explodeUploadElem = function() {
$r(uploadElem);
};
const uploadTask = eepromClient.createUpload(file);
uploadTask.onProgress = function(progressInfo) {
const progressValue = progressInfo.progress.toString() + '%';
uploadElemProgressBarValue.style.width = progressValue;
uploadElemProgressText.textContent = progressValue + ' (' + (progressInfo.total - progressInfo.loaded).toString() + ' bytes remaining)';
};
uploadTask.onFailure = function(errorInfo) {
if(!errorInfo.userAborted) {
let errorText = 'Was unable to upload file.';
switch(errorInfo.error) {
case EEPROM.ERR_INVALID:
errorText = 'Upload request was invalid.';
break;
case EEPROM.ERR_AUTH:
errorText = 'Upload authentication failed, refresh and try again.';
break;
case EEPROM.ERR_ACCESS:
errorText = 'You\'re not allowed to upload files.';
break;
case EEPROM.ERR_GONE:
errorText = 'Upload client has a configuration error or the server is gone.';
break;
case EEPROM.ERR_DMCA:
errorText = 'This file has been uploaded before and was removed for copyright reasons, you cannot upload this file.';
break;
case EEPROM.ERR_SERVER:
errorText = 'Upload server returned a critical error, try again later.';
break;
case EEPROM.ERR_SIZE:
if(errorInfo.maxSize < 1)
errorText = 'Selected file is too large.';
else {
const _t = ['bytes', 'KB', 'MB', 'GB', 'TB'],
_i = parseInt(Math.floor(Math.log(errorInfo.maxSize) / Math.log(1024))),
_s = Math.round(errorInfo.maxSize / Math.pow(1024, _i), 2);
errorText = 'Upload may not be larger than %1 %2.'.replace('%1', _s).replace('%2', _t[_i]);
}
break;
}
uploadElem.classList.add('eeprom-widget-file-fail');
uploadElemProgressText.textContent = errorText;
Misuzu.showMessageBox(errorText, 'Upload Error');
}
};
uploadTask.onComplete = function(fileInfo) {
uploadElem.classList.add('eeprom-widget-file-done');
uploadElemName.href = fileInfo.url;
uploadElemProgressText.textContent = '';
const insertTheLinkIntoTheBoxEx2 = function() {
const parserMode = parseInt(postingParser.value);
let insertText = location.protocol + fileInfo.url;
if(parserMode == 1) { // bbcode
if(fileInfo.isImage())
insertText = '[img]' + fileInfo.url + '[/img]';
else if(fileInfo.isAudio())
insertText = '[audio]' + fileInfo.url + '[/audio]';
else if(fileInfo.isVideo())
insertText = '[video]' + fileInfo.url + '[/video]';
} else if(parserMode == 2) { // markdown
if(fileInfo.isMedia())
insertText = '![](' + fileInfo.url + ')';
}
$insertTags(postingText, insertText, '');
postingText.value = postingText.value.trim();
};
uploadElemProgressText.appendChild($e({
tag: 'a',
attrs: {
href: 'javascript:void(0);',
onclick: function() { insertTheLinkIntoTheBoxEx2(); },
},
child: 'Insert',
}));
uploadElemProgressText.appendChild($t(' '));
uploadElemProgressText.appendChild($e({
tag: 'a',
attrs: {
href: 'javascript:void(0);',
onclick: function() {
eepromClient.deleteUpload(fileInfo).start();
explodeUploadElem();
},
},
child: 'Delete',
}));
insertTheLinkIntoTheBoxEx2();
};
uploadTask.start();
};
const eepromFormInput = $e({
tag: 'input',
attrs: {
type: 'file',
multiple: 'multiple',
className: 'eeprom-widget-form-input',
onchange: function(ev) {
const files = this.files;
for(const file of files)
eepromHandleFileUpload(file);
this.value = '';
},
},
});
const eepromForm = $e({
tag: 'label',
attrs: {
className: 'eeprom-widget-form',
},
child: [
eepromFormInput,
{
attrs: {
className: 'eeprom-widget-form-text',
},
child: 'Select Files...',
}
],
});
const eepromWidget = $e({
attrs: {
className: 'eeprom-widget',
},
child: [
eepromForm,
{
attrs: {
className: 'eeprom-widget-history',
},
child: eepromHistory,
},
],
});
postingForm.appendChild(eepromWidget);
postingText.addEventListener('paste', function(ev) {
if(ev.clipboardData && ev.clipboardData.files.length > 0) {
ev.preventDefault();
const files = ev.clipboardData.files;
for(const file of files)
eepromHandleFileUpload(file);
}
});
document.body.addEventListener('dragenter', function(ev) {
ev.preventDefault();
ev.stopPropagation();
});
document.body.addEventListener('dragover', function(ev) {
ev.preventDefault();
ev.stopPropagation();
});
document.body.addEventListener('dragleave', function(ev) {
ev.preventDefault();
ev.stopPropagation();
});
document.body.addEventListener('drop', function(ev) {
ev.preventDefault();
ev.stopPropagation();
if(ev.dataTransfer && ev.dataTransfer.files.length > 0) {
const files = ev.dataTransfer.files;
for(const file of files)
eepromHandleFileUpload(file);
}
});
},
onerror: function(ev) {
console.error('Failed to initialise EEPROM: ', ev);
},
},
}));
// hack: don't prompt user when hitting submit, really need to make this not stupid.
postingButtons.firstElementChild.addEventListener('click', function() {
Misuzu.Forum.Editor.allowWindowClose = true;
});
window.addEventListener('beforeunload', function(ev) {
if(!Misuzu.Forum.Editor.allowWindowClose && postingText.value.length > 0) {
ev.preventDefault();
ev.returnValue = '';
}
});
for(var i = 0; i < markupButtons.length; ++i)
(function(currentBtn) {
currentBtn.addEventListener('click', function(ev) {
$insertTags(postingText, currentBtn.dataset.tagOpen, currentBtn.dataset.tagClose);
});
})(markupButtons[i]);
Misuzu.Forum.Editor.switchButtons(parseInt(postingParser.value));
var lastPostText = '',
lastPostParser = null;
postingParser.addEventListener('change', function() {
var postParser = parseInt(postingParser.value);
Misuzu.Forum.Editor.switchButtons(postParser);
if(postingPreview.hasAttribute('hidden'))
return;
// dunno if this would even be possible, but ech
if(postParser === lastPostParser)
return;
postingParser.setAttribute('disabled', 'disabled');
previewButton.setAttribute('disabled', 'disabled');
previewButton.classList.add('input__button--busy');
Misuzu.Forum.Editor.renderPreview(postParser, lastPostText, function(success, text) {
if(!success) {
Misuzu.showMessageBox(text);
return;
}
postingPreview.classList[postParser == 2 ? 'add' : 'remove']('markdown');
lastPostParser = postParser;
postingPreview.innerHTML = text;
MszEmbed.handle($qa('.js-msz-embed-media'));
previewButton.removeAttribute('disabled');
postingParser.removeAttribute('disabled');
previewButton.classList.remove('input__button--busy');
});
});
previewButton.className = 'input__button';
previewButton.textContent = 'Preview';
previewButton.type = 'button';
previewButton.value = 'preview';
previewButton.addEventListener('click', function() {
if(previewButton.value === 'back') {
postingPreview.setAttribute('hidden', 'hidden');
postingText.removeAttribute('hidden');
previewButton.value = 'preview';
previewButton.textContent = 'Preview';
postingMode.textContent = postingMode.dataset.original;
postingMode.dataset.original = null;
} else {
var postText = postingText.value,
postParser = parseInt(postingParser.value);
if(lastPostText === postText && lastPostParser === postParser) {
postingPreview.removeAttribute('hidden');
postingText.setAttribute('hidden', 'hidden');
previewButton.value = 'back';
previewButton.textContent = 'Edit';
postingMode.dataset.original = postingMode.textContent;
postingMode.textContent = 'Previewing';
return;
}
postingParser.setAttribute('disabled', 'disabled');
previewButton.setAttribute('disabled', 'disabled');
previewButton.classList.add('input__button--busy');
Misuzu.Forum.Editor.renderPreview(postParser, postText, function(success, text) {
if(!success) {
Misuzu.showMessageBox(text);
return;
}
postingPreview.classList[postParser == 2 ? 'add' : 'remove']('markdown');
lastPostText = postText;
lastPostParser = postParser;
postingPreview.innerHTML = text;
MszEmbed.handle($qa('.js-msz-embed-media'));
postingPreview.removeAttribute('hidden');
postingText.setAttribute('hidden', 'hidden');
previewButton.value = 'back';
previewButton.textContent = 'Back';
previewButton.removeAttribute('disabled');
postingParser.removeAttribute('disabled');
previewButton.classList.remove('input__button--busy');
postingMode.dataset.original = postingMode.textContent;
postingMode.textContent = 'Previewing';
});
}
});
postingButtons.insertBefore(previewButton, postingButtons.firstChild);
};
Misuzu.Forum.Editor.switchButtons = function(parser) {
var bbcodeButtons = $q('.forum__post__actions--bbcode'),
markdownButtons = $q('.forum__post__actions--markdown');
bbcodeButtons.hidden = parser != 1;
markdownButtons.hidden = parser != 2;
};
Misuzu.Forum.Editor.renderPreview = function(parser, text, callback) {
if(!callback)
return;
parser = parseInt(parser);
text = text || '';
var xhr = new XMLHttpRequest,
formData = new FormData;
formData.append('post[mode]', 'preview');
formData.append('post[text]', text);
formData.append('post[parser]', parser.toString());
xhr.addEventListener('readystatechange', function() {
if(xhr.readyState !== XMLHttpRequest.DONE)
return;
if(xhr.status === 200)
callback(true, xhr.response);
else
callback(false, 'Failed to render preview.');
});
// need to figure out a url registry system again, current one is too much overhead so lets just do this for now
xhr.open('POST', '/forum/posting.php');
xhr.withCredentials = true;
xhr.send(formData);
};