the bold, italic and strikethrough options now function as toggles for formatting options and removes them rather than just replacing text the options buttons under the meta ui now communicate their status through use of the 'aria pressed' attribute so they can be properly read by assitive technologies like screen readers
230 lines
7.2 KiB
JavaScript
230 lines
7.2 KiB
JavaScript
import * as DataEvent from '../events/DataEvent.js';
|
|
import EventEmitter from '../events/EventEmitter.js';
|
|
import * as EditorEvent from '../events/EditorEvent.js';
|
|
import Prism from '../vendor/prism.js';
|
|
//import MarkdownLang from '../vendor/lang/prism-markdown.js';
|
|
//Prism.language.md = '../vendor/lang/prism-markdown.js';
|
|
//Prism.languauges['markdown'];
|
|
class TextEditor extends EventEmitter {
|
|
/**
|
|
* Text Editor UI Component
|
|
* @constructor
|
|
* @param {object} textEditor - Text area that will edit text
|
|
* @param {number} scrollLimit - YPos where editor position will become fixed
|
|
*/
|
|
//--------------------------
|
|
// constructor
|
|
//--------------------------
|
|
constructor(textEditor, scrollLimit) {
|
|
super();
|
|
|
|
document.querySelector('.text-editor-control').addEventListener('scroll', e => {
|
|
console.log('HERE');
|
|
});
|
|
|
|
document.body.addEventListener('scroll', e => {
|
|
var fixLimit = scrollLimit;
|
|
//console.log('POSITION', document.body.scrollTop + ' : ' + fixLimit);
|
|
/**
|
|
if (document.body.scrollTop + 5 >= fixLimit) {
|
|
document
|
|
.querySelector('.text-editor-control')
|
|
.classList.add('control-freeze');
|
|
} else {
|
|
document
|
|
.querySelector('.text-editor-control')
|
|
.classList.remove('control-freeze');
|
|
}
|
|
**/
|
|
});
|
|
document.getElementById('edit').addEventListener('input', e => {
|
|
let result_element = document.querySelector('#highlight-content');
|
|
this.textEditor = textEditor;
|
|
|
|
// Update code
|
|
let text = e.target.value;
|
|
result_element.innerHTML = text
|
|
.replace(new RegExp('&', 'g'), '&')
|
|
.replace(new RegExp('<', 'g'), '<');
|
|
let editorHeight = document.getElementById('highlight').offsetHeight;
|
|
document.querySelector('.edit-post-wrapper').style.height =
|
|
editorHeight + 'px';
|
|
e.target.style.height = editorHeight + 30 + 'px'; //TODO: yeah, it's ugly but it works for now, fix soon
|
|
// Syntax Highlight
|
|
Prism.highlightElement(result_element);
|
|
});
|
|
document.getElementById('edit').addEventListener('scroll', e => {
|
|
/* Scroll result to scroll coords of event - sync with textarea */
|
|
let result_element = document.querySelector('#highlight');
|
|
// Get and set x and y
|
|
result_element.scrollTop = e.scrollTop;
|
|
result_element.scrollLeft = e.scrollLeft;
|
|
});
|
|
document.getElementById('edit').dispatchEvent(new Event('input'));
|
|
this.setInputs();
|
|
|
|
//freeze editor formatting so it doesn't scroll off screen
|
|
}
|
|
//--------------------------
|
|
// methods
|
|
//--------------------------
|
|
setInputs() {
|
|
var editorButtons = document.querySelectorAll('.editor-button');
|
|
for (var i = 0, length = editorButtons.length; i < length; i++) {
|
|
editorButtons[i].addEventListener(
|
|
'click',
|
|
e => this.handleEditorOption(e),
|
|
false
|
|
);
|
|
}
|
|
}
|
|
notify(type, data) {
|
|
switch (type) {
|
|
case DataEvent.PAGE_UPDATED:
|
|
document.getElementById('submit-update').classList.add('icon-hide');
|
|
document.getElementById('submit-good').classList.remove('icon-hide');
|
|
document.getElementById('edit-update').classList.remove('submit-start');
|
|
document.getElementById('edit-update').classList.add('submit-cool');
|
|
setTimeout(() => {
|
|
document
|
|
.getElementById('submit-update')
|
|
.classList.remove('icon-hide');
|
|
document.getElementById('submit-good').classList.add('icon-hide');
|
|
document.getElementById('edit-update').classList.add('submit-start');
|
|
document
|
|
.getElementById('edit-update')
|
|
.classList.remove('submit-cool');
|
|
}, 2000);
|
|
break;
|
|
case DataEvent.PAGE_ADDED:
|
|
// do nothing
|
|
break;
|
|
case EditorEvent.EDITOR_UPLOAD_POST_IMAGE: {
|
|
let len = this.textEditor.value.length;
|
|
let start = this.textEditor.selectionStart;
|
|
let end = this.textEditor.selectionEnd;
|
|
let insert = '';
|
|
|
|
this.textEditor.value =
|
|
this.textEditor.value.substring(0, start) +
|
|
insert +
|
|
this.textEditor.value.substring(end, len);
|
|
document.getElementById('edit').dispatchEvent(new Event('input'));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//--------------------------
|
|
// event handlers
|
|
//--------------------------
|
|
handleEditorOption(e) {
|
|
e.preventDefault();
|
|
let len = this.textEditor.value.length;
|
|
let start = this.textEditor.selectionStart;
|
|
let end = this.textEditor.selectionEnd;
|
|
|
|
let selectedText = this.textEditor.value.substring(start, end);
|
|
let formatText = this.textEditor.value.substring(start - 1, end + 1);
|
|
let insert = '';
|
|
switch (e.target.id) {
|
|
case 'edit-bold':
|
|
if (formatText.includes('*')) {
|
|
insert = selectedText;
|
|
this.textEditor.value =
|
|
this.textEditor.value.substring(0, start - 2) +
|
|
insert +
|
|
this.textEditor.value.substring(end + 2, len);
|
|
} else {
|
|
insert = '**' + selectedText + '**';
|
|
this.textEditor.value =
|
|
this.textEditor.value.substring(0, start) +
|
|
insert +
|
|
this.textEditor.value.substring(end, len);
|
|
}
|
|
|
|
break;
|
|
case 'edit-italic':
|
|
if (formatText.includes('*')) {
|
|
insert = selectedText;
|
|
this.textEditor.value =
|
|
this.textEditor.value.substring(0, start - 1) +
|
|
insert +
|
|
this.textEditor.value.substring(end + 1, len);
|
|
} else {
|
|
insert = '*' + selectedText + '*';
|
|
this.textEditor.value =
|
|
this.textEditor.value.substring(0, start) +
|
|
insert +
|
|
this.textEditor.value.substring(end, len);
|
|
}
|
|
break;
|
|
case 'edit-strikethrough':
|
|
if (formatText.includes('~')) {
|
|
insert = selectedText;
|
|
this.textEditor.value =
|
|
this.textEditor.value.substring(0, start - 2) +
|
|
insert +
|
|
this.textEditor.value.substring(end + 2, len);
|
|
} else {
|
|
insert = '~~' + selectedText + '~~';
|
|
this.textEditor.value =
|
|
this.textEditor.value.substring(0, start) +
|
|
insert +
|
|
this.textEditor.value.substring(end, len);
|
|
}
|
|
break;
|
|
case 'edit-header1':
|
|
insert = '# ' + selectedText + '\n';
|
|
this.textEditor.value =
|
|
this.textEditor.value.substring(0, start) +
|
|
insert +
|
|
this.textEditor.value.substring(end, len);
|
|
break;
|
|
case 'edit-header2':
|
|
insert = '## ' + selectedText + '\n';
|
|
this.textEditor.value =
|
|
this.textEditor.value.substring(0, start) +
|
|
insert +
|
|
this.textEditor.value.substring(end, len);
|
|
break;
|
|
case 'edit-header3':
|
|
insert = '### ' + selectedText + '\n';
|
|
this.textEditor.value =
|
|
this.textEditor.value.substring(0, start) +
|
|
insert +
|
|
this.textEditor.value.substring(end, len);
|
|
break;
|
|
case 'edit-link':
|
|
{
|
|
let url = prompt("Let's get that url, boss");
|
|
let link = url.toLowerCase();
|
|
insert = '[' + selectedText + '](' + link + ')';
|
|
this.textEditor.value =
|
|
this.textEditor.value.substring(0, start) +
|
|
insert +
|
|
this.textEditor.value.substring(end, len);
|
|
}
|
|
break;
|
|
case 'edit-image':
|
|
//this.caretPos = position(this.textEditor).pos;
|
|
this.emitEvent(EditorEvent.EDITOR_UPLOAD_POST_IMAGE);
|
|
break;
|
|
case 'submit-save':
|
|
case 'edit-save':
|
|
this.emitEvent(EditorEvent.EDITOR_SAVE);
|
|
break;
|
|
case 'submit-update':
|
|
case 'edit-update':
|
|
this.emitEvent(EditorEvent.EDITOR_UPDATE);
|
|
break;
|
|
case 'edit-delete':
|
|
this.emitEvent(EditorEvent.EDITOR_DELETE);
|
|
break;
|
|
default:
|
|
//do stuff
|
|
break;
|
|
}
|
|
document.getElementById('edit').dispatchEvent(new Event('input'));
|
|
}
|
|
}
|
|
export default TextEditor;
|