Following uraimo's great response here I have managed to create a handler for making the text bold:
addHandler('bold', function (obj) {
var isBold = getStyle(obj, 'fontWeight') === 'bold';
setStyle(obj, 'textDecoration', isUnderline ? '' : 'underline');
});
It is attached to the button and it works fine whenever there is a portion of the text selected.
However, I need to also react on the button clicks when there is no text selected. Clicking a button in such case would result in bold text that is subsequently typed (just like hitting the "bold button" works in any text editor).
How can I do that?
You can bold text that is subsequently typed and also the one applied by setting the preperty of text
addHandler('bold', function (obj) {
var isBold = getStyle(obj, 'fontWeight') === 'bold';
var style = {};
style['fontwieight'] = isBold;
object.setSelectionStyles(style);
object.set('fontweight', isBold);
});
Related
I am using quill editor. suppose i have a select box where i can select value from it, so that it can be inserted into the quill editor. But I want the value to be inserted at the cursor, instead of at the end or beginning of the content.
Here you are, check out the codesandbox demo below:
https://codesandbox.io/s/hidden-brook-m2m80?file=/src/app/app.component.ts
Bind the reference of quill editor
#ViewChild(QuillEditorComponent, { static: true })
editor: QuillEditorComponent;
Get the cursor position and insert text
onChangeOption(key: string) {
const index = this.editor.quillEditor?.getSelection()?.index; // get cursor position
if (index !== undefined) {
this.editor.quillEditor?.insertText(index, key); // insert text after the index
}
}
//to get the index of selection
var range = quill.getSelection();
//to insert the text at cursor
quill.insertText(range.index, text, 'bold', true);
I am using textarea for making an editor and wanna implement bold, italic or hyperlink to a selected text. Right now, if I am making it bold or italic, the effect is in entire box. I wanna restrict it and keep it to selected text only. I am able to get the selected text from the textarea, I am not able to make it bold or italic or put a link on the selected task as document.execCommand doesn't work in reactjs.
I am getting the selected text from textarea through getSelectionTxt() function but with this text_to_hyperlink it is replacing the entire text with anchor tags and url.
I want to have that link to be associated with the selected tags. I am invoking this text_to_hyperlink with a button.
text_to_hyperlink=()=> {
var text_entry = document.getElementById('textArea');
var text_selected = this.getSelectionTxt();
var url = document.getElementById("url").value;
text_entry.value = '' + text_selected + '' ;
}
getSelectionTxt =() => {
var text = "";
var activeEl = document.activeElement;
if (activeEl == "textarea") {
text = activeEl.value.slice(activeEl.selectionStart, activeEl.selectionEnd);
} else if (window.getSelection) {
text = window.getSelection().toString();
}
var url = document.getElementById("url").value;
return text;
}
<textarea
id="textArea"
contenteditable="true"
rows="10"
value={this.state.value}
onClick={this.getSelectionTxt}
onChange={this.handleChange}
/>
You can't do this with a textarea element: they support plaintext only, and not HTML. You will have to use a different element with contenteditable="true". I prefer div, but others work as well.
A textarea element cannot render HTML. You could either use a WYSIWYG editor compatible with React like one of these:
1) Medium-Editor - https://github.com/yabwe/medium-editor
2) Draft.js - https://draftjs.org/
or use a <div> with contentEditable=true and render HTML inside of it.
In WordPress I have added a custom editor button to get the contents of a selection and wrap it in a shortcode. The content is not getting the tags surrounding the selection.
For example:
<h1>Heading text</h1>
becomes
<h1>[shortcode]Heading Text[/shortcode]</h1>
Not
[shortcode]<h1>Heading Text</h1>[/shortcode]
It does work for
<h1>Header</h1>
<h2>Sub-Header</h2>
becomes
[shortcode]<h1>Header</h1>
<h2>Sub-Header</h2>[/shortcode]
This is the code I have.
(function() {
tinymce.create('tinymce.plugins.zgwd', {
init : function(ed, url) {
ed.addButton('headerblock', {
title : 'Add a Header Block',
cmd: 'headerblock',
});
ed.addCommand('headerblock', function() {
var selected_text = ed.selection.getContent({ format: 'html' });
var return_text = '';
if( !(selected_text && selected_text.length > 0) ) {
selected_text = 'Add header block text here';
}
return_text = '[header-block]' + selected_text + '[/header-block]';
ed.execCommand('mceInsertContent', 0, return_text);
});
},
createControl : function(n, cm) {
return null;
},
});
tinymce.PluginManager.add('zgwd', tinymce.plugins.zgwd);
})();
How can I get the content including the <h1> tags (or similar). Am I using the wrong function to get the content or is there a setting I am missing somewhere? I tried .getnode() but get the same result.
If you want to do something with a single block tag, getNode is your best bet. If you look at this Fiddle with the console open in Dev Tools, try selecting one line, and then try selecting both. getNode() and getContent() behave a little differently based on selection.
getNode() Returns the selected element, but, if you have more than one element selected, it returns the common ancestor (in this case body).
getSelection() will return tags if you select multiple blocks, which is why it works when trying to surround more than one block tag.
JSfiddle for reference: https://jsfiddle.net/9jp346r4/20/
I am trying to create functionality that allows user to highlight the selected text upon pressing a button, and unhighlight the highlighted text upon right-clicking.
I've gotten it mostly working using the rangy library except there's one scenario that doesn't work and I'm not sure how to solve it.
When I highlight text that is in 2 different paragraphs, it highlights it successfully.
The issue arises when I would like to come back later and un-highlight both the paragraphs.
The expected behaviour is: I right-click any highlighted text regardless of if it is selected or not and it will un-highlight all nearby highlighted text even if it's separated by a paragraph tag or strong tag.
The current behaviour is: It only unhighlights the text in the paragraph I clicked.
To re-produce:
1) Select text that overlaps both the first and second paragraph and press the "Press" button.
2) Un-select the selected text by clicking somewhere else on the screen.
3) Right-click any of the highlighted text. Notice only one of the paragraphs gets un-highlighted.
If something is unclear, feel free to ask questions. Would appreciate the help.
Here is my HTML:
<div id="content">
<p>
Paragraph 1
</p>
<p>
Paragraph 2
</p>
</div>
<div id="divId">
<input id="myBtn" type="button" value="Press" onclick = "javascript:toggleItalicYellowBg()"/>
</div>
Here is my javascript:
function coverAll() {
var ranges = [];
for(var i=0; i<window.getSelection().rangeCount; i++) {
var range = window.getSelection().getRangeAt(i);
while(range.startContainer.nodeType == 3
|| range.startContainer.childNodes.length == 1)
range.setStartBefore(range.startContainer);
while(range.endContainer.nodeType == 3
|| range.endContainer.childNodes.length == 1)
range.setEndAfter(range.endContainer);
ranges.push(range);
}
window.getSelection().removeAllRanges();
for(var i=0; i<ranges.length; i++) {
window.getSelection().addRange(ranges[i]);
}
return true;
}
function getSelectedText() {
if (window.getSelection) {
return window.getSelection().toString();
} else if (document.selection) {
return document.selection.createRange().text;
}
return '';
}
var italicYellowBgApplier;
function toggleItalicYellowBg() {
italicYellowBgApplier.toggleSelection();
}
window.onload = function() {
$(document).on("contextmenu", ".italicYellowBg", function(e){
if(coverAll()) {
italicYellowBgApplier.undoToSelection();
return false;
}
});
rangy.init();
// Enable buttons
var classApplierModule = rangy.modules.ClassApplier;
// Next line is pure paranoia: it will only return false if the browser has no support for ranges,
// selections or TextRanges. Even IE 5 would pass this test.
if (rangy.supported && classApplierModule && classApplierModule.supported) {
italicYellowBgApplier = rangy.createClassApplier("italicYellowBg", {
tagNames: ["span", "a", "b", "img"]
});
}
};
I guess to easy solve this problem, in memory keep an array of user highlights, one item of that array is not a single highlight item, but a further "selection of selected items during the highlight", when somebody would right click on a single segment of highlight, in-memory find from array all associated highlights and unhighlight the related segments by yourself.
I can simulate text selection with protractor by a lot of different ways. But I can't find solution how I can expect that text was really selected. How I can do this without using marking?
I can simulate select text by protractor with:
DragAndDrop function (mouse)
Combination: browser.actions().sendKeys(protractor.Key.CONTROL, 'a').perform();
Combination: shift + left arrow
Elaborating Michael's comment into a working example.
In the following demo example, we are navigating to the AngularJS website, sending "testing" text to the search input on the top right, pressing left arrow 3 times to move the cursor 3 characters to the left, then pressing SHIFT + ARROW_RIGHT keyboard combination 2 times to select the next 2 characters - which is in:
Finally, we are applying the solution to get the selection text provided here and asserting:
describe("Get selection text", function () {
beforeEach(function () {
browser.get("https://angularjs.org/");
});
it("should input 'testing', select 'in' and assert it is selected", function () {
var q = element(by.name("as_q"));
// enter 'testing' and go 3 chars left
q.sendKeys("testing")
.sendKeys(protractor.Key.ARROW_LEFT)
.sendKeys(protractor.Key.ARROW_LEFT)
.sendKeys(protractor.Key.ARROW_LEFT);
// select 2 chars to the right
browser.actions()
.keyDown(protractor.Key.SHIFT)
.sendKeys(protractor.Key.ARROW_RIGHT)
.sendKeys(protractor.Key.ARROW_RIGHT)
.keyUp(protractor.Key.SHIFT)
.perform();
// get highlighted text
var highligtedText = browser.executeScript(function getSelectionText() {
var text = "";
if (window.getSelection) {
text = window.getSelection().toString();
} else if (document.selection && document.selection.type != "Control") {
text = document.selection.createRange().text;
}
return text;
});
expect(highligtedText).toEqual("in");
});
});
Hope this would help you and others coming here.
Here you might also need to verify that the text inside a particular text box is selected. You can do that by using these 2 lines below:
*document.evaluate( 'XpathOfTheElement//input', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue.selectionStart
document.evaluate( 'XpathOfTheElement//input', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue.selectionEnd*
if 'in' is selected in the string 'testing' then first line will return 4 and second line will return 6.