Hidden text that can be dragged from the browser? - javascript

How can you create an html element that when dragged from the browser into a text editor, hidden text on or in the dragged element will be pasted into the editor?
My first thought was to use the href attribute on the anchor tag:
Drag me into a text editor!
This works great in chrome, but firefox and safari remove spaces from the href value which renders the copied message unusable.
Any ideas?

Instead of manipulating the browser's default behavior for dragging text/links/images, you want to set the data to something arbitrary in the dragstart event.
For example, use the text from a hidden #content:
$('[draggable]').on('dragstart', function(e) {
var content = $(this).find('#content').text(); // Can be anything you want!
e.originalEvent.dataTransfer.setData('text/plain', content);
$(this).addClass('dragging');
});
Here is a working JSFiddle

For versions of IE below 10 which don't support the dataTransfer method, I've discovered another somewhat hacky way to make this work.
Basically you make text invisible with css then use js to select it in the background on hover.
HTML
<div id="drag_area" draggable="true">
<div id="text">
hidden text
</div>
</div>​
CSS
#text { filter:alpha(opacity=0); opacity:0;
overflow:hidden; z-index:100000; width:180px; height:50px }
​
JS
function selectText(elementID) {
var text = document.getElementById(elementID);
if ($.browser.msie) {
var range = document.body.createTextRange();
range.moveToElementText(text);
range.select();
} else if ($.browser.mozilla || $.browser.opera) {
var selection = window.getSelection();
var range = document.createRange();
range.selectNodeContents(text);
selection.removeAllRanges();
selection.addRange(range);
} else {
var selection = window.getSelection();
selection.setBaseAndExtent(text, 0, text, 1);
}
}
$('#drag_area').hover(function(){
selectText('text');
});
Here it is combined with Anson's solution and a little feature detection:
http://jsfiddle.net/zaqx/PB6XL/
(works in IE8, IE9 and all modern browsers)
EDIT: Updated Fiddle in the comments below.

Related

JavaScript - Select span text on mouse hover

I have this HTML code.
<div class="dontsplit" onmouseover="selCode('c111');">
Face savoring delicious food <span class="notranslate" id="c111">😊</span>
</div>
I want to select the value between span tags when mouse hovers the div. The code I am using is this.
function selCode(objId) {
if(document.selection) {
var range = document.body.createTextRange();
range.moveToElementText(document.getElementById(objId));
range.select();
} else if(window.getSelection) {
var range = document.createRange();
range.selectNode(document.getElementById(objId));
window.getSelection().addRange(range);
}
}
But it doesn't seem to work. How do I get this work?
I repeat. I need to automatically select the text between span when mouse hovers over the div. So it can be copied easily. Thanks in advance!
Your script is working for the first mouseover but the second one inwards is giving the error Discontiguous selection is not supported. so clear the existing selection before doing a new selection.
function selCode(objId) {
if (document.selection) {
var range = document.body.createTextRange();
range.moveToElementText(document.getElementById(objId));
range.select();
} else if (window.getSelection) {
var range = document.createRange();
range.selectNode(document.getElementById(objId));
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
}
Demo: Fiddle
I think this should help.
You can use jQuery .text() method.
You have a span with notranslate class.
So you can do somthing like this to get the text:
$(".notranslate").text();
http://jsfiddle.net/L8r6ns88/
Try this one. I'm using jquery to make this task done.
HTML
<div class="dontsplit">
Face savoring delicious food <span class="notranslate" id="c111">😊</span>
</div>
JS
$(function(){
$('.dontsplit').on('mouseover','.notranslate', function(){
console.log($(this).text()); //see result
})
})

Content-editable <span> tag unselects when the mouse button is released

I'm trying to use a content-editable span tag as a variable-width inline text input box. Everything is working fine, except I can't get it to select the whole text when I focus on the box. Tabbing to the editable span works fine, but when I click it, the mouse-up event seems to unselect the selection I just made. I'm using google chrome latest on Ubuntu.
http://jsfiddle.net/6b3tP/
Here's the HTML:
<div>
Inline editable <span contenteditable="true">spans</span> are hard to select.
</div>
And here's the JS:
$('span').focus(function() {
var text_node = this.firstChild;
var text = $(this).text();
var range = document.createRange();
range.setStart(text_node, 0);
range.setEnd(text_node, text.length);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
});
I'd suggest delaying doing the selecting using window.setTimeout() to allow the dust to settle before doing anything. You can also simplify the code a little.
Demo: http://jsfiddle.net/6b3tP/1/
Code:
$('span').focus(function() {
var span = this;
window.setTimeout(function() {
var range = document.createRange();
range.selectNodeContents(span);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}, 1);
});

Dragging a div select whole text

imagine i have a div
<div id="blah">
spotify:track:something
spotify:track:something
spotify:track:something
spotify:track:something
</div>
With close to 100+ of spotify:track stuff and I want to drag whole list to Spotify program to create a new playlist, but first I would have to select all the text.
Is it possible to make that starting to drag div automatically would select whole text.
For example: http://codepen.io/anon/pen/Hwbdy
It actually doesn't if it's a div or text area as long as a user can simple click and drag without selecting the text, thanks
if you want to select texts by javascript try this:
function select(){
var div = document.getElementById('blah'),
sel, range;
if(window.getSelection){
range = document.createRange();
range.selectNode(div)
sel = window.getSelection();
sel.addRange(range);
}else{
range = document.body.createTextRange();
range.moveToElementText(div);
range.select();
}
}
demo / jsfiddle
Maybe use jQuery? :
$("#yourID").focus(function() {
var $this = $(this);
$this.select();
// Work around Chrome's little problem
$this.mouseup(function() {
// Prevent further mouseup intervention
$this.unbind("mouseup");
return false;
});
});

updating the range in html [duplicate]

I'm trying to make a JavaScript bookmarklet that will act as a highlighter, changing the background of selected text on a webpage to yellow when the bookmarklet is pressed.
I'm using the following code to get the selected text, and it works fine, returning the correct string
function getSelText() {
var SelText = '';
if (window.getSelection) {
SelText = window.getSelection();
} else if (document.getSelection) {
SelText = document.getSelection();
} else if (document.selection) {
SelText = document.selection.createRange().text;
}
return SelText;
}
However, when I created a similar function to change the CSS of the selected text using jQuery, it isn't working:
function highlightSelText() {
var SelText;
if (window.getSelection) {
SelText = window.getSelection();
} else if (document.getSelection) {
SelText = document.getSelection();
} else if (document.selection) {
SelText = document.selection.createRange().text;
}
$(SelText).css({'background-color' : 'yellow', 'font-weight' : 'bolder'});
}
Any ideas?
The easiest way to do this is to use execCommand(), which has a command to change the background colour in all modern browsers.
The following should do what you want on any selection, including ones spanning multiple elements. In non-IE browsers it turns on designMode, applies a background colour and then switches designMode off again.
UPDATE
Fixed in IE 9.
function makeEditableAndHighlight(colour) {
var range, 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);
}
}
Here is a crude example of how it could work. As Zack points out you'll need to be aware of cases where the selection spans multiple elements. This isn't intended to be used as-is, just something to help get ideas flowing. Tested in Chrome.
var selection = window.getSelection();
var text = selection.toString();
var parent = $(selection.focusNode.parentElement);
var oldHtml = parent.html();
var newHtml = oldHtml.replace(text, "<span class='highlight'>"+text+"</span>");
parent.html( newHtml );
To make the highlight stick permanently, I believe you are going to have to wrap the selection in a new DOM element (span should do), to which you can then attach style properties. I don't know if jQuery can do that for you. Keep in mind that selections can span element boundaries, so in the general case you're going to have to inject a whole bunch of new elements
Have a look at a little example i made at http://www.jsfiddle.net/hbwEE/3/
It does not take into account selections that span multiple elements..
(IE will do but will mess the html a bit ..)
In Firefox, you can use the ::-moz-selection psuedo-class.
In Webkit, you can use the ::selection pseudo-class.
I like Tim's answer, it's clean and fast. But it also shuts down the doors to doing any interactions with the highlights.
Inserting inline elements directly around the texts is a bad choice, as they broke the text flow and mess things up in complex situations,
So I suggest a dirty hack that
calculates the absolute layout of each line of selected text (no matter where they are),
then insert colored, semi-transparent inline-block elements in the end of the document body.
This chrome extension is an example of how this can be done.
It uses API from this library to get the absolute layout of each selected line.

How can I highlight the text of the DOM Range object?

I select some text on the html page(opened in firefox) using mouse,and using javascript functions, i create/get the rangeobject corresponding to the selected text.
userSelection =window.getSelection();
var rangeObject = getRangeObject(userSelection);
Now i want to highlight all the text which comes under the rangeobject.I am doing it like this,
var span = document.createElement("span");
rangeObject.surroundContents(span);
span.style.backgroundColor = "yellow";
Well,this works fine, only when the rangeobject(startpoint and endpoint) lies in the same textnode,then it highlights the corresponding text.Ex
<p>In this case,the text selected will be highlighted properly,
because the selected text lies under a single textnode</p>
But if the rangeobject covers more than one textnode, then it is not working properlay, It highlights only the texts which lie in the first textnode,Ex
<p><h3>In this case</h3>, only the text inside the header(h3)
will be highlighted, not any text outside the header</p>
Any idea how can i make, all the texts which comes under rangeobject,highlighted,independent of whether range lies in a single node or multiple node?
Thanks....
I would suggest using document's or the TextRange's execCommand method, which is built for just such a purpose, but is usually used in editable documents. Here's the answer I gave to a similar question:
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.
UPDATE 12 September 2013
Here's a link detailing a method for removing highlights created by this method:
https://stackoverflow.com/a/8106283/96100
function makeEditableAndHighlight(colour) {
var range, 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;
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);
}
}
Rangy is a cross-browser range and selection library that solves this problem perfectly with its CSS Class Applier module. I'm using it to implement highlighting across a range of desktop browsers and on iPad and it works perfectly.
Tim Down's answer is great but Rangy spares you from having to write and maintain all that feature detection code yourself.
var userSelection = document.getSelection();
var range = userSelection.getRangeAt(0);
Instead of surroundContent method you can use the appendChild and extractContents methods this way:
let newNode = document.createElement('mark');
newNode.appendChild(range.extractContents());
range.insertNode(newNode);
function markNode() {
if(document.getSelection() && document.getSelection().toString().length){
let range = document.getSelection().getRangeAt(0);
let newNode = document.createElement('mark');
newNode.appendChild(range.extractContents());
range.insertNode(newNode);
}
else{
alert('please make selection of text to mark');
}
}
function resetContent() {
testMe.innerHTML = `Remember: Read and <strong>stay strong</strong>`;
}
<p id="testMe">Remember: Read and <strong>stay strong</strong></p>
<div><button onclick="markNode()">markNode</button></div>
<div><button onclick="resetContent()">resetContent</button></div>
Could you please elaborate the need of this functionality. If you only want to change the highlight style of the selected text you can use CSS: '::selection'
More Info:
http://www.quirksmode.org/css/selection.html
https://developer.mozilla.org/en/CSS/::selection
Can you try adding a class for the surrounding span and apply hierarchical CSS?
var span = document.createElement("span");
span.className="selection";
rangeObject.surroundContents(span);
In CSS definition,
span.selection, span.selection * {
background-color : yellow;
}
I did not try it. But just guessing that it would work.

Categories

Resources