Transforming highlighted text inside an element using javascript - javascript

My goal is to be able to get the highlighted text within a document, but only if that text is within a given section, and then apply a certain style to that selected text after clicking a div tag. I'll explain what I mean:
So, having looked at window.getSelection() and document.selection.createRange().text, I attempted to use elmnt.getSelection() or elmnt.selection.createRange().text for some HTML element, elmnt. However, it doesn't seem to work, so that idea seems pretty null. This means I can't use this idea to determine the text that is highlighted within a given location. In case this doesn't make sense, essentially, I want html code that looks like this:
<body>
<div id="content">Stuff here will not be effected</div>
<div id="highlightable">Stuff here can be effected when highlighted</div>
<div id="morecontent">Stuff here will also not be effected</div>
</body>
So that whenever I've highlighted text, clicking on a specified div will apply the proper CSS.
Now, on to the div tags. Basically, here's what I've got on that:
$('.colorpicker').click( function(e)
{
console.log(getSelectedText());
}
Eventually, all I want this to highlight the selected text and have the div tag change the color of the selected text to that of the respective div tag that I've selected. Neither of these seems to be working right now, and my only guess for the reason of the div tag is that it unhighlights whatever I've got selected whenever I click on the div tag.
Fallbacks:
If there is more than one time that 'abc' is found on the page and I highlight to color 'abc', I would like that only that copy of 'abc' be highlighted.
I know this is a lot in one question, but even if I could get a little head start on this idea, my next personal project would be going a lot more smoothly. Thanks. :)

The key in the solution to this will be working with the objects that represent text ranges in browsers, not the selected text itself. Look into methods available to you in both the FireFox Range and IE TextRange objects. Both of these contain means of replacing the selected text with your own markup (e.g. a span wrapping your selected text.)
For FF look into Range.getRangeAt(0).surroundContents(element)
For IE look into TextRange.pasteHTML()
I must warn you though... You'll probably end up down a scary path of browser quirks if you go through with this. Already from the get-go you're supporting two different objects for two of the major browsers.

Related

Is there a way to apply css to part of the element?

I am looking for a way to apply new CSS to only part of the element.
For example. The original HTML looks like
<p>123456</p>
I want to make only 456 into bold.
Of course, I can do it by adding another tag into 456 like
<p>123<b>456</b></p>
But in my application, I do want not to change the original DOM structure. By adding a new tag, I changed the DOM structure.
To do that, I am thinking of adding new custom attribute to the existing tag like
<p data-wms="e-3">123456</p>
Here data-wms means that there are special part and e-3 means that from index 3 character (it is 4 here) to the end will have a special attribute (like bold in this example)
Now I have all the information about where to change inside the element.
But still, how can I do that with javascript without adding a tag, without changing dom.
Thanks
You can use the span element to do so, it's made specifically to handle inline styling while mantaining the overall structure.
An example would be:
<p>123<span class="bold-highlight">456</span></p>
Thanks to everyone's advice, I researched more, especially about nth-letter.
Though nth-letter is exactly what I want, I found that it is still just proposal, not implemented in any browser.
Thus, there is no way to applying different css letter by letter in one text element without embracing each letter with span tag at this moment (2021-March). I hope that there will be nth-letter in the near future.
I think that I have to re-design my project...
if it's a static page and you want to change a style for specific text in a specific tag like the following case
<p>11111</p>
<p>22222</p>
<p>33333</p>
<p>44444</p>
let's say you want just style the third element, you can change it by the following code using jQuery for sure you can use JavaScript but jQuery will help you to make your code shorter
$( "p:nth-child(3)" ).css("color","#f00");

Find the Element in which a Range Starts or Ends

I am trying to find the element in which a Selected Range Starts.
For example:
<p>Hello, <span class="editet">Genei180</span> is My Name</p>
The user now Selects:
"ei180 is My Name"
Therefore i want something like startElementofRange() which Returns "object HTMLSpanElement"
I than want that on keypress only the Part which sits in Span Edíted gets Deleted.
I know about the Node.startOffset and Node.startContainer.
But Node.startContainer would return in this case the whole p-Element as Text Element. But Node.startOffset is in this Case Relative to the Span Element so it would be 2. Also there can be occasions where more than one Span Edited Element can be selected. Current Approach is to loop true them all:
Sitenote:
This is for a Website which allows editing true the Javascript tag Contenteditable='true' and Displays Everything that changed in Green.
I also want to read in only the Changed Parts from the Spans if Submited.
So it can be Disscussed by the Users and Voteaccepted into an Articel.
Is this in general a Secure and sense Making approach?
I searched for weeks...
range.startContainer returns the Notetype but not as i thought of the p Element
instead it returns the type of the Span Element.
So you just need to use range.startContainer.parentNode to get The Element from it.
I feel stupid now.
I leaf this up in case some one has the Same Problem

Rangy SurroundContents Replacement

I'm looking at implementing a simple 2 button toggle on a webpage to switch some selected text between having a H1 heading and H2. The surroundContents method works great, however I'm encountering a problem when trying to replace an existing parent tag element node. I've played around with all sorts of ways trying to do this but not had much success.
The basic functions are below. Using the same selected text and running both of these functions one after the other will result on some output such as the following:
After selecting text of "test text" and then selecting the H1 option:
<h1>test text</h1>
If the same text is selected again and this time the H2 option pressed: <h1><h2>test text</h2></h1>
function surroundSelectedWithH1() {
var element = document.createElement("h1");
// removed code to setup range to save space
if (range) {
range.surroundContents(element);
}
}
function surroundSelectedWithH2() {
var element = document.createElement("h2");
// removed code to setup range to save space
if (range) {
range.surroundContents(element);
}
}
This is fine, and what would be expected, but I'm really looking for a way to remove the original parent heading element so that the heading elements do not become nested (for example - the text is surrounded by either h1 or h2, not both). I did experiment accessing the parentNode etc but did not manage to get this approach functional. I've tried looking at the following parentElement suggestion Getting the parent node for selected text with rangy library however I wasn't able to have rangy write the changed parent element back to the DOM or have a satisfactory way of determining where in the DOM the object was in order to replace it. It quickly became an unwieldy approach and there must be a better option.
I do know that the rangy CssApplier module can handle this situation but I need to work with actual elements and not css.
I also noticed that on the raptor editor which uses rangy for a text editor implementation suffers from the exact same problem when applying headings: http://www.raptor-editor.com/demo
This question was also relevant but this particular element problem can't be handled with execCommand as far as I'm aware - Javascript: how to un-surroundContents range
Any help or advice graciously received.
Try with:
highlighter.unhighlightSelection()

Manipulations with user's selected text in editMode

I have this HTML code (it is located in contenteditable="true" block):
<ol>
<li>Mozilla Firefox 1.5+</li>
<li>Internet <span>Explorer</span> 6+</li>
<li>Opera 9.6+</li>
<li>Google Chrome 2+</li>
<li>Apple Safari 3+</li>
</ol>
User has selected some text in this list:
exactly the word «Chrome»,
or exactly the word «Explorer» (it is wrapped with span tag).
The main difference between words «Chrome» and «Explorer» is that word «Explorer» is wrapped with span tag, but «Chrome» is not.
So, how do I know if selected text wrapped with some HTML tags or not?
With some regexp? — I don't know how to get selected text with HTML tags (I know only how to get plain text from selection).
With detecting range's commonAncestorContainer.parentNode? — If I have selected word «Chrome», my parentNode will be li tag (but li tag doesn't wrap my selected word directly, I don't want set styles for li tag). So, I cannot use commonAncestorContainer.parentNode 'cos it is useless for me.
Actually, I just want to set some CSS styles for the selected text:
if user's selected text has already directly wrapped with some HTML tag, I want to add CSS rules for this tag (eq. if user has selected word «Explorer» I want to add style="font-weight:bold;" for the span tag; if user has selected Apple Safari 3+ I want to add CSS rules for li tag)
if user's selected text is just plain text (not directly wrapped with some tags, like word «Chrome»), I want to wrap this text with some tags and add some CSS rules. (With this item I have no problems, I know how to do this.)
UPD:
Look, when I select some text and then run document.execCommand('Bold', false, null), browser wraps my selection with b tags. When I select exactly the same text again and run the same document.execCommand('Bold', false, null) command, boldness disappear. So, browser somehow knows that my selection is wrapped with b tags and remove them (unwrap). So, how does browser know, is selection wrapped with tags or not? If browser knows, why it is so hard to make it with JS?
This is a slightly complex area:
IE < 9 has a completely different API for selections and ranges from other browsers
Getting hold of and then styling the selected content requires some careful DOM manipulation
Here are two suggestions:
If you just want to toggle boldness on the selection, you can use document.execCommand("bold", false, null)
If using CSS classes rather than element style properties/attributes, you could use the CSS class applier module of my Rangy library.

set cursor on a div element?

How do I set the cursor on a div-element in javascript?
I have a form(div-element not input) with a textstring attached on it. I want the textstring removed and the cursor set at the beginning of the element onclick.
I have removed the content in the div-element with onclick event with: divElement.innerHTML = '';
Now I want the cursor to be set?
If you mean the mouse pointer, use the CSS cursor style like this:
#mydiv {
cursor: help;
}
There are a whole load of standard options you can use. You can also define a graphic to use as the pointer (though this has cross-browser compatibility issues).
See this page on Quirksmode for more info.
Similarly, if you want to do it dynamically in Javascript, then just set the object's style:
document.getElementById('mydiv').style.cursor = 'help';
If by 'cursor', you mean the text cursor (aka the caret), I presume what you're really asking is how to make a div into an editable content box.
What you need is to set the contentEditable attribute on your div.
If you want it editable from the start, just include it in your HTML code:
<div contentEditable="true">....</div>
If you want to switch it on/off, you can set it in javascript:
mydiv.contentEditable="true"
However, the only time I can think of when it's better to use contentEditable rather than a textarea is if you're writing a WYSIWYG HTML editor.
Most of the rest of the time I would say it's probably preferable to use a <textarea>. You can style it to look like the rest of your page, and you can make it readonly or disabled when you don't want it changed. But it is much easier to work with in a form and in Javascript. The problem with using a div is that it can contain other html tags, which may affect how it works, and will likely open you up to security problems if you make it directly editable.
divElement.style.cursor = 'whatever';
If you want to move the cursor to be over the divElement, then you can't.

Categories

Resources