I have an iframe text editor. For inserting image I have a snippet of code as :
.
.
.
var sel = document.getElementById('wysiwygtextfield').contentWindow.getSelection();
// get the first range of the selection (there's almost always only one range)
var range = sel.getRangeAt(0);
// deselect everything
sel.removeAllRanges();
// remove content of current selection from document
range.deleteContents();
// get location of current selection
var container = range.startContainer;
.
.
.
**afterNode = container.childNodes[0];
container.insertBefore(insertNode, afterNode);**
// This does not work
// container.insertAfter(insertNode, afterNode);
The problem lies with the last two lines. I tried using insertAfter but it doesn't seem to work. With insert before it inserts before the selected content or the element adjacent to it. Any way to make it insert after. This way it makes it appear as if the user if typing right to left instead of left to right.
I would try to avoid the use of iframes. Is there a way you can achieve your goal with a div or using AJAX calls with JQuery? This isn't exactly what your talking about but you can use the same idea for your WYSIWYG editor. http://techmeout.org/hacking-joomla/
Related
I can not come up with a suitable solution...
<p class="session" contenteditable="true">
Everything contained <b>**within**</b> this div is editable in browsers
that support <code>`HTML5`</code>. Go on, give it a try: click it and
start typing.
</p>
I want to add the appropriate HTML-tags while typing.
Of course it is no problem doing it by simple regex replacements. But I have problems setting the caret at the right place.
Say, in the example above, I want to emphasize the word "try". While typing the right * first and then the left star *, the text is converted to <i>*try*</i> but I want to preserve the position of the caret (set the the caret after the left *). And of cource vice versa, where the right * is set at last.
I find it more difficult to set the part contained <b>**within**</b> this say underlined. _contained <b>**within**</b> this_ becomes <u>_contained <b>**within**</b> this_</u>. So we are not in the same node.
I can think of complicated solutions, but since I am no expert in these text conversions techniques (range, window selection etc.) I wonder if there is a well known pratice of doing it.
Check out the Fiddle
I have tried to get the caret position as a first step and in the second step i have tried to put the caret back to the position .
$('.session').keyup(function(){
//alert("happening");
var sel = window.getSelection();
var offset=sel.anchorOffset;
// you can change the text in div by uncommeting the line below and replace your text with mathcing regex .
//$('.session').text($('.session').text().replace('/(\*.\*)+/','<i>$1<i>'));
setCaret(offset);
$('.session')
});
function setCaret(offset) {
var el = $('.session');
//alert();
var range = document.createRange();
var sel = window.getSelection();
range.setStart(el[0].childNodes[0],offset);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
el.focus();
}
You need to figure out how to change the text in the div as per your needs. While replacing the text inside the div also maintain the formatting so that the solution works.
I'm using Froala 2 and the documentation doesn't seem to have anything that implies a simple way to set the location of the caret, let alone at the beginning or end. I'm trying to seed the editor instance with a little content in certain cases and when I do using html.set, the caret just stays where it is at the beginning and I want to move it to the end. The internet doesn't seem to have anything helpful around this for v2.
Froala support provided an answer for me that works:
var editor = $('#edit').data('froala.editor');
editor.selection.setAtEnd(editor.$el.get(0));
editor.selection.restore();
As far as I know, Froala 2 doesn't provide any API to do this, but you can use native JavaScript Selection API.
This code should do the job:
// Selects the contenteditable element. You may have to change the selector.
var element = document.querySelector("#froala-editor .fr-element");
// Selects the last and the deepest child of the element.
while (element.lastChild) {
element = element.lastChild;
}
// Gets length of the element's content.
var textLength = element.textContent.length;
var range = document.createRange();
var selection = window.getSelection();
// Sets selection position to the end of the element.
range.setStart(element, textLength);
range.setEnd(element, textLength);
// Removes other selection ranges.
selection.removeAllRanges();
// Adds the range to the selection.
selection.addRange(range);
See also:
How to set caret(cursor) position in contenteditable element (div)?
Set caret position at a specific position in contenteditable div
I'm trying to make it so I can edit an iframe and be able to set selected text to bold. As you can see in the text below.
Now, I will explain how I am stuck, first of all here is some code:
var sel = $iFrame.get(0).contentWindow.getSelection();
if (sel.rangeCount) {
var text = sel.toString();
var range = sel.getRangeAt(0);
var parent = range.commonAncestorContainer;
if (parent.nodeType != 1) {
parent = parent.parentNode;
}
if (range.startOffset > 0) {
// change at offset
} else {
// change at beginning
}
}
So far I have acquired the parent node. But I'm struggling with how I can replace the content within the parent node with the new code including the tags. I also need it to consider that other text might already be bold and words might be repeated so i need it to make the exact highlighted option bold.
Also be able to reverse it to remove the bold from the selected text.
How can I proceed from this?
You don't want to insert tags yourself; just let the browser do it with the built-in commands. As long as the user has text selected in a contenteditable document, just running this function call will turn it bold:
document.execCommand('bold', false, null)
This works on practically every browser. Other commands and full documentation can be found here: https://developer.mozilla.org/en-US/docs/Web/API/document/execCommand
I am not able to figure out, how to highlight a selected text in an editable div (when it contains many tags (nested) in it).
If I could get the exact position from where selection starts (index in the editable div, innerHTML), I could add a font tag over there with background color style (giving the effect of highlight). But I am not able to figure out a reliable way to get the index from where the selection starts.
My sample code is at: Sample.
"window.getSelection();" method gives me complete text of what has been selected, including nested tags (if I use innerHTML on it). Thus all I need is a reliable way to calculate the start index from where selection is starting.
Any help/reference is greatly appreciated.
Edit:
Suppose my oDiv has content:
<br><br><h2>I am H2, Title</h2>
And say I select H2 above, I need starting index as: 19 (counting all the tags inside oDiv). How can I get that? I need it to work for arbitrary deep nesting.
var r = window.getSelection().getRangeAt(0); - gives the range inside the selection.
r.startOffset, r.endOffset - gives you the bounds of the range in selection.
If the div you are interested in has a id then you can get the element by:
var objDiv = document.getElementById("divId");
var r = document.createRange();
r.selectNodeContents(objDiv);
If the element doesn't have an id, then there are other means to get the object. See here: Finding HTML Elements
And now you can get the bounds of range r using the startOffset and endOffset properties.
I am using WYMEditor on my forum and users have the ability to "quote" messages of others. In such cases WYMEditor is loaded with content wrapped in blockquote tag.
Unfortunately usually the contents of the quote take more space than the input box size and when users click on the box end up entering their text inside the blockquote. This results in messy messages.
What I want is to scroll the contents of WYMEditor to the bottom, put cursor in the end and focus on the wym box. Unfortunately there is no such functionality in the WYMEditor api. There are some undocumented functions that provide selection management in the source, but my JavaScript/jQuery skills are not good enough to utilize them - I've tried but failed.
A combination of the postInit option and the jQuery scrollTop function should do the trick. I would also recommend inserting a placeholder paragraph for them along with scrolling to the bottom. For example:
jQuery('.wymeditor').wymeditor({
postInit: function (wym) {
var $contents,
$p,
$blockquote = jQuery(wym._doc).find('blockquote');
// Insert a placeholder empty paragraph
// so that users will be encouraged to not type inside the blockquote
$blockquote.after("<p>");
// Scroll the iframe to the bottom
$contents = $(wym._iframe).contents();
$contents.scrollTop($contents.height());
// Move the selection to the paragraph
$(wym._iframe).focus();
$p = jQuery(wym._doc).find('p');
var sel = rangy.getIframeSelection(wym._iframe),
range = rangy.createRange(wym._doc);
range.setStart($p[0], 0);
range.setEnd($p[0], 0);
range.collapse(true);
sel.setSingleRange(range);
if (jQuery.browser.msie) {
wym.saveCaret();
}
}
});