it has any way for bind execcommand with a div element not for whole document , i try this :
document.getElementById('div').execcommand(...)
but it has an error :
execcommand is not a function
it has any way for bind the execcommand with just div element not whole document !!
i don't like use iframe method .
This is easier to do in IE than other browsers because IE's TextRange objects have an execCommand() method, meaning that a command can be executed on a section of the document without needing to change the selection and temporarily enable designMode (which is what you have to do in other browsers). Here's a function to do what you want cleanly:
function execCommandOnElement(el, commandName, value) {
if (typeof value == "undefined") {
value = null;
}
if (typeof window.getSelection != "undefined") {
// Non-IE case
var sel = window.getSelection();
// Save the current selection
var savedRanges = [];
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
savedRanges[i] = sel.getRangeAt(i).cloneRange();
}
// Temporarily enable designMode so that
// document.execCommand() will work
document.designMode = "on";
// Select the element's content
sel = window.getSelection();
var range = document.createRange();
range.selectNodeContents(el);
sel.removeAllRanges();
sel.addRange(range);
// Execute the command
document.execCommand(commandName, false, value);
// Disable designMode
document.designMode = "off";
// Restore the previous selection
sel = window.getSelection();
sel.removeAllRanges();
for (var i = 0, len = savedRanges.length; i < len; ++i) {
sel.addRange(savedRanges[i]);
}
} else if (typeof document.body.createTextRange != "undefined") {
// IE case
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.execCommand(commandName, false, value);
}
}
Examples:
var testDiv = document.getElementById("test");
execCommandOnElement(testDiv, "Bold");
execCommandOnElement(testDiv, "ForeColor", "red");
Perhaps this helps you out:
Example code 1 on this page has the execcommand on a div by using a function. Not sure if that's what you're after? Good luck!
Edit: I figured out how to put the code here :o
<head>
<script type="text/javascript">
function SetToBold () {
document.execCommand ('bold', false, null);
}
</script>
</head>
<body>
<div contenteditable="true" onmouseup="SetToBold ();">
Select a part of this text!
</div>
</body>
Javascript:
var editableFocus = null;
window.onload = function() {
var editableElements = document.querySelectorAll("[contenteditable=true]");
for (var i = 0; i<editableElements.length; i++) {
editableElements[i].onfocus = function() {
editableFocus = this.id;
}
};
}
function setPreviewFocus(obj){
editableFocus = obj.id
}
function formatDoc(sCmd, sValue) {
if(editableFocus == "textBox"){
document.execCommand(sCmd, false, sValue);
}
}
HTML:
<div id="textBox" contenteditable="true">
Texto fora do box
</div>
<div contenteditable="true">
Texto fora do box
</div>
<button title="Bold" onclick="formatDoc('bold');">Bold</button>
You can keep it Simple, and add this to your div.
<div contenteditable="true" onmouseup="document.execCommand('bold',false,null);">
Related
I want to select the HTML of whatever the user selects in a contenteditable div. I found some code to retrieve the HTML of the selection, but it's not limited to just the div.
What I want to do is copy the selected HTML, wrap tags around it, and then replace the selection with it. So, 'test' would become 'test' for instance.
<div contenteditable="true" class="body" id="bodydiv"></div>
function getSelectionHtml() {
var html = "";
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
}
HI for getting content(text) inside a selected div I have create a little code you can check it out if it works for you :
$(document).ready(function(){
$(document).bind('mouseup', function(){
var content = getSelected();
content = "<b>"+content+"</b>";
$('#selected').html(content);
});
});
function getSelected(){
var t;
if(window.getSelection){
t = window.getSelection();
var start = t.focusOffset;
var end = t.baseOffset;
t = t.anchorNode.data;
t = t.slice(start, end);
} else if (document.selection) {
t = document.selection.createRange().text;
}
return t;
}
And
<div id="selected"></div>
Hope this helps.
I have added a button to insert some text from a textarea to an editable DIV using this function found on stakoverflow.
function insertAtCursor(){
document.getElementById('myInstance1').focus() ; // DIV with cursor is 'myInstance1' (Editable DIV)
var sel, range, html;
var text = document.getElementById('AreaInsert').value ; // Textarea containing the text to add to the myInstance1 DIV
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
range.insertNode( document.createTextNode(text) );
}
} else if (document.selection && document.selection.createRange) {
document.selection.createRange().text = text;
}
}
With Internet Explorer using document.selection.createRange().text it works fine for line breaks.
With Firefox and Chrome, line breaks of the textarea are not respected, all the text inserted to the editable div from the textarea is on only one line.
How to modify insertAtCursor() to make it works for line breaks with Firefox and Chrome ?
I suggest splitting the text up into separate text nodes, replacing the line breaks with <br> elements, creating a DocumentFragment containing the text and <br> nodes and calling insertNode() to insert it.
Demo: http://jsfiddle.net/timdown/zfggy/
Code:
function insertAtCursor(){
document.getElementById('myInstance1').focus() ; // DIV with cursor is 'myInstance1' (Editable DIV)
var sel, range;
var text = document.getElementById('AreaInsert').value ; // Textarea containing the text to add to the myInstance1 DIV
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
var lines = text.replace("\r\n", "\n").split("\n");
var frag = document.createDocumentFragment();
for (var i = 0, len = lines.length; i < len; ++i) {
if (i > 0) {
frag.appendChild( document.createElement("br") );
}
frag.appendChild( document.createTextNode(lines[i]) );
}
range.insertNode(frag);
}
} else if (document.selection && document.selection.createRange) {
document.selection.createRange().text = text;
}
}
I think I found a more appropriate solution for your problem. For demonstration see this Fiddle. See also the css property word-wrap.
Java Script:
var button = document.getElementById('insertText');
button.onclick = function() {
var text = document.getElementById('textarea').value;
document.getElementById('insertHere').innerText = document.getElementById('insertHere').textContent = text
};
To achieve cross browser compatibility, you could also do this:
var isIE = (window.navigator.userAgent.indexOf("MSIE") > 0);
if (! isIE) {
HTMLElement.prototype.__defineGetter__("innerText",
function () { return(this.textContent); });
HTMLElement.prototype.__defineSetter__("innerText",
function (txt) { this.textContent = txt; });
}
I'm using this code to select text from the window document. This code is working fine in all browsers: it returns the selected text, but in IE8 it does not give the selected text. Instead it gives the whole HTML of the selected line. Can anybody give me solution for this?
Example:
<B><U><SPAN style="LINE-HEIGHT: 150%; FONT-FAMILY: 'Arial',
'sans-serif'; FONT-SIZE: 12pt">Summary</SPAN></U></B>
I want only Summary so all major browser return this except IE8.
<script type="text/javascript">
function getSelectionText(id) {
var html = "";
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
document.getElementById(id).value = html;
//document.getElementById(id).value = html;
}
</script>
You should look into rangy - A cross-browser JavaScript range and selection library. In their own words:
It provides a simple standards-based API for performing common DOM Range and Selection tasks in all major browsers, abstracting away the wildly different implementations of this functionality between Internet Explorer up to and including version 8 and DOM-compliant browsers.
Change
html = container.innerHTML;
into
html = container.innerText;
The issue is with the following line in IE8
html = document.selection.createRange().htmlText;
Change it to this
html = document.selection.createRange().text;
Below is a nice simple function which seems to work well for me
function getSelectedText() {
var txt = '';
if (window.getSelection) {
txt = window.getSelection();
}
else if (document.getSelection) {
txt = document.getSelection();
}
else if (document.selection) {
txt = document.selection.createRange().text;
}
else return;
return txt;
}
Hope this helps
I have this function which removes selected (cursor) highlighted elements:
function deleteSelection() {
if (window.getSelection) {
// Mozilla
var selection = window.getSelection();
if (selection.rangeCount > 0) {
window.getSelection().deleteFromDocument();
window.getSelection().removeAllRanges();
}
} else if (document.selection) {
// Internet Explorer
var ranges = document.selection.createRangeCollection();
for (var i = 0; i < ranges.length; i++) {
ranges[i].text = "";
}
}
}
What I actually want to do is remove all the cursor- highlighted elements, except for the input#cursor element.
edit:
so lets say if I highlighted these elements with my cursor:
<span>a</span>
<span>b</span>
<input type='text' id = 'cursor' />
<span>c</span>
<span>d</span>
on a keyup, this function should not remove the <input> ...only the <span>
Phew, that was a little harder than expected!
Here's the code, I've tested it in IE8 and Chrome 16/FF5. The JSFiddle I used to test is available here. AFAIK, this is probably the best performance-wise you'll get.
The docs I used for Moz: Selection, Range, DocumentFragment. IE: TextRange
function deleteSelection() {
// get cursor element
var cursor = document.getElementById('cursor');
// mozilla
if(window.getSelection) {
var selection = window.getSelection();
var containsCursor = selection.containsNode(cursor, true);
if(containsCursor) {
var cursorFound = false;
for(var i=0; i < selection.rangeCount; i++) {
var range = selection.getRangeAt(i);
if(!cursorFound) {
// extracts tree from DOM and gives back a fragment
var contents = range.extractContents();
// check if tree fragment contains our cursor
cursorFound = containsChildById(contents, 'cursor');
if(cursorFound) range.insertNode(cursor); // put back in DOM
}
else {
// deletes everything in range
range.deleteContents();
}
}
}
else {
selection.deleteFromDocument();
}
// removes highlight
selection.removeAllRanges();
}
// ie
else if(document.selection) {
var ranges = document.selection.createRangeCollection();
var cursorFound = false;
for(var i=0; i < ranges.length; i++) {
if(!cursorFound) {
// hacky but it will work
cursorFound = (ranges[i].htmlText.indexOf('id=cursor') != -1);
if(cursorFound)
ranges[i].pasteHTML(cursor.outerHTML); // replaces html with parameter
else
ranges[i].text = '';
}
else {
ranges[i].text = '';
}
}
}
}
// simple BFS to find an id in a tree, not sure if you have a
// library function that does this or not
function containsChildById(source, id) {
q = [];
q.push(source);
while(q.length > 0) {
var current = q.shift();
if(current.id == id)
return true;
for(var i=0; i < current.childNodes.length; i++) {
q.push(current.childNodes[i]);
}
}
return false;
}
I would suggest removing the element you want keep, extracting the contents of the selection using Range's extractContents() method and then reinserting the element you want to keep using the range's insertNode() method.
For IE < 9, which doesn't support DOM Range, the code is trickier, so for simplicity you could use my Rangy library, which also adds convenience methods such as the containsNode() method of Range.
Live demo: http://jsfiddle.net/DFxH8/1/
Code:
function deleteSelectedExcept(node) {
var sel = rangy.getSelection();
if (!sel.isCollapsed) {
for (var i = 0, len = sel.rangeCount, range, nodeInRange; i < len; ++i) {
range = sel.getRangeAt(i);
nodeInRange = range.containsNode(node);
range.extractContents();
if (nodeInRange) {
range.insertNode(node);
}
}
}
}
deleteSelectedExcept(document.getElementById("cursor"));
I'm using window.getSelection () to get the selected text.
But, if i select an image too, it returns also altof an image.
EXAMPLE:
<img src="someSrc.jpg" alt="image_alt" /> My text here ...
if i select an image too, it returns
image_alt My text here ...
But i need only
My text here ...
Is there any way to get only text, without alt?
Thanks much
Try this:
window.getTextSelection = function() {
//First get HTML Fragment of selection
var html = window.getSelection().getRangeAt(0).cloneContents();
//Return only the text
return html.textContent||html.innerText;
}
In some cases you can simply disable the user selection via CSS:
May you also can achieve this by disabling user-select for images:
img {
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
The easiest way would be to use the toString() method of selection's Range(s), which is what window.getSelection().toString() is specified to do in the current version of WHATWG's new Range spec (although this is contrary to what some browsers do and may or may not change). The following will work with multiple selected ranges (which Mozilla supports) and also in IE < 9.
jsFiddle: http://jsfiddle.net/timdown/HkP2S/
Code:
function getSelectionRangeText() {
var selText = "";
if (window.getSelection) {
var sel = window.getSelection(), rangeCount = sel.rangeCount;
if (rangeCount) {
for (var i = 0, rangeTexts = []; i < rangeCount; ++i) {
rangeTexts.push("" + sel.getRangeAt(i));
}
selText = rangeTexts.join("");
}
} else if (document.selection && document.selection.type == "Text") {
selText = document.selection.createRange().text;
}
return selText;
}
UPDATE
This solution includes text inside <script> and <style> elements. To remove this, you could use cloneContents() on the selection ranges and traverse the DOM of the resulting document fragments, collecting text only from text nodes not contained within <script> and <style> elements. You could also expand on this to remove text that is inside elements with CSS display: none.
jsFiddle: http://jsfiddle.net/timdown/HkP2S/2/
Code:
function getSelectionRangeText() {
var selText = "", selTextParts = [];
function getNodeText(node) {
if (node.nodeType == 3) {
selTextParts.push(node.data);
} else if (node.hasChildNodes()
&& !(node.nodeType == 1 && /^(script|style)$/i.test(node.tagName))) {
for (var child = node.firstChild; !!child; child = child.nextSibling) {
getNodeText(child);
}
}
}
if (window.getSelection) {
var sel = window.getSelection(), rangeCount = sel.rangeCount;
if (rangeCount) {
for (var i = 0; i < rangeCount; ++i) {
getNodeText(sel.getRangeAt(i).cloneContents());
}
selText = selTextParts.join("");
}
} else if (document.selection && document.selection.type == "Text") {
selText = document.selection.createRange().text;
}
return selText;
}