Codemirror plugin Tinymce inline mode IndexSizeError - javascript

I'm using tinymce in inline mode on a contenteditable div.
I have used the CodeMirror tinymce plugin before (not inline mode) with no issues, but it doesn't seem to work correctly in inline mode.
I've tried changing the config to inline: false and it works.
Clicking the Source button opens the HTML with CodeMirror and seems ok.
But when I click Ok to save it, it seems to work fine in Chrome and Firefox but in Safari it adds an  and I can't close the modal (however, I can see that it has changed the content of the editable div), clicking the Ok button again, it adds another  and console error. Clicking the cancel or X button just adds console error.
In the console I get IndexSizeError: DOM Exception 1: Index or size was negative, or greater than the allowed value tinymce.min.js:5724
In Chrome, it seems to work but I still get a console error The given range isn't in document.
My tinymce config is below:
var tinymceEditText = tinymce.init({
selector: '.editableEl',
// target: ".editableElTinyMCE",
// theme: 'inlite',
inline: true,
plugins: [
'advlist autolink lists link image charmap anchor media',
'searchreplace visualblocks code fullscreen',
'template textcolor colorpicker hr fontawesome noneditable hr',
'insertdatetime contextmenu paste save codemirror',
'OBstock emoji_one'
],
toolbar1: 'save undo redo | styleselect | bold italic underline | forecolor backcolor | alignleft aligncenter alignright alignjustify | | code',
toolbar2: 'bullist numlist outdent indent | template | hr | anchor link unlink | image media OBstock emoji_one fontawesome ',
relative_urls: false,
remove_script_host: true,
templates: "/admin/JS/tinymce/js/tinymce/lists/template_list.php",
external_filemanager_path: "/filemanager/",
external_plugins: {"filemanager": "/filemanager/plugin.min.js"},
filemanager_title: "Uploaded Files", //the title of filemanager window default="Responsive filemanager",
filemanager_sort_by: "name", //the element to sorting (values: name,size,extension,date) default="",
filemanager_descending: 0, //descending ? or ascending (values=1 or 0) default="0"
codemirror: {
indentOnInit: true, // Whether or not to indent code on init.
smartIndent: true,
indentWithTabs: true,
saveCursorPosition: false,
path: '/admin/JS/codemirror-' + CODEMIRRORVERSION, // Path to CodeMirror distribution
config: { // CodeMirror config object
theme: CODETHEME,
indentUnit: 4,
lineNumbers: true,
mode: "htmlmixed",
matchBrackets: true,
autoCloseBrackets: true,
autoCloseTags: true,
matchTags: {bothTags: true},
indentOnInit: true, // Whether or not to indent code on init.
smartIndent: true,
indentWithTabs: true,
lineWrapping: true,
paletteHints: false,
lint: true,
lintOnChange: true,
showHint: true,
HTMLHint: true,
CSSHint: true,
JSHint: true,
getAnnotations: true,
gutters: ['CodeMirror-lint-markers', 'CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
foldGutter: true,
profile: 'xhtml', /* define Emmet output profile */
extraKeys: {
"Ctrl-Space": "autocomplete",
"F11": function (cm) {
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
},
"Esc": function (cm) {
if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
}
}
},
jsFiles: [
'mode/php/php.js',
'mode/htmlembedded/htmlembedded.js',
'addon/edit/matchbrackets.js',
'addon/edit/closebrackets.js',
'addon/edit/closetag.js',
'addon/fold/xml-fold.js',
'addon/fold/comment-fold.js',
'addon/edit/matchtags.js',
'mode/htmlmixed/htmlmixed.js',
'addon/search/searchcursor.js',
'addon/search/search.js',
'addon/hint/show-hint.js',
'addon/hint/anyword-hint.js',
'addon/hint/html-hint.js',
'addon/hint/css-hint.js',
'addon/hint/xml-hint.js',
'addon/hint/javascript-hint.js',
'addon/lint/lint.js',
'addon/lint/javascript-lint.js',
'addon/lint/json-lint.js',
'addon/lint/css-lint.js',
'addon/lint/html-lint.js',
'addon/customplugins/lint/csslint.js',
'addon/customplugins/hint/htmlhint.js'
],
cssFiles: [
'theme/' + CODETHEME + '.css',
'addon/dialog/dialog.css',
'addon/hint/show-hint.css',
'addon/lint/lint.css',
'addon/fold/foldgutter.css',
]
}
});
EDIT: I've now managed to recreate this in Chrome and Firefox, by opening the source editor, clicking cancel, opening the source editor again and clicking Ok. Different errors in the console though:
Chrome:
Uncaught DOMException: Failed to execute 'setStart' on 'Range': There is no child at offset 3. tinymce.min.js:5
Firefox:
IndexSizeError: Index or size is negative or greater than the allowed amount tinymce.mins.js:5

Finally managed to figure this one out be myself.
The issue wasn't with CodeMirror itself but actually tinymce's setContent function.
This fix for this was using the insertContent function instead and adding an extra setting in the tinymce.init
if(CMsettings.config.inlineFix) {
editor.selection.select(editor.getBody(), true);
editor.insertContent(codemirror.getValue().replace(cc, '<span id="CmCaReT"></span>'));
} else {
editor.setContent(codemirror.getValue().replace(cc, '<span id="CmCaReT"></span>'));
}
This made the insert button work but the cancel button still had some weird behaviour with the cursor, so I ended up duplicating and modifying the whole plugin to remove the insert and cancel buttons, and add them myself in the html

Related

Add custom image upload in tinymce

tinymce and using image upload, I have modified my config and added image upload from system.This is working fine and got new tab upload and below is my config :
config: any = {
height: 250,
theme: 'modern',
// powerpaste advcode toc tinymcespellchecker a11ychecker mediaembed linkchecker help
plugins: 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image imagetools link media template codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists textcolor wordcount contextmenu colorpicker textpattern',
toolbar: 'formatselect | bold italic strikethrough forecolor backcolor | link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent fontselect fontsizeselect | removeformat',
image_advtab: true,
imagetools_toolbar: 'rotateleft rotateright | flipv fliph | editimage imageoptions',
menubar: true,
statusbar: false,
images_upload_handler: (blobInfo, success, failure) => {
let firmuseracctid;
let loggedInUserData = JSON.parse((sessionStorage.getItem('userDetails')));
if (loggedInUserData && loggedInUserData.useracctid) {
firmuseracctid = loggedInUserData.useracctid
}
var formData;
formData = new FormData();
let s3signatureKey = 'path';
let headerImageName = blobInfo.filename();
let status: any = 0;
formData.append('status', status);
formData.append('signatureKey', s3signatureKey);
formData.append("file", blobInfo.blob(), blobInfo.filename());
//console.log(formData);
this.uploadFile(formData).subscribe(response => {
if (response) {
this.headerImageUrl = 'myURL';
success(this.headerImageUrl);
}
});
},
content_css: [
'//fonts.googleapis.com/css?family=Lato:300,300i,400,400i',
'//www.tinymce.com/css/codepen.min.css'
]
};
Now i need to add another tab where i have to load all images from my service side, For this how to add in config, Any help on this.
TinyMCE has no configuration option to create an entire UI for browsing your repository of images. To do this you have a few options.
TinyMCE makes two products that can do this for you:
MoxieManager
TinyDrive
There are 3rd party plugins that can do this for you such as:
Responsive File Manager
Roxy Fileman
Lastly you could choose to create your own file manager and use TinyMCE's APIs to interact with what you create (that is all the above tools do).

Insert text at cursor using tinyMCE and Angular

Using tinyMCE with Angular I need to insert text at the cursor position, preferably with a toolbar button.
As I understand, I'll need to use the onExecCommand event with mceInsertContent command.
I've looked at the following:
How to insert text in TinyMCE Editor where the cursor is?
Inserting text in TinyMCE Editor where the cursor is
But the solutions don't help in this case.
Here's the documentation
editor-dialog.component.html
<editor [init]="tinyMceConfig"
[formControl]="data.formControl">
</editor>
editor-dialog.component.ts
/* ... */
export class EditorDialogComponent implements OnInit {
tinyMceConfig: any;
constructor(
/* ... */
) { }
ngOnInit() {
this.configureTinyMce();
}
configureTinyMce() {
this.tinyMceConfig = {
theme: 'modern',
menubar: false,
branding: false,
height: 400,
skin_url: 'assets/tinymce/skins/lightgray',
inline: false,
plugins: [
'advlist lists link image directionality',
'searchreplace visualblocks visualchars media table contextmenu paste textcolor colorpicker pagebreak code'
],
// tslint:disable-next-line:max-line-length
toolbar: 'copy undo redo formatselect | bold italic strikethrough forecolor backcolor | link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat hr pagebreak code',
image_advtab: true,
imagetools_toolbar: 'rotateleft rotateright | flipv fliph | editimage imageoptions',
paste_data_images: !0,
importcss_append: !0,
images_upload_handler: function (e, t, a) {
console.log('image');
t('data:' + e.blob().type + ';base64,' + e.base64());
},
};
}
}
Thanks
The documentation you referenced is how to get TinyMCE integrated in an Angular application. What I believe you want to do is:
Add a toolbar button to the toolbar
Clicking the toolbar button inserts content at the current cursor location
Fundamentally the fact that you are using Angular is not important to either of these goals so you won't see anything Angular specific in the following details.
Adding a Toolbar Button
This is done (in TinyMCE 5) via the tinymce.editor.ui.registry.addButton() API. This is documented here: https://www.tiny.cloud/docs/api/tinymce.editor.ui/tinymce.editor.ui.registry/#addbutton
Inserting Content at the Cursor
This is done (in TinyMCE 5) via the tinymce.editor.insertContent() API.
This is documented here: https://www.tiny.cloud/docs/api/tinymce/tinymce.editor/#insertcontent
The simplest way to do all of this is to use your TinyMCE configuration via the setup() function. You can add the button and determine what actions (via JavaScript) it will take when clicked all in one place.
Here is an example: http://fiddle.tinymce.com/fHgaab
For anyone looking at this recently ( Mar 2021 ), this is how to send commands to tiny mce in angular 11:
import {Component, OnInit, ViewChild} from '#angular/core';
import {DomSanitizer, SafeHtml} from '#angular/platform-browser';
import {EditorComponent as tiny} from '#tinymce/tinymce-angular';
#Component({
selector: 'app-test-tiny',
templateUrl: './test-tiny.component.html',
styleUrls: ['./test-tiny.component.scss']
})
export class TestTinyComponent implements OnInit {
#ViewChild(tiny) tinyEditor: tiny;
contents = 'Hello World';
get preview(): SafeHtml {
return this.san.bypassSecurityTrustHtml(this.contents);
}
constructor(protected san: DomSanitizer) {
}
ngOnInit(): void {
}
doTest(): void {
this.tinyEditor.editor.execCommand('mceInsertContent', false, '<h1>Dude</h1>');
}
}
Seems like you are linking examples for a different library. So those wouldn't work. Is there any reason you chose to use the TinyMCE library instead of https://www.npmjs.com/package/angular2-tinymce ?
I've looked into the source code and couldn't find an easy way of targeting the tinyMCE instance through ViewChild, which is possible with the other library.
Michael's answer is correct, as it isn't important that I'm using Angular.
But I thought it would be worth sharing the Angular implementation for future reference.
TL;DR: Here's an example StackBlitz - Angular TinyMCE Insert Text at Cursor
The process included:
Upgrading to the (currently) latest versions of TinyMCE and TinyMCE Angular:
npm install tinymce#5.0.4
npm install #tinymce/tinymce-angular#3.0.1
Importing EditorModule:
/* ... */
import { EditorModule } from '#tinymce/tinymce-angular';
imports: [
/* ... */
EditorModule
]
/* ... */
Initialise the editor in the component (notice the setup() function for this case):
export class AppComponent implements OnInit {
name = 'Angular & TinyMCE';
tinyMceConfig: any;
ngOnInit() {
this.configureTinyMce();
}
configureTinyMce() {
this.tinyMceConfig = {
branding: false,
/**
* 'content_css' is needed to prevent console errors
* if you're hosting your own TinyMCE,
* You'll also need to add the following to angular.json:
* /* ... */
* "scripts": [
* "node_modules/tinymce/tinymce.min.js",
* "node_modules/tinymce/themes/silver/theme.js"
* ]
* /* ... */
*/
// content_css: 'assets/tinymce/skins/ui/oxide/content.min.css',
height: 400,
image_advtab: true,
imagetools_toolbar: `
rotateleft rotateright |
flipv fliph |
editimage imageoptions`,
importcss_append: !0,
inline: false,
menubar: true,
paste_data_images: !0,
/**
* 'skin_url' is needed to prevent console errors
* if you're hosting your own TinyMCE
*/
// skin_url: 'assets/tinymce/skins/ui/oxide',
toolbar: `
insertText |
copy undo redo formatselect |
bold italic strikethrough forecolor backcolor |
link | alignleft aligncenter alignright alignjustify |
numlist bullist outdent indent |
removeformat`,
setup: (editor) => {
editor.ui.registry.addButton('insertText', {
text: 'Press Me To Insert Text!',
onAction: () => {
editor.insertContent('<strong>Hello World!</strong>');
}
});
}
};
}
}
The HTML is simply:
<editor [init]="tinyMceConfig"></editor>

Tiny mce editor doesn't work on https url

I have test website (developing site) works on http and my editor loads without any issue but since i moved my app to main site which runs on https my editor stopped loading and I get this error in console:
ReferenceError: tinymce is not defined
Screenshots
http site
https site
Code
JavaScript
<script>
var editor_config = {
path_absolute : "/",
selector: "textarea.editor", //get class name "editor"
plugins: [
"advlist autolink lists link image charmap print preview hr anchor pagebreak",
"searchreplace wordcount visualblocks visualchars code fullscreen",
"insertdatetime media nonbreaking save table contextmenu directionality",
"emoticons template paste textcolor colorpicker textpattern codesample",
"fullpage toc tinymcespellchecker imagetools help"
],
toolbar: "insertfile undo redo | styleselect | bold italic strikethrough | alignleft aligncenter alignright alignjustify | ltr rtl | bullist numlist outdent indent removeformat formatselect| link image media | emoticons charmap | code codesample | forecolor backcolor",
external_plugins: { "nanospell": "https://www.mysiteurl.com/js/tinymce/plugins/nanospell/plugin.js" },
nanospell_server:"php",
browser_spellcheck: true,
relative_urls: true,
remove_script_host: false,
branding: false,
file_browser_callback : function(field_name, url, type, win) {
var x = window.innerWidth || document.documentElement.clientWidth || document.getElementsByTagName('body')[0].clientWidth;
var y = window.innerHeight|| document.documentElement.clientHeight|| document.getElementsByTagName('body')[0].clientHeight;
var cmsURL = editor_config.path_absolute + 'laravel-filemanager?field_name=' + field_name;
if (type == 'image') {
cmsURL = cmsURL + "&type=Images";
} else {
cmsURL = cmsURL + "&type=Files";
}
tinymce.activeEditor.windowManager.open({
file: '<?= route('elfinder.tinymce4') ?>',// use an absolute path!
title: 'File manager',
width: 900,
height: 450,
resizable: 'yes'
}, {
setUrl: function (url) {
win.document.getElementById(field_name).value = url;
}
});
}
};
tinymce.init(editor_config);
</script>
<script>
{!! \File::get(base_path('vendor/barryvdh/laravel-elfinder/resources/assets/js/standalonepopup.js')) !!}
</script>
Note: error refers to this line tinymce.init(editor_config);
Blade
{{Form::textarea('short_description', null, array('class' => 'form-control editor'))}}
Help would be appreciated!
SOLVED
I download again tinymce and reupload js files, now is loading without issue.

Allow all attributes for TinyMCE

I am building a javascript (Backbone with Coffeescript) app and in this app I am using TinyMCE.
I am adding a new tag with contenteditable set to true but TinyMCE ignores it. How can I allow this attribute?
This is my code:
#App.module "Concerns", (Concerns, App, Backbone, Marionette, $, _) ->
Concerns.FormWysiwyg =
onDomRefresh: ->
tinymce.init
selector: '.wysiwyg'
height: 350
menubar: false
statusbar: false
plugins: [
'advlist autolink lists link image charmap print preview anchor'
'searchreplace visualblocks code fullscreen'
'insertdatetime media table contextmenu paste code'
]
extended_valid_elements: 'span[class|contenteditable]'
toolbar: 'bold italic | alignleft aligncenter alignright | bullist numlist outdent indent | link | editable'
setup: (editor) ->
editor.on 'change', ->
editor.save()
editor.addButton 'editable',
text: 'Editable'
icon: false
onclick: ->
ed = tinyMCE.activeEditor
content = ed.selection.getContent({'format':'html'})
new_selection_content = '<span class="editable yellow" contenteditable="true">' + content + '</span>'
ed.execCommand('insertHTML', false, new_selection_content)

tiniMCE do not init in a jsPanel

I use jsPanel to have kind of modal windows appearing on my site.
On jsPanel init, I specify content with a textarea, and a callback function.
Once my jsPanel is created, I try to initialise a tinyMCE in the callback. I test tinyMCE instances and my editor is in the listing of instances... but in the jsPanel it displays as a normal textarea, not as a tinyMCE.
Any idea ?
Here is the code :
function oninitjspanel()
{
console.log('before init modal mce');
tinymce.init({
selector: "#email_message",
entity_encoding : "raw",
encoding: "UTF-8",
theme: "modern",
height: "100%",
width: "100%",
plugins: [
"advlist autolink lists link image charmap print preview hr anchor pagebreak",
"searchreplace wordcount visualblocks visualchars code fullscreen",
"insertdatetime media nonbreaking save table contextmenu directionality",
"emoticons template paste textcolor colorpicker textpattern"
],
toolbar1: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image preview media | forecolor backcolor emoticons",
image_advtab: true,
});
console.log('after init modal mce');
for (var i = 0; i < tinymce.editors.length; i++)
{
console.log(i + " Editor id:", tinymce.editors[i].id);
}
}
$('#new_document').click (function () {
var content = '<div id="choix_document"><textarea id="email_message"></textarea></div>';
$.jsPanel({
content: content,
position: "center",
theme: "success",
title: "Nouveau document/email",
size: { width: function(){ return $(window).width()*0.75 },
height: function(){ return $(window).height()*0.75 } },
toolbarFooter: "<div class='email_submit'>Envoyer email</div><div id='email_returnmessage'></div>",
callback: oninitjspanel(),
});
});
The console log :
before init modal mce
after init modal mce
0 Editor id: model_editor
1 Editor id: email_message
EDIT : one more thing, as tinyMCE have focus issues in modals, I apply at my page loading the following to prevent the issue :
$(document).on('focusin', function(e) {
if ($(e.target).closest(".mce-window, .moxman-window").length) {
e.stopImmediatePropagation();
}
});
Just take a look at https://github.com/Flyer53/jsPanel/issues/51
But I guess you're the one asking the same question on GitHub's the jsPanel issues page anyhow?

Categories