CKEditor 5-insert html and move the caret outside it - javascript

i have a button outside ckeditor, when clicked i want to insert a span element at caret position, this is what i have so far:
var el = document.querySelector('#editor');
ClassicEditor.create(el, {
licenseKey: ''
}).then( editor => {
appConfigs.editor = editor; //storing the editor for later usage
}).catch( error => {
//...
});
when the button is clicked i do:
function clickHandler(){
var editor = appConfigs.editor;
editor.model.change( writer => {
var html = '<span class="special-class-name" data-name="something">special word or button</span>';
var viewFragment = editor.data.processor.toView(html);
var modelFragment = editor.data.toModel(viewFragment);
var insertPosition = editor.model.document.selection.getFirstPosition();
editor.model.insertContent(modelFragment, insertPosition);
});
}
the code have the following issues:
1)the inserted span get stripped off all its attributes(class, data-name) which i want to preserve.
2)the editing caret doesn't go back automatically to the editor when the button clicked.
3)when i click the editor to restore caret and start typing, i noticed it edits the text inside inserted span, i want inserted span to be untouched and any further typing goes after it.
i will be so grateful if anyone could help me with those issues.

Related

I am trying to replace the selected word in Quill Library with an ID from an Input that I create dynamically ANGULAR

Change the selected word "TEST" with the ID of the Input "1"
With this code I am able to get the selected word and actually replace it with a hard coded dummy text but that only happens when I click inside the editor..
replaceSelection(event) {
var range = this.quill.getSelection();
if (range) {
if (range.length == 0) {
console.log('User cursor is at index', range.index);
} else {
var text = this.quill.getText(range.index, range.length);
console.log('User has highlighted: ', text);
this.quill.deleteText(range.index, range.length);
var clickedElement = event.target;
console.log(`clickedElement`, clickedElement)
// Get the id of the clicked element
var id = event.target.id;
console.log(`id:`);
this.quill.insertText(range.index, '{{' + id + '}}');
}
} else {
console.log('User cursor is not in editor');
}
}
}
When I click the Input ID this line is called:
console.log('User cursor is not in editor');
As said in API docs .getSelection will return null if editor has no focus. When you click on button that is not inside editor, you lose focus from editor.
However you can provide first argument, that will focus editor before getting selection range.
You just need to change your code to:
var range = this.quill.getSelection(true);
Editor will retain previous selection.

How to display current html page with js onclick?

I am currently trying to implement the page layout change with js onclick of the function, and the question is, how do I make the js display the current body html?
The logic is as following:
first I have my page html and the body dom, then I have the script where I define that if you click on the button then you have different content displayed, using the pageLayout.innerHTML = "<p>this is the new content</p>".
But how do I make the js display back the last content, or be back to the content that is defined on top of the script in the body without copy pasting it twice in the end with the same function?
You can store the previous content in a global variable, before making any changes.
So if you want the same button to revert the content you can do something like this:
let previousContent = "";
function handleClick() {
// Find the element that you want to change its content
const pageLayout = document.getElementById("layout");
// Check if there is any stored content
if(previousContent) {
pageLayout.innerHTML = previousContent;
//Clear the stored content
previousContent = "";
} else {
// Store the previous content
previousContent = pageLayout.innerHTML;
//Create the new content
const newContent = " your new content";
//Update the content
pageLayout.innerHTML = newContent;
}
}
const button = document.getElementById("my-button-id");
button.addEventListener("click", handleClick);

Highlight Selected text with different color for each tag

Text Selection and highlighting is not working when I want to select the text on clicking of a dynamic button, but it works when I directly select the text from paragraph (on mouseup) itself. (see JSFiddle for complete code)
I have generated dynamic buttons for each tag with various color, eg. Tag1-Green, Tag2-Blue, Tag3-Red,...etc
So when user clicks on :
Tag1 button, selected text from the paragraph should get highlighted in the green color
Tag2 button, selected text from the paragraph should get highlighted in the blue color
Tag3 button, selected text from the paragraph should get highlighted in the red color
...etc
var getSelectedText = function() {
var selectedRange ="";
try {
if (window.getSelection) {
selectedRange = window.getSelection().getRangeAt(0);
} else {
selectedRange = document.getSelection().getRangeAt(0);
}
} catch (err) {
console.log(err)
}
return selectedRange
};
function highlight(){
//Below Commented code works fine
// $("p.raw_text").on("mouseup", function(e) {
// e.preventDefault()
// var selection = getSelectedText();
// alert("Selection: " + selection);
// });
//But this code does not work as buttons with id that starts with highlight are dynamically generated
$(document).on('click', '[id^=highlight]', function(e) {
e.preventDefault()
var selection = getSelectedText();
alert("Selection: " + selection);
});
}
$(function(){
highlight();
});
P.S Highlighting of the text is not yet implemented as I am not getting the selected text to highlight it..
EDIT
Note - I am trying to build a data annotation tool to annotate my machine learning training data. What it does is, it allows users to select the NER text to be annotated and mark it with specific label(or tag). Ex. selected text could be a person's name from the paragraph, then user should click on the Tag (Person) and highlight the selected text from the paragraph with some color, similarly there could be any number of Tags(labels) in the paragraph such as organization, city, country, etc User should be able to highlight each NER with specific color. (which further, I will pass that resultant data along with its highlighted indexes to build a machine learning model.)
Below code perfectly worked for me as I moved button click inside paragraph click.
function highlight(){
$(document).on('click', 'p.raw_text', function(e) {
e.stopPropagation()
var selectedRange = getSelectedText()
$(document).off('click', '[id^=highlight]')
$(document).on('click', '[id^=highlight]', function(ev) {
var text = selectedRange.toString();
if(!text)return;
console.log(selectedRange.toString())
hiliter(text, e.target, $(ev.target).data())
});
});
}
function hiliter(word, element, data) {
console.log("data", data.color)
var rgxp = new RegExp(word, 'g');
var repl = '<span style="background-color:'+ data.color +';">' + word + '</span>';
element.innerHTML = element.innerHTML.replace(rgxp, repl);
}
P.S- With my little knowledge of jquery, I am not sure if I am doing it right way. Please verify someone. Thank you

Append HTML Tag Into Codemirror and Center Cursor Location

Fiddle - http://liveweave.com/kzBlq3
I'm trying to add custom html tags into CodeMirror and focus the cursor into the center of these tags.
Here's an example of how it'd be done for a textarea.
// Mirror Codemirror Code to Textarea
$(".code").val( editor.getValue() ).on('keyup change', function() {
editor.setValue( $(this).val() );
});
// Add center code
$(".bold").click(function() {
// For a regular textarea & center cursor
var start = $('.code').get(0).selectionStart;
$('.code').val($('.code').val().substring(0, start) + "<strong></strong>" + $('.code').val().substring($('.code').get(0).selectionEnd));
$('.code').get(0).selectionStart = $('.code').get(0).selectionEnd = start + 8;
$('.code').focus();
return false;
});
The lines and locations will always be different so I have to grab it's location first before I add and move it aside the added characters as I did with the textarea demo.
However I don't want to use a blank textarea. I want to use Codemirror.
I can add the html tag without a problem, but getting the cursor location inside of the appended tag is where I'm having trouble.
editor.replaceRange("<strong></strong>", editor.getCursor());
Add the following code to move cursor to center of tag. Also I updated your code, Please use the below link for accessing it
http://liveweave.com/LLq9GS
$(".bold").click(function() {
// For codemirror & center cursor
editor.replaceRange("<strong></strong>", editor.getCursor());
editor.focus();
var str="</strong>";
var mynum=str.length;
var start_cursor = editor.getCursor(); //I need to get the cursor position
console.log(start_cursor); //Cursor position
var cursorLine = start_cursor.line;
var cursorCh = start_cursor.ch;
//Code to move cursor back [x] amount of spaces. [x] is the data-val value.
editor.setCursor({line: cursorLine , ch : cursorCh -mynum });

Html Code not working properly while generated with JavaScript

I am trying to impliment the IN Place Editing functionality using JQuery.
Here is the code
editinplace.js
$(document).ready(function() {
//When div.edit me is clicked, run this function
$("div.editme").click(function() {
//This if statement checks to see if there are
//and children of div.editme are input boxes. If so,
//we don't want to do anything and allow the user
//to continue typing
if ($(this).children('input').length == 0) {
//Create the HTML to insert into the div. Escape any " characters
var inputbox = "<input type='text' class='inputbox' value=\""+$(this).text()+"\">";
//Insert the HTML into the div
$(this).html(inputbox);
//Immediately give the input box focus. The user
//will be expecting to immediately type in the input box,
//and we need to give them that ability
$("input.inputbox").focus();
//Once the input box loses focus, we need to replace the
//input box with the current text inside of it.
$("input.inputbox").blur(function() {
var value = $(this).val();
$(".editme").text(value);
});
}
});
});
ButtonClickFunction.js
function ADDRADIOBUTTON(){
//Creating the div Tag
var answer_div = document.createElement("div");
answer_div.setAttribute("class", "answer");
answer_div.id = "answer_div_"+counter;
// Creating the Radio button tag
var answer_tag = document.createElement("input");
answer_tag.setAttribute("type", "radio");
answer_tag.id = "answer_tag_"+counter;
answer_tag.setAttribute("name", answer_div.id);
// Creating the Label Tag
var radio_label_tag = document.createElement("label");
radio_label_tag.setAttribute("for", answer_tag.id);
//Creating the label
var In_Place_Edit_div = document.createElement("div");
In_Place_Edit_div.setAttribute("class", "editme");
var In_Place_Edit = document.createTextNode("label");
In_Place_Edit_div.appendChild(In_Place_Edit);
radio_label_tag.appendChild(In_Place_Edit_div);
// Adding Radio button dot on the div and screen actually
answer_div.appendChild(answer_tag);
//Adding the Label here on the right of radio button.
answer_div.appendChild(radio_label_tag);
// Adding Answer div to the main div
var element=document.getElementById("divid_"+counter);
element.appendChild(answer_div);
}
and the index.php file includes these two JS files along with jquery-1.8.2.min.js
<script language="javascript" src="js/jquery-1.8.2.min.js"></script>
<script language="javascript" src="js/editinplace.js"></script>
<script type="text/javascript" src="js/ButtonClickFunction.js"></script>
What I am trying to do is create a radio button with label besides it and the label can be edited when we click on it. Now the problem here is that when I use the Code
<div class="editme">Please click me!!</div>
directly in the index.html page it works fine but when I try to generate the same line of code dynamically as I shown in ButtonClickFuction.js file it Does not work. What might be the problem ?
After crerating the HTML element dynamically you must bind the click function once more.Otherwise it wont work.Just call the click function after dynamic creation of the
< div class="edttime">Please click me!!.Otherwise click wont work for the newly created div with class edttime.
$("div.editme").click(function() {
//This if statement checks to see if there are
//and children of div.editme are input boxes. If so,
//we don't want to do anything and allow the user
//to continue typing
if ($(this).children('input').length == 0) {
//Create the HTML to insert into the div. Escape any " characters
var inputbox = "<input type='text' class='inputbox' value=\""+$(this).text()+"\">";
//Insert the HTML into the div
$(this).html(inputbox);
//Immediately give the input box focus. The user
//will be expecting to immediately type in the input box,
//and we need to give them that ability
$("input.inputbox").focus();
//Once the input box loses focus, we need to replace the
//input box with the current text inside of it.
$("input.inputbox").blur(function() {
var value = $(this).val();
$(".editme").text(value);
});
}

Categories