mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-01-08 19:21:40 +09:00
Add a simple editor based on contenteditable
This commit is contained in:
parent
ece4ce90c2
commit
a2c763661c
5 changed files with 221 additions and 0 deletions
28
modules/editor/skins/simpleeditor/css/simpleeditor.less
Normal file
28
modules/editor/skins/simpleeditor/css/simpleeditor.less
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
.rx_simpleeditor {
|
||||
width: 100%;
|
||||
min-height: 60px;
|
||||
box-sizing: border-box;
|
||||
resize: vertical;
|
||||
overflow-y: auto;
|
||||
&.light {
|
||||
border: 1px solid #c4c4c4;
|
||||
background: #fff;
|
||||
padding: 10px;
|
||||
}
|
||||
&.dark {
|
||||
border-color: #111;
|
||||
background: #333;
|
||||
color: #fff;
|
||||
}
|
||||
iframe {
|
||||
max-width: 100%;
|
||||
padding: 5px 0;
|
||||
}
|
||||
img {
|
||||
max-width: 50%;
|
||||
padding: 5px 0;
|
||||
}
|
||||
img.thumbnail {
|
||||
max-width: 160px;
|
||||
}
|
||||
}
|
||||
16
modules/editor/skins/simpleeditor/editor.html
Normal file
16
modules/editor/skins/simpleeditor/editor.html
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<load target="../../tpl/js/editor_common.js" />
|
||||
<load target="css/simpleeditor.less" />
|
||||
<load target="js/simpleeditor.js" />
|
||||
<load target="js/interface.js" />
|
||||
|
||||
<div id="simpleeditor_wrapper_{$editor_sequence}" class="rx_simpleeditor_wrapper">
|
||||
<div id="simpleeditor_instance_{$editor_sequence}" class="rx_simpleeditor {$colorset} rhymix_content" contenteditable="true"
|
||||
data-editor-sequence="{$editor_sequence}"
|
||||
data-editor-primary-key-name="{$editor_primary_key_name}"
|
||||
data-editor-content-key-name="{$editor_content_key_name}"
|
||||
data-editor-height="{$editor_height}">
|
||||
</div>
|
||||
<!--@if($allow_fileupload)-->
|
||||
<include target="../ckeditor/file_upload.html" />
|
||||
<!--@endif-->
|
||||
</div>
|
||||
16
modules/editor/skins/simpleeditor/js/interface.js
Normal file
16
modules/editor/skins/simpleeditor/js/interface.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
function _getSimpleEditorInstance(editor_sequence) {
|
||||
return jQuery('#simpleeditor_instance_' + editor_sequence);
|
||||
}
|
||||
|
||||
function editorGetContent(editor_sequence) {
|
||||
return _getSimpleEditorInstance(editor_sequence).html().escape();
|
||||
}
|
||||
|
||||
function editorReplaceHTML(iframe_obj, content) {
|
||||
var editor_sequence = parseInt(iframe_obj.id.replace(/^.*_/, ''), 10);
|
||||
_getSimpleEditorInstance(editor_sequence).html(content);
|
||||
}
|
||||
|
||||
function editorGetIFrame(editor_sequence) {
|
||||
return _getSimpleEditorInstance(editor_sequence).get(0);
|
||||
}
|
||||
146
modules/editor/skins/simpleeditor/js/simpleeditor.js
Normal file
146
modules/editor/skins/simpleeditor/js/simpleeditor.js
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
"use strict";
|
||||
|
||||
(function($) {
|
||||
|
||||
// Save the cursor position.
|
||||
var ranges = [];
|
||||
var saveSelection = function() {
|
||||
var sel = window.getSelection();
|
||||
ranges = [];
|
||||
if (sel.getRangeAt && sel.rangeCount) {
|
||||
for (let i = 0; i < sel.rangeCount; i++) {
|
||||
ranges.push(sel.getRangeAt(i));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Insert content at cursor position.
|
||||
var insertContent = function(instance, content) {
|
||||
if (ranges.length) {
|
||||
var range = ranges[0];
|
||||
range.collapse(false);
|
||||
ranges = [];
|
||||
} else {
|
||||
var range = document.createRange();
|
||||
range.selectNodeContents(instance.get(0));
|
||||
range.collapse(false);
|
||||
}
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(range);
|
||||
document.execCommand('insertHTML', false, content);
|
||||
};
|
||||
|
||||
// Simplify HTML content by removing unnecessary tags.
|
||||
var simplifyContent = function(str) {
|
||||
str = String(str);
|
||||
str = str.replace(/<!--(.*?)-->/g, '');
|
||||
str = str.replace(/<\/?(\?xml|meta|link|font|style|script|noscript|frame|noframes)\b[^>]*?>/ig, '');
|
||||
str = str.replace(/<br\s?\/?>/g, '').replace(/(<\/?)div(\W)/g, '$1p$2');
|
||||
return str;
|
||||
};
|
||||
|
||||
// Convert YouTube links.
|
||||
var convertYouTube = function(str) {
|
||||
var regexp = /https?:\/\/(www\.youtube(?:-nocookie)?\.com\/(?:watch\?v=|v\/|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]+)\S*/g;
|
||||
var embed = '<iframe width="560" height="315" src="https://www.youtube.com/embed/$2" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><p></p>';
|
||||
return String(str).replace(regexp, embed);
|
||||
};
|
||||
|
||||
// Page load event handler.
|
||||
$(function() {
|
||||
$('.rx_simpleeditor').each(function() {
|
||||
|
||||
// Load editor info.
|
||||
var editor = $(this);
|
||||
var editor_sequence = editor.data('editor-sequence');
|
||||
var content_key = editor.data('editor-content-key-name');
|
||||
var primary_key = editor.data('editor-primary-key-name');
|
||||
var insert_form = editor.closest('form');
|
||||
var content_input = insert_form.find('input,textarea').filter('[name=' + content_key + ']');
|
||||
var editor_height = editor.data('editor-height');
|
||||
if (editor_height) {
|
||||
editor.css('height', editor_height + 'px');
|
||||
}
|
||||
|
||||
// Set editor sequence and other info to the form.
|
||||
insert_form[0].setAttribute('editor_sequence', editor_sequence);
|
||||
editorRelKeys[editor_sequence] = {};
|
||||
editorRelKeys[editor_sequence].primary = insert_form.find("input[name='" + primary_key + "']");
|
||||
editorRelKeys[editor_sequence].content = content_input;
|
||||
editorRelKeys[editor_sequence].func = editorGetContent;
|
||||
|
||||
// Force <p> as paragraph separator.
|
||||
document.execCommand('defaultParagraphSeparator', false, 'p');
|
||||
|
||||
// Capture some simple keyboard shortcuts.
|
||||
editor.on('keydown', function(event) {
|
||||
if (!event.ctrlKey) {
|
||||
return;
|
||||
}
|
||||
var char = String.fromCharCode(event.which).toLowerCase();
|
||||
if (char === 'b') {
|
||||
document.execCommand('bold');
|
||||
event.preventDefault();
|
||||
}
|
||||
if (char === 'i') {
|
||||
document.execCommand('italic');
|
||||
event.preventDefault();
|
||||
}
|
||||
if (char === 'u') {
|
||||
document.execCommand('underline');
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// Save cursor position on moseup & keyup.
|
||||
editor.on('mouseup keyup', function() {
|
||||
saveSelection();
|
||||
});
|
||||
|
||||
// Clean up pasted content.
|
||||
editor.on('paste', function(event) {
|
||||
var clipboard_data = (event.clipboardData || window.clipboardData || event.originalEvent.clipboardData);
|
||||
if (typeof clipboard_data !== 'undefined') {
|
||||
var content = clipboard_data.getData('text/html');
|
||||
if (content === '') {
|
||||
content = clipboard_data.getData('text');
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
content = convertYouTube(simplifyContent(content));
|
||||
insertContent(editor, content);
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
// Load existing content.
|
||||
if (content_input.size()) {
|
||||
editor.html(content_input.val());
|
||||
}
|
||||
|
||||
// Copy edited content to the actual input element.
|
||||
editor.on('input blur mouseup keyup', function() {
|
||||
var content = simplifyContent(editor.html());
|
||||
content_input.val(content);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Simulate CKEditor for file upload integration.
|
||||
window._getCkeInstance = function(editor_sequence) {
|
||||
var instance = $('#simpleeditor_instance_' + editor_sequence);
|
||||
return {
|
||||
getData: function() {
|
||||
return String(instance.html());
|
||||
},
|
||||
setData: function(content) {
|
||||
instance.html(content);
|
||||
},
|
||||
insertHtml: function(content) {
|
||||
insertContent(instance, content);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
15
modules/editor/skins/simpleeditor/skin.xml
Normal file
15
modules/editor/skins/simpleeditor/skin.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<skin version="0.2">
|
||||
<title xml:lang="ko">SimpleEditor</title>
|
||||
<description xml:lang="ko">SimpleEditor</description>
|
||||
<version>1.0.0</version>
|
||||
<date>2020-07-07</date>
|
||||
<colorset>
|
||||
<color name="light">
|
||||
<title xml:lang="ko">Light</title>
|
||||
</color>
|
||||
<color name="dark">
|
||||
<title xml:lang="ko">Dark</title>
|
||||
</color>
|
||||
</colorset>
|
||||
</skin>
|
||||
Loading…
Add table
Add a link
Reference in a new issue