selected text editing - javascript

I am a iPhone app developer.I am changing the color of selected text. This is working fine for me. But when there are few repeated words for example
Hi All.Hello world.I am iPhone app developer.Hello world.Stack overflow.Hello world.
Here 'Hello' text is repeating. When i am selecting last 'Hello' text it is giving me first 'Hello' text index. I tried indexOf(),search() and anchorOffset() but this is not working.
Following is my code.
function heighlightText(data) {
var selectedText = window.getSelection();
var textd=$("#data").html(); // this will give me whole text.
var normalText = $("#data").text();
var startPosition = normalText.search(selectedText); // this will give selected text start position.
var getPosition = selectedText.toString();
var endPosition = parseInt(getPosition.length) + parseInt(startPosition); // this will give selected text end position.
var textToReplace = "<span id='" + startPosition + "' class='highlightedText' onclick=\"myOnclikFunction('"+selectedText+"')\"> "+selectedText+"</span>";
var startPart = textd.substr(0,startPosition);
var lastPart = textd.substr(endPosition,textd.length);
var reT = startPart + textToReplace + lastPart;
$("#data").html(reT);
}
Hy HTML:
<style type = "text/css">
#data {
font-size : 20px;
color : black;
}
.highlightedText {
background-color : red;
}
</style>
<body>
<div id = "data" >Lots of text here...
<div/>
</body>
Can any one suggest solution for this.
Thanks in advance.

If you're just colouring the text, then Stefan's answer is the most reliable and easiest way:
document.execCommand("ForeColor", false, "#0000FF");
However, it looks as though you're adding a class and a click handler, so you need more flexibility.
First, there is no way to get a selection as offsets within an HTML representation of the DOM reliably. You can get the selection as offsets within nodes directly via anchorOffset, anchorNode, focusOffset and focusNode, or as a DOM range. If the selection is completely contained within a single text node, you can use the range's surroundContents() method:
Demo: http://jsfiddle.net/UvBTq/
Code:
function highlightText(data) {
var selection = window.getSelection();
if (selection.rangeCount > 0) {
var range = selection.getRangeAt(0);
var selectedText = range.toString();
var span = document.createElement("span");
span.id = "span_" + range.startOffset + "_" + range.endOffset;
span.className = "highlightedText";
span.onclick = function() {
myOnclikFunction(selectedText);
};
range.surroundContents(span);
// Restore selection
selection.removeAllRanges();
selection.addRange(range);
}
}
However, this is very brittle and will only work when the selection is completely contained within a single text node. Depending on what you're trying to do, you may need a more flexible solution.

To get the selected text, you have to use the getSelection javascript method. i don't know if that method is available on iphone browser, but here is a general function that combines the methods for all browsers.
function getSelected() {
var text = "";
if (window.getSelection
&& window.getSelection().toString()
&& $(window.getSelection()).attr('type') != "Caret") {
text = window.getSelection();
return text;
}
else if (document.getSelection
&& document.getSelection().toString()
&& $(document.getSelection()).attr('type') != "Caret") {
text = document.getSelection();
return text;
}
else {
var selection = document.selection && document.selection.createRange();
if (!(typeof selection === "undefined")
&& selection.text
&& selection.text.toString()) {
text = selection.text;
return text;
}
}
return false;
}
found here

Use contenteditable="true" and document.execCommand('ForeColor', false, 'YOURCOLOR'); instead
Example:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>- jsFiddle demo</title>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.2.js'></script>
<script type='text/javascript'>
$(function () {
$('#color').click(function () {
document.execCommand('ForeColor', false, '0000FF');
});
});
</script>
</head>
<body>
<p contenteditable="true">Hello world</p>
<button id="color">Change Color</button>
</body>
</html>
Fiddler: http://jsfiddle.net/WQKCw/1/

Related

Disable tab key blur in focused contentEditable

I'm fully aware that this question looks like a duplicate, but it isn't. Please read.
I have a div tag with the attribute contentEditable="true". I'm trying to make it so I can use the tab key inside the div without it moving focuses. Here's some code I have that doesn't fully fix the problem:
var tab = function(id){
if(event.keyCode === 9){
event.preventDefault();
document.getElementById(id).innerHTML += " ";
setCaretPos(id);
}
}
var setCaretPos = function(id){
var node = document.getElementById(id);
node.focus();
var textNode = node.firstChild;
var caret = textNode.length;
var range = document.createRange();
range.setStart(textNode, caret);
range.setEnd(textNode, caret);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
That is basically just adding four spaces to the end of the value of the text inside the div, then moving the caret to the end. That becomes a problem when I use tabs on other lines, because it will just add the tab to the end (If I'm not already on the last line).
So, I want to insert the four spaces where the caret is. This is where the trouble comes. I'll show the code, but I'm not sure what I'm doing wrong. I want it to add the four spaces to the text before the caret, then add all the text after the caret. Here's the code:
var insertTabAtCaret = function(id){
if(event.keyCode === 9){
event.preventDefault();
var box = document.getElementById(id);
if(box.selectionStart || box.selectionStart == "0"){
var startPos = box.selectionStart;
var endPos = box.selectionEnd;
box.innerHTML.substring(0, startPos) + " " + box.innerHTML.substring(endPos, box.innerHTML.length);
}
}
}
Please help! Let me know how I can achieve tabbing in a contentEditable div using the method described above! (I would prefer it in normal JavaScript, but jQuery is permissible. Please, don't tell me about libraries, plugins, extensions, etc. I don't want to use any of those.)
document.querySelector("div").addEventListener("keydown",insertTabAtCaret);
function insertTabAtCaret(event){
if(event.keyCode === 9){
event.preventDefault();
var range = window.getSelection().getRangeAt(0);
var tabNode = document.createTextNode("\u00a0\u00a0\u00a0\u00a0");
range.insertNode(tabNode);
range.setStartAfter(tabNode);
range.setEndAfter(tabNode);
}
}
div#editor{
height: 200px;
width:80%;
border: solid
}
<div contenteditable id="editor">
some text
</div>

Add html tags around highligted text in contenteditable div

I have a contenteditable div and i would like to add some html tags around highlighted text, after user select the text and click the button..
Here is the sample code. It has some javascript codes but i couldnt make it work as desired. And i played with a lot actually.
https://codepen.io/anon/pen/ybzzXZ
P.S. I'm going to add , or like html tags after when we solve the how to add html tags around it.
Some of that js codes which i found in stackoverflow.
function getSelectionText() {
var text = "";
if (window.getSelection) {
text = window.getSelection().text;
} else if (document.selection && document.selection.type != "Control") {
text = document.selection.createRange().text;
}
return text;
}
and the other one is
function replaceSelectionWithHtml(html) {
var range;
if (window.getSelection && window.getSelection().getRangeAt) {
range = window.getSelection().getRangeAt(0);
range.deleteContents();
var div = document.createElement("div");
div.innerHTML = html;
var frag = document.createDocumentFragment(), child;
while ( (child = div.firstChild) ) {
frag.appendChild(child);
}
range.insertNode(frag);
} else if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
range.pasteHTML(html);
}
}
There are several challenges with the problem you present.
First off you need to gather the selected text value. You have posted some examples of that - that is fairly well documented elsewhere so I will leave that up to you to isolate that issue.
Next you need to highlight the selected text. Often to highlight something in HTML we wrap that text that we wish to highlight in a simple element such as a span, then give that span some class - for example often this is used to give a background color to some text. <span style='background-color:yellow'>some text</span> - not so difficult to understand that portion.
The challenge with this then is to combine your "discovered text" with the highlight. Pretty easy to wrap that text as in the span example provided earlier. One issue however is that if that text is previously within some other HTML elements, we need to ensure that the text choice in the discovery is for example not contained within another element AND if so, handle that issue. Let's illustrate that with this span: Howdy <span style='background-color:yellow'>some text</span> Some more.
Now for this example suppose we wish to highlight the text "Howdy some" - a portion of that text is previously within a span with our desired markup, thus we must first extract that, remove that "highlight" and henceforth highlight the new text "choice" of "Howdy some".
To provide an illustration of that. Type the words "This I want" into the text box and see how it gets highlighted.
This is not exactly your problem however it provides the "highlight" which you could potentially combine with your selector. I have NOT fully vetted this for bugs such as typing in HTML in to "highlight".
/* highlight words */
function findStringLimit(searchChar, searchCharIndex, searchedString) {
return searchedString.substring(0, searchedString.lastIndexOf(searchChar, searchCharIndex));
};
function highlightWords(wordsy, text) { /* eliminate a bug with parenthesis */
wordsy = wordsy.replace("(", "");
wordsy = wordsy.replace(")", ""); /* escape other characters for bug */
text = text.replace(";", "");
text = text.replace("'", "'");
text = text.replace("<", "<");
text = text.replace(">", ">");
text = text.replace("<span", "<span");
text = text.replace('autoCompleteWord">', 'autoCompleteWord">');
text = text.replace("</span", "</span");
text = text.replace('span>', 'span>');
var re = '(' + wordsy + ')(?![^<]*(?:<\/span class=\"autoCompleteWord\"|>))';
var regExp = new RegExp(re, 'ig');
var sTag = '<span class="autoCompleteWord">';
var eTag = "</span>";
return text.replace(regExp, sTag + '$&' + eTag);
};
function parseAndHighlight(wordstring, htmlString) {
var htmlStringUn = htmlString;
var found = htmlStringUn.toLowerCase().indexOf(wordstring.toLowerCase(), 0);
if (found >= 0) {
htmlStringUn = highlightWords(wordstring, htmlStringUn);
}
else {
//split and parse the beast
var words = wordstring.split(/\W+/);
var allPhrases = [];
allPhrases.push(wordstring);
var i = 0;
i = words.length;
while (i--) {
allPhrases.push(findStringLimit(" ", allPhrases[(words.length - i) - 1].length, allPhrases[(words.length - i) - 1]));
};
i = allPhrases.length;
while (i--) {
if (allPhrases[i] != "") words = words.concat(allPhrases[i]);
};
i = words.length;
while (i--) {
htmlStringUn = highlightWords(words[i], htmlStringUn);
};
};
return htmlStringUn;
}
$(document).on('change', '#myInput', function() {
var myValue = $('#myInput').val(); //get what was typed
$('#found').text(myValue);
myValue = myValue.replace(/^\s+|\s+$/g, ""); //strip whitespace on ends
$('#found').text(myValue + ':stripped:');
var showText = $('#origshower').text();
var newShowString = parseAndHighlight(myValue, showText); //my original highlighter
$('#shower').html(newShowString);
});
#holder{border:red solid 2px; padding: 5px;}
#myInput{width:200px; background-color: aqua;}
span.autoCompleteWord /* this is the word(s) found */
{
font-weight: bold;
background-color: yellow;
}
#shower{border:lime 2px solid;}
<script
src="https://code.jquery.com/jquery-1.12.4.min.js"
integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
crossorigin="anonymous"></script>
<div id='holder'>
<input id='myInput' type='text' cols='60' rows='2' />Enter Text to match
</div>
<div id='origshower'>This is the span thistle with the whistle that I want matched is this neat</div>
<div id='shower'>none</div>
<div id='found'>enter</div>
You can just call executeCommand with formatBlock. You can find more information here:
https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand

assign selected text to a variable in designMode

I have a piece of code that sets the document to designMode and then operates on pieces of selected text using the document.execCommand() function.
It provides various functionality - for example it allows the user to turn a selected line of text to bold or italic (essentially the functionality of a text editor like this one that I am typing into now).
Here is a simplified example of the code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div>
This is some text - highlight a section of it and press h1 then li
</div>
<button onclick="setToHeader()" id="h1" style="width:100px" unselectable="on">h1</button>
<button onclick="setToList()" id="li" style="width:100px" unselectable="on">li</button>
<script>
document.designMode = 'on';
function setToHeader() {
document.execCommand('formatBlock', false, 'h1');
}
function setToList() {
document.execCommand('insertUnorderedList', false, null);
}
</script>
</body>
</html>
My problem here is that I do not want to be able to use the li button - i.e. convert the selected text to list format, when it is already converted into heading format with the h1 button.
I think I want to be able to read the selected text and simply check it with something like:
// var selectedText = ???
var isHeading = selectedText.search('h1') > -1
Is this the way, or is there a better approach?
How can I get hold of the relevant selected text and assign it to a variable?
You need a little bit more effort. Need to use jquery also, check it out:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div>This is some text - highlight a section of it and press h1 then li </div>
<div>This is some other text - highlight a section of it and press h1 then li </div>
<button onclick="setToHeader()" id="h1" style="width:100px" unselectable="on">h1</button>
<button onclick="setToList()" id="li" style="width:100px" unselectable="on">li</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script>
document.designMode = 'on';
setInterval(function () {
var el = getSelectionContainerElement();
if($(el).is('h1')){
$("#li").attr("disabled", true);
}
else
{
$("#li").attr("disabled", false);
}
}, 100);
function setToHeader() {
document.execCommand('formatBlock', false, 'h1');
}
function setToList() {
document.execCommand('insertUnorderedList', false, null);
}
function getSelectionContainerElement() {
var range, sel, container;
if (document.selection && document.selection.createRange) {
// IE case
range = document.selection.createRange();
return range.parentElement();
} else if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt) {
if (sel.rangeCount > 0) {
range = sel.getRangeAt(0);
}
} else {
// Old WebKit selection object has no getRangeAt, so
// create a range from other selection properties
range = document.createRange();
range.setStart(sel.anchorNode, sel.anchorOffset);
range.setEnd(sel.focusNode, sel.focusOffset);
// Handle the case when the selection was selected backwards (from the end to the start in the document)
if (range.collapsed !== sel.isCollapsed) {
range.setStart(sel.focusNode, sel.focusOffset);
range.setEnd(sel.anchorNode, sel.anchorOffset);
}
}
if (range) {
container = range.commonAncestorContainer;
// Check if the container is a text node and return its parent if so
return container.nodeType === 3 ? container.parentNode : container;
}
}
}
</script>
</body>
</html>
You can get hold of the selected text using the selection object.
e.g. in IE11:
getSelection()
Full documentation can be found here:
https://msdn.microsoft.com/en-us/library/ms535869(v=vs.85).aspx

Remove highlight added to selected text using JavaScript?

I highlighted selected text using JavaScript with the following code:
var sel = window.getSelection();
if(!sel.isCollapsed) {
var range = sel.getRangeAt(0);
sel.removeAllRanges();
document.designMode = "on";
sel.addRange(range);
document.execCommand("HiliteColor", false, "#ffffcc");
sel.removeAllRanges();
document.designMode = "off";
}
How do I then remove the highlighted color and restore the text?
Here's some code to add and remove highlights. It's too long to post here practically, so I've made a demo and posted a snippet below. It's not quite ideal because the unhighlight() function doesn't remove <span> elements inserted by the highlight command, but with a little care this would be a possible addition.
Live demo: http://jsfiddle.net/timdown/Bvd9d/
Code snippet:
function unhighlight(node, colour) {
if (!(colour instanceof Colour)) {
colour = new Colour(colour);
}
if (node.nodeType == 1) {
var bg = node.style.backgroundColor;
if (bg && colour.equals(new Colour(bg))) {
node.style.backgroundColor = "";
}
}
var child = node.firstChild;
while (child) {
unhighlight(child, colour);
child = child.nextSibling;
}
}
You could use CSS instead:
<style>
::selection {background-color: #ffffcc;}
</style>
EDIT: Update in response to comment and clarification
<script type="text/javascript">
var spans = document.getElementsByTagName('span'), i;
for( i=0; i<spans.length; i++) {
if( spans[i].style.backgroundColor == "#ffffcc") {
// Two alternatives. This:
spans[i].style.backgroundColor = "transparent";
// OR this, if spans contain only text:
spans[i].parentNode.replaceChild(spans[i].firstChild,spans[i]);
i--;
// End alternatives - only include i-- in the second one
}
}
</script>
Although, this fails in some browsers (I think it's Firefox) where the element style is changed to the computed style.
Use
sel.removeAllRanges()

How do I highlight and change a part of a textarea

I have a textarea where when the user selects and presses enter I want it to change to something else. For example I have a textarea, when a user selects something like NY, I want those two letters to change to NY
Here's a fiddle but I'm lost
I have something like :
$('textarea').html('I live in NY and it\'s a great place to live');
$(window).click(function(){
var selection = selectedText();
console.log(selection);
});
function selectedText() {
var ret = '';
if (window.getSelection){
ret = window.getSelection();
} else if (document.getSelection) {
ret = document.getSelection();
} else if (document.selection) {
ret = document.selection.createRange().text;
}
return ret;
}
I don't know where to check to see if it's from a textarea or from somewhere else, and I don't know how to change a specific part of a textarea's text
There are a lot of cross browser nuances when it comes to text selection. There are several jQuery plugins trying to deal with this. I'd recommend using a-tools. I've used it in the past, and it works as advertised.
This might help you :
Finding selection start and end position in a textarea
Also i just tested this and it works (it returns the selected text , so you can modify it and assign the value back to the textarea
Ref : http://www.codingforums.com/showpost.php?p=235174&postcount=5
<script type="text/javascript">
<!--//
function selectedText(input){
if(document.selection && document.selection.createRange().text != ''){ // IS IE
alert(document.selection.createRange().text);
}
else{ // Not IE.. assume Mozilla?
var startPos = input.selectionStart;
var endPos = input.selectionEnd;
alert(input.value.substring(startPos, endPos))
}
}
//-->
</script>
</head>
<body>
<form name="reportForm">
<textarea name="report">this is a test</textarea>
<button onclick="selectedText(this.form.report)">Alert Selection</button>
</form>

Categories

Resources