Use jQuery select() to select contents of a div - javascript

Is it possible to use or adapt jQuery's .select() to set a selection range on the entire contents of a div?
I have a div which has a series of labels, inputs, select objects and a couple of other UI elements. I have found code on a separate StackOverflow post with some code hosted on jsFiddle: http://jsfiddle.net/KcX6A/570/
Can this be adapted to select the value of inputs also? Or how would you suggest I go about this?
Thanks,
Conor
Edit: More info
I know how to get the value of inputs using jQuery, that is easy, I also know how to select he values of independent elements using .select().
In my div I have a series of different element types including inputs, labels, selects, etc. I need an overall selection of all elements. The jsFiddle link I added earlier shows how to set the range of a div and select the text of elements like p tags etc. What I need is to set the range of the div's contents and when I hit ctrl+c or cmd+c it copies the values of the inputs as well as the labels.
So to summarise, using .val and .select won't work for this I don't think. I need to combine the above in some way but not sure exactly how this will be accomplished. Any ideas?

Check this fiddle: http://jsfiddle.net/JAq2e/
Basically the trick is to introduce a hidden text node whose content will be included in the selection when copied.
jQuery.fn.selectText = function(){
this.find('input').each(function() {
if($(this).prev().length == 0 || !$(this).prev().hasClass('p_copy')) {
$('<p class="p_copy" style="position: absolute; z-index: -1;"></p>').insertBefore($(this));
}
$(this).prev().html($(this).val());
});
var doc = document;
var element = this[0];
console.log(this, element);
if (doc.body.createTextRange) {
var range = document.body.createTextRange();
range.moveToElementText(element);
range.select();
} else if (window.getSelection) {
var selection = window.getSelection();
var range = document.createRange();
range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);
}
};
And use it like:
$('#selectme').selectText();
You can couple the above plugin with an event handler if you want to create selection links :
Code :
$('.select-text').on('click', function(e) {
var selector = $(this).data('selector');
$(selector).selectText();
e.preventDefault();
});
Usage :
Select all
<div id="some-container">some text</div>
Demo : see js fiddle

If you want to select the input elements together with every thing.
Here is a jQuery mixed, JS solution
function selectElement(element) {
if (window.getSelection) {
var sel = window.getSelection();
sel.removeAllRanges();
var range = document.createRange();
range.selectNodeContents(element);
sel.addRange(range);
} else if (document.selection) {
var textRange = document.body.createTextRange();
textRange.moveToElementText(element);
textRange.select();
}
}
selectElement($("div")[0]); //Select the div
$("input").trigger("select"); //select the inputs
Demo

If you want to select inside form elements. Use .focus() /.blur() and .val() functions.
$('input').focus(); //focus on input element
$('input').val(); //return the value of input

Not really. In most browsers it's not possible for the contents of more than one input to be selected at once. See http://jsfiddle.net/timdown/D5sRE/1/

Related

setting caret (cursor) inside bold element present inside contenteditable paragraph

I have been trying to build a web based text editor. And as part of the process, I am trying to dynamically create and modify elements based and keystroke events for font editing. In this particular jsfiddle example I'm trying to create a strong element upon hitting CTRL+b and setting the focus/caret inside the strong element so that subsequent text entered will be part of the bold element and hence will have bold text. But my code is just creating a strong element but not transferring the focus hence no text is getting bolder.
In the below code I'm creating event listener to capture keystroke events
p=document.getElementsByTagName("p")[0];
//console.log(p)
// adding eventlistener for keydown
p.addEventListener("keydown",listener);
// eventlistenerr callback function
function listener(){
e=window.event;
if(e.ctrlKey && e.keyCode==66)
{
console.log("CTRL+B");
// creating bold element
belm=document.createElement("strong");
belm.setAttribute("contenteditable","true")
p.appendChild(belm);
//bug below
// setting focus inside bold element
setfocus(belm,0);
e.preventDefault();
}
}
Here is the function for setting the focus.
function setfocus(context, position){
var range = document.createRange();
position =position || 0;
var sel = window.getSelection();
range.setStart(context, position);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
context.focus();
}
However, I have not doubt that the function which sets focus is faulty, because in the fiddle if you observe, I have created a separate setup just to test this
out. Click on the button "Click Here" and the focus dynamically shifts to paragraph element without any hassle. I am unable to figure out what is going wrong.
It's pretty much impossible to move the cursor into an empty element in a contenteditable div. However, as shay levi suggested in another post, you can insert the zero-width character &#200B into your empty element to give it an index value.
Here's an example*:
function insertNode(nodeName) {
var sel = window.getSelection(),
range;
range = sel.getRangeAt(0);
range.deleteContents();
var child = document.createElement(nodeName);
child.innerHTML = '​';
range.insertNode(child);
}
var div = document.querySelector('div'),
btn = document.querySelector('button');
btn.addEventListener('click', function() {
insertNode('strong');
div.focus();
});
div.focus();
<div contenteditable></div><button><strong>B</strong></button>
*For the sake of simplicity, this script doesn't toggle bold text, it only sets it.

How to replace selected text on page with another text?

I'm trying to replace selected text with another text with a function switchText called from the context menu.
function switchText(info) {
var text = info.selectionText; // selected text
// then I do some manipulations with 'text' and get 'text_to_replace'
var text_to_replace = "some text"; // text to replace
}
alert(text) and alert(text_to_replace) works fine, but I'm trying to replace selected text right on the page but I can't figure out how to do it. I tried different methods but they hadn't worked. Any special permissions needed? I'm sorry if it's stupid question, I'm beginner in JS.
If you want to be able to do this anywhere on a page, you need to be able to set some kind of identifying ID to your selection. You have to do this through a content script of some kind. You can read more about it in the Chrome Developer documentation.
This code will allow you to change the text of a single selection
(tested in Chrome only)
function switchText(id) {
// Gets the selection range
// This is from Tim Down, linked below
var range, sel = window.getSelection();
if (sel.rangeCount && sel.getRangeAt) {
range = sel.getRangeAt(0);
}
// Creates a new node range
document.designMode = "on";
if (range) {
sel.removeAllRanges();
sel.addRange(range);
}
// This is from user YeppThatsMe, also linked below
document.execCommand("insertHTML", false, "<span id='own-id'>"+ document.getSelection()+"</span>");
document.designMode = "off";
// You can use either a variable or a string
var someNewText = "-- You can make this whatever you want --";
// Finds the new span and replaces the selection with your new text
document.getElementById("own-id").innerHTML=someNewText;
};
Sourced scripts
Tim's script
HTML5 inserCommand
Last Note
I didn't spend too long testing, and the script as-is will only change one selection per page. You'll need to tweak the way the function gets the tag and attribute info (change it to getElementsByClassName?) to run it more than once, but this should work.
to update a html element targeted by Id
document.getElementById("idtotarget").innerHTML = switchText(document.getElementById("idtotarget").innerHTML)

Inserting caret after an inserted node

So I have a method that takes a tag and wraps the selected text in that tag.
function wrap(tag)
{
var sel, range;
if (window.getSelection)
{
sel = window.getSelection();
if (sel.rangeCount)
{
range = sel.getRangeAt(0);
var selectedText = range.toString();
range.deleteContents();
range.insertNode(document.createTextNode('['+tag+']'+selectedText+'[/'+tag+']'));
}
}
}
This issue with this however, is after it's done wrapping the text and inserting the node the caret (where they are typing) is placed BEFORE the inserted text.
Is there such way to insert the text and have the caret remain at the end of it?
Please note i'd prefer if this could be done without the use of jQuery or any other library. I only need it to work in webkit (Safari).
You can use the range.setStartAfter and range.setEndAfter methods to set the start and end points to the point directly after your new node. I setup a jsfiddle example here: http://jsfiddle.net/phil_mcc/tM3mA/
//move the caret
range.setStartAfter(newNode);
range.setEndAfter(newNode);
sel.removeAllRanges();
sel.addRange(range);
do this after inserting the node to the range
range.collapse(false);
this will change position of selection range to the end of the range, so my guess is it should set the cursor at end position

selection position of selected text of div using javascript

I need to get the position of the selected text within a content non-editable div (not a textarea, not a rtf editor, just a simple div)
I want to do this in order to enable users to select pieces of an article and "highlight it", by wrapping it in a span with a different background and, of course, an article is build with divs and/or p-s etc, not textareas or rtfs
Any ideas?
P.s. You can also use jQuery :D
P.s.s. I need the position of the selection, not the selection itself. Aka: it start from index I to index J. I need this because the normal method of finding the text in the parent does not always return a unique result, which would suck :)
If you just want to change the background of the selected text, the easiest way to do this is by using document.execCommand(). See my answer here: Change CSS of selected text using Javascript
//Wrap selected text in span tags with the class 'hl'
//Take some action after (in this case, a simple alert)
$("p").live("mouseup",
function() {
selection = getSelectedText();
if(selection.length >= 3) {
$(this).html($(this).html().replace(selection, $('<\/span>').attr({'class':'hl'}).html(selection).parent().html()) );
alert(selection);
}
}
);
//Grab selected text
function getSelectedText(){
if(window.getSelection){
return window.getSelection().toString();
}
else if(document.getSelection){
return document.getSelection();
}
else if(document.selection){
return document.selection.createRange().text;
}
}
Code comes from here: http://esbueno.noahstokes.com/post/92274686/highlight-selected-text-with-jquery
You can check if text is selected by running :
window.getSelection and document.getSelection() and document.selection
(because browsers can check this i different ways)
and then search for div containing this text .
 
For getting the position of the selection, try these links:
http://bytes.com/topic/javascript/answers/153164-return-selectionstart-div
Set cursor position on contentEditable <div>
Well, even though you found a solution to the problem stated in your 2nd paragraph, i don't think the answer to your main question has been given. :)
The object Selection has a property named anchorOffset, giving exactly what you asked for (the position of the selected text within an element). The above link will tell you about which browsers support it, i'm afraid IE <9 might not.
function show_selected()
{
var sel = selection();
console.log(sel.anchorOffset + ':' + sel);
}
Now if you bind show_selected to, say, mouseup, you will see the offset and the selected text printed on the js console.
The fonction selection may be the following, supposed to be cross-browser:
function selection()
{
var sel;
if(window.getSelection){
sel = window.getSelection()
}
else if(document.getSelection){
sel = document.getSelection()
}
else if(document.selection){
sel = document.selection.createRange()
}
return sel
}

Javascript Highlight Selected Range Button

I'm attempting to create a study tool for a page that allows a user to select any text on the page and click a button. This click then formats the selected text with a yellow background. I can make this work inside of a single tag, but if the range of selection is across multiple tags (for instance, the first LI in an unordered list along with half of the second), I have difficulty applying the style. I can't just wrap the selection with a span here unfortunately.
Basically, I want the effects associated with contentEditable and execCommand without actually making anything editable on the page except to apply a background color to the selected text with the click of a button.
I'm open to jQuery solutions, and found this plug-in that seems to simplify the ability to create ranges across browsers, but I was unable to use it to apply any formatting to the selected range. I can see from the console that it's picking up on the selection, but using something like:
var selected = $().selectedText();
$(selected).css("background-color","yellow");
has no effect.
Any help pointing me in the right direction would be greatly appreciated.
The following should do what you want. In non-IE browsers it turns on designMode, applies a background colour and then switches designMode off again.
UPDATE
Fixed to work in IE 9.
function makeEditableAndHighlight(colour) {
sel = window.getSelection();
if (sel.rangeCount && sel.getRangeAt) {
range = sel.getRangeAt(0);
}
document.designMode = "on";
if (range) {
sel.removeAllRanges();
sel.addRange(range);
}
// Use HiliteColor since some browsers apply BackColor to the whole block
if (!document.execCommand("HiliteColor", false, colour)) {
document.execCommand("BackColor", false, colour);
}
document.designMode = "off";
}
function highlight(colour) {
var range, sel;
if (window.getSelection) {
// IE9 and non-IE
try {
if (!document.execCommand("BackColor", false, colour)) {
makeEditableAndHighlight(colour);
}
} catch (ex) {
makeEditableAndHighlight(colour)
}
} else if (document.selection && document.selection.createRange) {
// IE <= 8 case
range = document.selection.createRange();
range.execCommand("BackColor", false, colour);
}
}
As far as I know, you won't be able to apply styling to regular text. You some sort of html element to operate on. You could try wrapping the selected text with a span and then style the span.
$().selectedText().wrap("<span></span>").parent().addClass("wrapped").css({backgroundColor: "Yellow"});
I added a class of "wrapped" as well, so that on subsequent attempts to highlight text, you can remove previous highlights.
$(".wrapped").each(function(){ ($(this).replaceWith( $(this).text() });
Code is untested.

Categories

Resources