I am trying to create a preview function in a CKEditor instance.
I'm using CKEditor 4 and am replacing textareas by class name, the only issue I am facing is that I cannot get the value of the textarea using JavaScript, this is what I've tried so far:
function prev()
{
html=document.forms["1_form"]["editor1"].value;
document.getElementById("prev").innerHTML = html;
}
and the CKEditor textarea:
<textarea class="ckeditor" onkeydown="prev()"></textarea>
Why doesn't this work? If I disable CKEditor, the script functions as expected, but not with ckeditor enabled. What am I supposed to do?
Thanks!
Edit:
I am now trying to do it with replace and this is the code I'm using:
CKEDITOR.replace('editor1'); //new ckeditor instance
var editor = CKEDITOR.instances.editor1; //reference to instance
//on `key` event
editor.on('key', function(){
var data = editor.getData(); //reference to ckeditor data
$('#prev').html(data); //update `div` html
});
it works but the only this is, it updates only after the next key is pressed so say the value of the editor is hello world it will show the preview as hello worl what can I do to this code to fix it, please ignore the first set of code.
This is because CKEDITOR replace your <textarea> into <div> with contenteditable="true" attribute and there is no value property in DOM for <div> element.
You need to add event listener to CKEDITOR instance, not to DOM element, for example:
// check if editor is ready
CKEDITOR.on( 'instanceCreated', function( e ) {
// check if DOM is ready
e.editor.on( 'contentDom', function() {
// bind "keydown" event to CKEDITOR
e.editor.document.on('keydown', function( event ) {
// write editor content into "prev" element
document.getElementById( "prev" ).innerHTML = e.editor.getData();
}
);
});
});
For anyone who needs it, here's one way to get the TEXT value of an HTML field (used in this case for a dynamic character counter):
JS ...
CKEDITOR.replace( 'myDoc', {
width: 605,
height: 500
});
setInterval("updateCount()", 500);
function updateCount() {
var str = CKEDITOR.instances.myDoc.getData();
if (str) {
var element = CKEDITOR.dom.element.createFromHtml( str );
var no_html = element.getText();
$('#myDoc_length').html( no_html.length );
}
}
... with HTML ...
<textarea id="myDoc"></textarea>
<span id="myDoc_length">0</span> characters
Related
*UPDATE:I am new to jQuery, as well as using XPath, and I am struggling with getting a proper working solution that will blur a dynamically created HTML element. I have an .onblur event hooked up (doesn't work as expected), and have tried using the $(document.activeElement), but my implementation might be incorrect. I would appreciate any help in creating a working solution, that will blur this element (jqInput) when a user clicks anywhere outside the active element. I have added the HTML and jQuery/JavaScript below.
Some ideas I have had:
(1) Use XPath to select a dynamic HTML element (jqInput), and then use jQuery's .onClick method to blur a this element, when a user clicks anywhere outside of the area of the XPath selected element.
(2) Use the $(document.activeElement) to determine where the .onblur should fire:
var thisTitle = input0;
var activeElement = $(document.activeElement);
if (thisTitle != activeElement) {
jqInput.hide();
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
}
I am open to all working solutions. And hopefully this will answer someone else's question in the future.
My challenge: Multiple elements are active, and the .onblur does not fire. See the image below:
NOTE: The <input /> field has focus, as well as the <div> to the left of the (the blue outline). If a user clicks anywhere outside that <input />, the blur must be applied to that element.
My Code: jQuery and JavaScript
This is a code snippet where the variable jqInput and input0 is created:
var jqInput = null;
if (jqHeaderText.next().hasClass("inline-editable"))
{
//Use existing input if it already exists
jqInput = jqHeaderText.next();
}
else
{
//Creaet a new editable header text input
jqInput = $("<input class=\"inline-editable\" type=\"text\"/>").insertAfter(jqHeaderText);
}
var input0 = jqInput.get(0);
//Assign key down event for the input when user preses enter to complete entering of the text
input0.onkeydown = function (e)
{
if (e.keyCode === 13)
{
jqInput.trigger("blur");
e.preventDefault();
e.stopPropagation();
}
};
This is my .onblur event, and my helper method to blur the element:
input0.onblur = function ()
{
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
};
inputOnBlurHandler: function (canvasObj, jqHeaderText, jqInput)
{
// Hide input textbox
jqInput.hide();
// Store the value in the canvas
canvasObj.headingText = jqInput.val();
_layout.updateCanvasControlProperty(canvasObj.instanceid, "Title", canvasObj.headingText, canvasObj.headingText);
// Show header element
jqHeaderText.show();
_layout.$propertiesContent.find(".propertyGridEditWrapper").filter(function ()
{
return $(this).data("propertyName") === "Title";
}).find("input[type=text]").val(canvasObj.headingText); // Update the property grid title input element
}
I have tried using the active element, but I don't think the implementation is correct:
var thisTitle = input0;
var activeElement = $(document.activeElement);
if (thisTitle != activeElement) {
jqInput.hide();
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
}
My HTML code:
<div class="panel-header-c">
<div class="panel-header-wrapper">
<div class="panel-header-text" style="display: none;">(Enter View Title)</div><input class="inline-editable" type="text" style="display: block;"><div class="panel-header-controls">
<span></span>
</div>
</div>
</div>
I thank you all in advance.
I can see numerous examples on removing buttons in the tinymce editor but I want to do this for a custom editor I am adding from Javascript.
function myplugin_tinymce_buttons( $buttons ) {
//Remove the text color selector
$remove = 'forecolor';
//Find the array key and then unset
if ( ( $key = array_search( $remove, $buttons ) ) !== false )
unset( $buttons[$key] );
return $buttons;
}
There is no mention of editor ID here. How do I do this only for a custom editor? I dont want to change anything in the main editor shown in Wordpress post page.
The best and cleanest way is definitely to change your TinyMCE config before initialization.
Otherwise you can refer to my answer on another question where I set the editor in ReadOnly mode then enable just few buttons.
I didn't test this code but your function should be something like this:
function removeButton(editorId, pluginName, commandName) {
var htmlEditorDiv = document.getElementById(editorId).previousSibling;
var editor = tinymce.get(editorId);
var buttonDiv = htmlEditorDiv.querySelectorAll('.mce-i-' + pluginName.toLowerCase())[0].parentElement.parentElement;
buttonDiv.style.display = "none";
buttonDiv.firstChild.onclick = function () {
//Even if the button is invisible, it's better
//removing the command associated to the button click just in case
};
}
For the list of commands, refer to this page
I want to create a live HTML/CSS preview on a page.
But the code will not be given using textareas. The code is going to be fixed in the page (div).
I want the user to be able to alter the code and that will reflect on the live preview box.I have created the page where you can change parts of the script text (for amateurs). You can preview that here :
http://apolosiskos.co.uk/HTML-CSS-EDITOR/index3.html
01) The live preview does not work if I replace the textarea with a div.
02) Even if I use the textareas, the live preview does not work because in my HTML script I am using the codeand the xmp tags.
--> Snippet that works with a textarea but not with a div :
var wpcomment = document.getElementById('WPComment');
wpcomment.blur = wpcomment.onkeypress = function(){
document.getElementById('prevCom').innerHTML = this.value;
}
#prevCom
{
background:#124;
color:#fff;
min-width:20px;
min-height:50px;
font-size:25pt;
}
<textarea name="WPcomment" id="WPComment" placeholder="Add comments:">aaaaa</textarea>
<div id="prevCom"></div>
with no success. Is there any other addEventListener() method I can replace keyup with?
Yes, blur
If you would like to add keydown events on a <div> element, you can do the following:
First, you need to set the tabindex attribute:
<div id="a-div" tabindex="1" />
Then,
(2) Bind to keydown:
$('#mydiv').bind('keydown', function(event) {
//console.log(event.keyCode);
});
If you would like your div to be "focused" from the start:
$(function() {
$('#mydiv').focus();
});
You should place your preview code it within a function, then you can simply call it once the document has loaded.
https://jsfiddle.net/michaelvinall/4053oL1x/1/
The separate issue of your preview only rendering when you press the enter key, is because of the following if statement:
if(e.which == 13 && $(this).val().length > 0)
The e.which == 13 within your if is specifying that the code within the block should only be ran if the key pressed by the user was the enter key (code 13). By removing this portion of each if statement, any key pressed will execute the code within the block:
if($(this).val().length > 0)
Your function is call when keyup is trigger, but no after page load.
You must do it : Define function to call them when 2 different event are fired.
$(function() {
function GetHtml(){
var html = $('.html').val();
return html;
}
function GetCss(){
var Css = $('.css').val();
return Css;
}
var previewRendering = function(){
console.log('kikou');
var targetp = $('#previewTarget')[0].contentWindow.document;
targetp.open();
targetp.close();
var html = GetHtml();
var css = GetCss();
$('body',targetp).append(html);
$('head', targetp).append('<style>' + css + '</style>');
};
$('.innerbox').on("keyup",function(){
previewRendering();
});
$(document).ready(function() {
previewRendering();
});
});
This code can not work because load event is only compatible with this list of HTML tags: body, frame, iframe, img, input type="image", link, script, style
$('.innerbox').load(function()
I have a TinyMCE 4.x instance where the text should be in read only mode. But I still have some buttons that I want to have enabled. For example, one button could provide a character count for the part of the text I've selected.
But when I turn on read only mode for TinyMCE all buttons are disabled. Can I enable just my buttons while still retaining read only mode?
It's probably too late for you but other people may pass by here.
I came up by writing this function
function enableTinyMceEditorPlugin(editorId, pluginName, commandName) {
var htmlEditorDiv = document.getElementById(editorId).previousSibling;
var editor = tinymce.get(editorId);
var buttonDiv = htmlEditorDiv.querySelectorAll('.mce-i-' + pluginName.toLowerCase())[0].parentElement.parentElement;
buttonDiv.className = buttonDiv.className.replace(' mce-disabled', '');
buttonDiv.removeAttribute('aria-disabled');
buttonDiv.firstChild.onclick = function () {
editor.execCommand(commandName);
};
}
It does the trick in 2 steps:
make the button clickable (remove mce-disabled CSS class and remove the aria-disabled property)
assign the good command to the click event
And in my editor init event I call the function.
editor.on('init', function () {
if (readOnly) {
editor.setMode('readonly');
enableTinyMceEditorPlugin(htmlEditorId, 'preview', 'mcePreview');
enableTinyMceEditorPlugin(htmlEditorId, 'code', 'mceCodeEditor');
}
});
Current version of TinyMCE for which I wrote this code is 4.4.3. It may break in a future version, specifically about the selectors to get and modify the good HTML elements.
Command identifiers can be found at this page otherwise you can also find them under tinymce\plugins\PluginName\plugin(.min).js
Here is a simple way to enable your custom toolbar button and attach a click event handler inside a read only TinyMCE editor using JQUERY:
//Initialize read only Tinymce editor so that Lock button is also disabled
function initReadOnlyTinyMCE() {
tinymce.init({
selector: '#main'
, toolbar: 'myLockButton'
, body_class: 'main-div'
, content_css: 'stylesheets/index.css'
, readonly: true
, setup: function (readOnlyMain) {
readOnlyMain.addButton('myLockButton', { //Lock button is disabled because readonly is set to true
image: 'images/lock.png'
, tooltip: 'Lock Editor'
});
}
});
}
function displayReadOnlyTinyMCEwithLockButtonEnabled() {
var edContent = $('main').html();
$("#main").empty();
initReadOnlyTinyMCE(true);
tinyMCE.activeEditor.setContent(edContent);
//enable the lock button and attach a click event handler
$('[aria-label="Lock Editor"]').removeClass("mce-disabled");
$('[aria-label="Lock Editor"]').removeAttr("aria-disabled");
$('[aria-label="Lock Editor"]').attr("onclick", "LockEditor()");
}
function LockEditor() {
alert("Tiny mce editor is locked by the current user!!");
//Write your logic to lock the editor...
}
I couldn't find an easy way to do this. The simplest way is to remove the contenteditable attribute from the iframe body instead and substitute a read only toolbar set. It also means that people will still be able to copy content from the editor.
$("iframe").contents().find("body").removeAttr("contenteditable");
How about this :
editor.addButton('yourButton', {
title: 'One can Enable/disable TinyMCE',
text: "Disable",
onclick: function (ee) {
editor.setMode('readonly');
if($(ee.target).text() == "Disable"){
var theEle = $(ee.target).toggle();
var edit = editor;
var newBut = "<input type='button' style='opacity:1;color:white; background-color:orange;' value='Enable'/>";
$(newBut).prependTo($(theEle).closest("div")).click(function(e){
edit.setMode('design');
$(e.target).remove();
$(theEle).toggle();
});
}
}
});
You can try to run the code below:
$("#tinymce").contentEditable="false";
if you have more than one editors, you can use their id like below
$("#tinymce[data-id='idOfTheEditor']").contentEditable="false";
I create a textarea and a button on a loop based on a certain condition:
while($row_c= mysqli_fetch_array($result_comments))
{
//some code goes here
<textarea type="text" id="pm_text" name="text"></textarea><br>
<button name="send_comment" id="post_comment" class="button" onClick="post_pm_comment()">Post</button>
}
Now in my function "post_pm_comment" I would like to access the text written in the textarea when the post button is clicked.
I tried this, but it only gives me the text of the first textarea and button created:
function post_pm_comment(thidid, pm_id, path, pm,getter)
{
var pm_text = document.getElementById("pm_text").value;
}
What should I do?
Thank you
Your code is outputting an invalid DOM structure, because id values must be unique on the page. You cannot have the same id on more than one element. Remove the id values entirely, you don't need them.
Having done that, the minimal-changes answer is to pass this into your handler:
onClick="post_pm_comment(this)"
...and then in your handler, do the navigation:
function post_pm_comment(postButton)
{
var pm_text;
var textarea = postButton.previousSibling;
while (textarea && textarea.nodeName.toUpperCase() !== "TEXTAREA") {
textarea = textarea.previousSibling;
}
if (textarea) {
pm_text = textarea.value; // Or you may want .innerHTML instead
// Do something with it
}
}
Live Example | Source