new text editor: tinyMCE
This commit is contained in:
247
masks/convert.html
Normal file
247
masks/convert.html
Normal file
@@ -0,0 +1,247 @@
|
||||
<div id="convert" class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col"><a id="prev">Previous</a></div>
|
||||
<div class="col"><a id="next">next</a></div>
|
||||
<div class="col"><a id="res">Result</a></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="notes_feedback"></div>
|
||||
</div>
|
||||
<div class="row h-100">
|
||||
<div class="col w-50"><div id="notes_old"></div></div>
|
||||
<div class="col w-50"><textarea id="tiny"></textarea></div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="scripts/quill.min.js"></script>
|
||||
<script type="text/javascript" src="scripts/quill.mods.js"></script>
|
||||
<script type="text/javascript">
|
||||
Quill.register({'modules/better-table': quillBetterTable}, true);
|
||||
|
||||
class Editor {
|
||||
constructor(sEditorId, bReadOnly) {
|
||||
this.keystrokes = 0;
|
||||
this.readOnly = bReadOnly || false;
|
||||
this.sCursorPos = '';
|
||||
|
||||
//DOM Elements
|
||||
this.$Editor = $(sEditorId);
|
||||
|
||||
this.onKeyStroke = function() {};
|
||||
|
||||
this.oQuill = new Quill(sEditorId, {
|
||||
theme: 'snow',
|
||||
placeholder: 'Notes',
|
||||
readOnly: bReadOnly,
|
||||
modules: {
|
||||
table: false,
|
||||
'better-table': {
|
||||
operationMenu: {
|
||||
items: {
|
||||
mergeCells: false,
|
||||
unmergeCells: false
|
||||
}
|
||||
}
|
||||
},
|
||||
keyboard: {
|
||||
bindings: quillBetterTable.keyboardBindings
|
||||
},
|
||||
toolbar: [
|
||||
['bold', 'italic', 'underline', 'strike'],
|
||||
//['blockquote', 'code-block'],
|
||||
[{ 'color': [] }, { 'background': [] }],
|
||||
[{ 'header': 1 }, { 'header': 2 }, 'blockquote'],
|
||||
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
|
||||
//[{ 'script': 'sub'}, { 'script': 'super' }],
|
||||
//[{ 'indent': '-1'}, { 'indent': '+1' }],
|
||||
//[{ 'direction': 'rtl' }],
|
||||
//[{ 'size': ['small', false, 'large', 'huge'] }],
|
||||
//[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
|
||||
//[{ 'font': [] }],
|
||||
[{ 'align': [] }],
|
||||
['table'],
|
||||
['link', 'image'],
|
||||
['clean']
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
var oToolbar = this.oQuill.getModule('toolbar');
|
||||
oToolbar.addHandler('table', () => {
|
||||
let tableModule = this.oQuill.getModule('better-table');
|
||||
tableModule.insertTable(3, 3);
|
||||
});
|
||||
|
||||
this._initEvents();
|
||||
this._postInit();
|
||||
}
|
||||
|
||||
_initEvents() {
|
||||
//Key strokes
|
||||
this.$Editor.keydown((e) => {
|
||||
if($.inArray(e.which, [13, 37, 38, 39, 40]) == -1) this.onKeyStroke(e);
|
||||
});
|
||||
|
||||
//On text modification
|
||||
this.oQuill.on('text-change', (delta, oldDelta, sSource) => {this._incKeyStrokes();});
|
||||
}
|
||||
|
||||
_postInit(iPage) {
|
||||
if(!this.readOnly) this.oQuill.focus();
|
||||
}
|
||||
|
||||
_incKeyStrokes() {
|
||||
this.keystrokes += 1;
|
||||
}
|
||||
|
||||
getContent() {
|
||||
return this.oQuill.getContents().ops;
|
||||
}
|
||||
|
||||
setContent(asOps) {
|
||||
this.oQuill.setContents(asOps);
|
||||
this._postInit();
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
const rEmpty = /^(<p>(<br>|<br\/>|<br\s\/>|\s+|)<\/p>|)$/gm;
|
||||
return rEmpty.test(this.oQuill.getText().trim());
|
||||
}
|
||||
|
||||
quill2Html(asDelta) {
|
||||
var tempCont = document.createElement('div');
|
||||
(new Quill(tempCont)).setContents(asDelta);
|
||||
return tempCont.getElementsByClassName('ql-editor')[0].innerHTML;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
oCATC.pageInit = function(asHash, bFirstPage) {
|
||||
self.tmp('id_course', asHash.items[0]);
|
||||
|
||||
$('#prev').attr('href', '#convert-'+(parseInt(self.tmp('id_course')) - 1));
|
||||
$('#next').attr('href', '#convert-'+(parseInt(self.tmp('id_course')) + 1));
|
||||
$('#res').attr('href', '#course-'+(self.tmp('id_course')));
|
||||
|
||||
//Setup Quill
|
||||
oEditor = new Editor('#notes_old');
|
||||
oEditor.onKeyStroke = (e) => {
|
||||
if(e.which == 83 && e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
save(true);
|
||||
}
|
||||
else save();
|
||||
};
|
||||
|
||||
//Setup TinyMCE (new)
|
||||
tinymce.init({
|
||||
selector: '#tiny',
|
||||
menubar: false,
|
||||
height: "10000px",
|
||||
plugins: [
|
||||
'advlist autolink lists link image charmap print preview anchor',
|
||||
'searchreplace visualblocks code fullscreen',
|
||||
'insertdatetime media table paste save'
|
||||
],
|
||||
toolbar:
|
||||
'save | '+
|
||||
'formatselect | '+
|
||||
'bold italic underline strikethrough forecolor | '+
|
||||
'alignleft aligncenter alignright alignjustify | '+
|
||||
'bullist numlist outdent indent | '+
|
||||
'link table image | '+
|
||||
'removeformat',
|
||||
save_onsavecallback: function(oEditor) { save(true); },
|
||||
content_style: 'body{font-family:Helvetica,Arial,sans-serif; font-size:13px;} p{margin:0; padding:0;}',
|
||||
setup: function(ed) {
|
||||
ed.on('init', function(e) {
|
||||
//Load notes (old)
|
||||
Tools.ajax(
|
||||
'get_note_old',
|
||||
(asData) => {
|
||||
oEditor.setContent(asData.notes);
|
||||
|
||||
$Content = $('.ql-editor').clone();
|
||||
$($Content.find('ol li[data-list=bullet]').removeAttr('data-list').parent().get().reverse()).each(function(iKey, oElem) {
|
||||
$(this).replaceWith($('<ul>'+$(this).html()+'</ul>'));
|
||||
});
|
||||
|
||||
tinymce.activeEditor.setContent($Content.html());
|
||||
save(true);
|
||||
},
|
||||
{id: self.tmp('id_course')},
|
||||
() => {console.log('Note not found for course ID = '+self.tmp('id_course'))}
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
oCATC.onSamePageMove = function(asHash) {
|
||||
location.reload();
|
||||
return false;
|
||||
};
|
||||
|
||||
function noteFeedback(sType, sMsg) {
|
||||
var $Feedback = $('#notes_feedback');
|
||||
if(sMsg != $Feedback.find('.alert').text()) {
|
||||
$Feedback.finish().fadeOut($Feedback.is(':empty')?0:'fast', function(){
|
||||
$(this)
|
||||
.empty()
|
||||
.append($('<div>', {'class':'alert note-'+sType}).text(sMsg))
|
||||
.fadeIn('fast')
|
||||
.delay(5000)
|
||||
.fadeOut('fast');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function save(bForce, bOnUnload) {
|
||||
bForce = bForce || false;
|
||||
bOnUnload = bOnUnload || false;
|
||||
if(bOnUnload) bForce = true;
|
||||
|
||||
if(typeof oSaveTimer != 'undefined') clearTimeout(oSaveTimer);
|
||||
var bSave = (/*oEditor.keystrokes % 20 == 0 || */bForce);
|
||||
|
||||
if(bSave) {
|
||||
if(self.tmp('saving') && !bOnUnload) {
|
||||
oSaveTimer = setTimeout(function(){save(true);}, 500);
|
||||
}
|
||||
else {
|
||||
var sContent = tinymce.activeEditor.getContent();
|
||||
if(self.tmp('id_course') != 0) {
|
||||
self.tmp('saving', true);
|
||||
noteFeedback('info', 'Saving...');
|
||||
Tools.ajax(
|
||||
'set_note',
|
||||
function(asData) {
|
||||
self.tmp('saving', false);
|
||||
var sMsg = 'Note saved ('+asData.led_time+')';
|
||||
if($.type(noteFeedback)=='function') noteFeedback('notice', sMsg);
|
||||
else oCATC.feedback('success', sMsg);
|
||||
},
|
||||
{id: self.tmp('id_course'), content: sContent},
|
||||
function(sError) {
|
||||
self.tmp('saving', false);
|
||||
var sMsg = 'Not saved! An error occured: '+sError;
|
||||
if($.type(noteFeedback)=='function') noteFeedback('error', sMsg);
|
||||
else oCATC.feedback('error', sMsg);
|
||||
oSaveTimer = setTimeout(save, 1000);
|
||||
},
|
||||
false,
|
||||
'POST',
|
||||
'json',
|
||||
bOnUnload
|
||||
);
|
||||
}
|
||||
else noteFeedback('error', 'No Course ID');
|
||||
}
|
||||
}
|
||||
else {
|
||||
oSaveTimer = setTimeout(function(){save(true);}, 1000*5);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
<div id="notes_box" class="col-9 h-100">
|
||||
<div id="notes_feedback"></div>
|
||||
<div id="notes"></div>
|
||||
<form id="notes" method="post"><textarea id="tiny"></textarea></form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="template-items">
|
||||
@@ -31,27 +31,40 @@ oCATC.pageInit = function(asHash, bFirstPage) {
|
||||
//Setup layout
|
||||
self.setPageTitle(self.consts.courses[self.tmp('id_course')].description);
|
||||
|
||||
//Setup Quill
|
||||
oEditor = new Editor('#notes');
|
||||
oEditor.onKeyStroke = (e) => {
|
||||
if(e.which == 83 && e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
save(true);
|
||||
//Setup TinyMCE
|
||||
tinymce.init({
|
||||
selector: '#tiny',
|
||||
height: '100%',
|
||||
menubar: false,
|
||||
plugins: [
|
||||
'advlist autolink lists link image charmap print preview anchor',
|
||||
'searchreplace visualblocks code fullscreen',
|
||||
'insertdatetime media table paste autosave save hr'
|
||||
],
|
||||
toolbar:
|
||||
'save undo redo | '+
|
||||
'formatselect | '+
|
||||
'bold italic underline strikethrough forecolor | '+
|
||||
'alignleft aligncenter alignright alignjustify | '+
|
||||
'bullist numlist outdent indent hr | '+
|
||||
'link table image | '+
|
||||
'removeformat',
|
||||
save_onsavecallback: function(oEditor) { save(true); },
|
||||
autosave_interval: "10s",
|
||||
setup: function(ed) {
|
||||
ed.on('init', function(e) {
|
||||
Tools.ajax(
|
||||
'get_note',
|
||||
(asData) => {
|
||||
tinymce.activeEditor.setContent(asData.notes);
|
||||
noteFeedback('notice', 'Last update at '+asData.led_time+' on '+asData.led_date);
|
||||
},
|
||||
{id: self.tmp('id_course')},
|
||||
() => {console.log('Note not found for course ID = '+self.tmp('id_course'))}
|
||||
);
|
||||
});
|
||||
}
|
||||
else save();
|
||||
};
|
||||
//oQuill.keyboard.addBinding({key: 'S', ctrlKey: true}, function(){saveNotes(true);});
|
||||
|
||||
//Load notes
|
||||
Tools.ajax(
|
||||
'get_note',
|
||||
(asData) => {
|
||||
oEditor.setContent(asData.notes);
|
||||
noteFeedback('notice', 'Last update at '+asData.led_time+' on '+asData.led_date);
|
||||
},
|
||||
{id: self.tmp('id_course')},
|
||||
() => {console.log('Note not found for course ID = '+self.tmp('id_course'))}
|
||||
);
|
||||
});
|
||||
|
||||
//Setup File Upload
|
||||
$('#fileupload')
|
||||
@@ -85,7 +98,7 @@ oCATC.pageInit = function(asHash, bFirstPage) {
|
||||
loadDocs();
|
||||
|
||||
//Scrollbar
|
||||
$('#doc_list_box, #notes').mCustomScrollbar({
|
||||
$('#doc_list_box').mCustomScrollbar({
|
||||
axis: 'y',
|
||||
scrollInertia: 0,
|
||||
autoExpandScrollbar: true,
|
||||
@@ -93,6 +106,10 @@ oCATC.pageInit = function(asHash, bFirstPage) {
|
||||
});
|
||||
};
|
||||
|
||||
oCATC.onSamePageMove = function(asHash) {
|
||||
return true;
|
||||
};
|
||||
|
||||
oCATC.onQuitPage = function(sExitMode) {
|
||||
return save(true, (sExitMode==self.consts.exitmodes.closing));
|
||||
};
|
||||
@@ -148,14 +165,14 @@ function save(bForce, bOnUnload) {
|
||||
if(bOnUnload) bForce = true;
|
||||
|
||||
if(typeof oSaveTimer != 'undefined') clearTimeout(oSaveTimer);
|
||||
var bSave = (oEditor.keystrokes % 20 == 0 || bForce);
|
||||
var bSave = (/*oEditor.keystrokes % 20 == 0 || */bForce); //FIXME: redo auto save
|
||||
|
||||
if(bSave) {
|
||||
if(self.tmp('saving') && !bOnUnload) {
|
||||
oSaveTimer = setTimeout(function(){save(true);}, 500);
|
||||
}
|
||||
else {
|
||||
var sContent = oEditor.getContent();
|
||||
var sContent = tinymce.activeEditor.getContent();
|
||||
if(self.tmp('id_course') != 0) {
|
||||
self.tmp('saving', true);
|
||||
noteFeedback('info', 'Saving...');
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
<script type="text/javascript" src="scripts/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="scripts/bootstrap.bundle.min.js"></script>
|
||||
<script type="text/javascript" src="scripts/jquery.mods.js"></script>
|
||||
<script type="text/javascript" src="scripts/quill.min.js"></script>
|
||||
<script type="text/javascript" src="scripts/quill.mods.js"></script>
|
||||
<script type="text/javascript" src="scripts/tinymce/tinymce.min.js"></script>
|
||||
<script type="text/javascript" src="scripts/tinymce/jquery.tinymce.min.js"></script>
|
||||
<script type="text/javascript" src="[#]filepath_js_common[#]"></script>
|
||||
<script type="text/javascript" src="[#]filepath_js_catc[#]"></script>
|
||||
<link rel="icon" type="image/png" href="images/favicon.png">
|
||||
|
||||
Reference in New Issue
Block a user