execCommand behavior in IE : CLEditor image overwrite problem - javascript

I am using CLEditor in my site and I am facing a problem when using it with IE. The problem is: When you insert image and place it in the editor then insert another image , it will overwrite the prevoius one. With Firefox it will place the new one beside the prevoius one. I contacted the CLEditor and he told me this is a browser sprecific issue. He adivse me to make a work around by checking for IE then collapse the current range to its end using TextRange.collapse() method after the image have been inserted. I tried to make this soultion but I am not expert with Javascript to make it works. I need your help to make it working.
This is the code for inserting the image to the editor area:
.bind(CLICK, function() {
// Insert the image or link if a url was entered
var $text = $popup.find(":text"),
url = $.trim($text.val());
if (url !== "")
execCommand(editor, data.command, url, null, data.button);
// Reset the text, hide the popup and set focus
$text.val("http://");
hidePopups();
focus(editor);
});

This is the solution for this problem. It take three days to solve this because I am not JavaScript expert. I hope this will help.
.bind(CLICK, function() {
// Insert the image or link if a url was entered
var $text = $popup.find(":text"),
url = $.trim($text.val());
if (url !== "")
execCommand(editor, data.command, url, null, data.button);
// Reset the text, hide the popup and set focus
$text.val("http://");
hidePopups();
if ($.browser.msie) {
var editorvalue=editor.$frame[0].contentWindow;
var pos = editorvalue.document.body.innerHTML.length;
var textRange = editorvalue.document.body.createTextRange();
textRange.collapse(true);
textRange.moveEnd("character", pos);
textRange.moveStart("character", pos);
textRange.select();
}
focus(editor);
});

Related

How to perform programmatic text input that supports both undo and redo?

My current Chrome extension is supposed to programmatically insert text on user input. This works great, however, it mangles the undo/redo behavior of all text editors I've tried it on so far. So, the following routine:
type some text
insert some text programmatically
type more text
press ctrl-z thrice
does not always revert to a blank state. Very often it will get stuck somewhere in the middle. Its behaviour is mostly inconsistent.
Here's an MCVE of the content script:
function init() {
var $input = document.getElementsByTagName("textarea")[0];
if (!$input) {
console.log("No input element found.");
return true;
}
var $btn = document.createElement("button");
$btn.innerHTML = "Click";
$btn.addEventListener("click", function() {
var caretPos = $input.selectionStart;
$input.value = $input.value.substring(0, caretPos) + " test string " + $input.value.substring(caretPos);
});
$input.parentElement.insertBefore($btn, $input);
return true;
}
window.addEventListener("load", init);
<div><textarea></textarea></div>
(I also bundled it as a Chrome extension in case you'd like that.)
I want the undo/redo to function perfectly in both textarea as well as contenteditable nodes. I also tried document.execCommand in both insertText and insertHTML modes without any success. I've looked at the other two related questions but they do not answer my query. (q1, q2)
What else can be a possible solution to this problem?
Thanks to the helpful comments above, my problem was doing execCommand on pre-programmed weird editors like Facebook messenger box, tinymce, etc. They might have their own customizations interfering.
In normal text editors, document.execCommand should work fine, and support undo/redo. Use it like so:
document.execCommand('insertText', false, "text");
document.execCommand('insertHTML', false, "html");

TinyMCE disappears after save Widget in Wordpress

first of all, sorry for my bad english, I'm from Germany.
I just created my first widget. It's a widget that creates automatically a grid out of a list.
I can add a new list-item and every form field will be duplicated.
But after 3 days of searching the internet without a result I decided to ask by myself...
So here is my first problem, when I add a new item, the TinyMCE in the new item is disabled, I can't click on the buttons or type text into it.
There are no errors in the console log.
My second problem is when I save the widget, all TinyMCE-Editors disappear and leave the textareas, with the html code.
Here also: no errors... but I've seen, that the TinyMCE isn't loading after save. There is no iframe, nothing but the textarea.
After reload the widget page, everything is fine again for both problems.
So I have to add new items and save the page and then reload it to edit and edit the content, but that don't solve the problem.
I think I have to reinitialize the TinyMCE but I don't know how.
I had problems with adding the wordpress editor to my widget so I integrated the jQuery TinyMCE from the website.
Here is the code snippet of my add-function:
$("body").on('click.sgw','.sgw-add',function() {
var sgw = $(this).parent().parent();
var num = sgw.find('.simple-grid .list-item').length + 1;
sgw.find('.amount').val(num);
var item = sgw.find('.simple-grid .list-item:last-child').clone();
var item_id = item.attr('id');
item.attr('id',increment_last_num(item_id));
$('.toggled-off',item).removeClass('toggled-off');
$('.number',item).html(num);
$('.item-title',item).html('');
$('.custom_media_image',item).attr('src','');
$('textarea',item).val('');
$('img.custom_media_image',item).each(function() {
var class_val = $(this).attr('class');
$(this).attr('class',increment_last_num(class_val));
});
$('textarea',item).each(function() {
var id_iframe = $(this).attr('id');
tinymce.EditorManager.execCommand('mceRemoveEditor',true, id_iframe);
tinymce.EditorManager.execCommand('mceAddEditor',true, id_iframe);
});
$('label',item).each(function() {
var for_val = $(this).attr('for');
$(this).attr('for',increment_last_num(for_val));
});
$('input',item).each(function() {
var id_val = $(this).attr('id');
var name_val = $(this).attr('name');
$(this).attr('id',increment_last_num(id_val));
$(this).attr('name',increment_last_num(name_val));
if($(':checked',this)){
$(this).removeAttr('checked');
}
if($(this).hasClass('custom_media_button') || $(this).hasClass('custom_media_url')){
var class_val = $(this).attr('class');
$(this).attr('class',increment_last_num(class_val));
}
if($(this).hasClass('button-primary')){
var number_val = $(this).attr('number');
$(this).attr('number',increment_last_num(number_val));
}
$(this).not('#custom_media_button').val('');
});
sgw.find('.simple-grid').append(item);
sgw.find('.order').val(sgw.find('.simple-grid').sortable('toArray'));
});
I hope this is understandable and someone can help me.
You can download the zip here: https://www.dropbox.com/s/22b8q29v94n7mdj/simple-grid-widget.zip?dl=0
Are you trying to run several editors at once? There's a limitation with Wordpress and TinyMCE where you can basically one editor at a time. I've gotten around that but it was very difficult.
To load a new editor you may have to remove the old one:
tinymce.remove();

Replace text in textarea on his exact position [duplicate]

I'm trying to use Javascript to replace the selected text in an arbitrary selected TEXTAREA node in Chrome (! not a content editable div !) The code fragment I see repeated in lots of places to replace selected text basically does this:
var sel = window.getSelection();
var range = sel.getRangeAt(0);
range.insertNode( document.createTextNode("test "));
However, this does not work for input fields such as TEXTAREA or INPUT TYPE=TEXT. The text is inserted BEFORE the TEXTAREA instead of inside it.
There is an alternative method to modify the selection text inside a text area using textarea.selectionStart and textarea.selectionEnd. However, these require figuring out which textarea element is actually active/selected. Chrome/Webkit document.activeElement seems to be broken and has been broken for a long time. I can't figure out any workaround to find the "currently selected textarea". See the bug here...
http://code.google.com/p/chromium/issues/detail?id=14436
You can see a micro-demo of the problem I'm trying to solve here.
http://dj1.willowmail.com/~jeske/_drop/insertIssue/1.html
http://ajaxandxml.blogspot.com/2007/11/emulating-activeelement-property-with.html
Any thoughts on this?
Given a webpage with an arbitrary bit of text selected in an arbitrary TEXTAREA node, without knowing ahead of time what textarea the focus is in, how do I find the active textarea and replace the selected text with some other text?
(( FYI: I'm using this code in a Chrome extension. An in-page javascript content script is extending the page javascript, so I have no idea what the page structure is ahead of time. It needs to work for any webpage. ))
I think the problem you may be having is that the active element changes as a result of clicking the button before your code runs. If you instead use the mousedown event and prevent the default button action, it works fine in Chrome:
http://jsfiddle.net/b3Fk5/2/
It appears that as of 8/23/2012, Chrome does not properly support activeElement, as it is often set to "body" when it shouldn't be.
There may also be some challenges because in my chrome extension, right-clicking to get a context menu might be altering the activeElement.
The solution was to provide a focus handler to create a more reliable activeElement in Chrome, and then use direct interaction with the TEXTAREA to handle the selection replacement.
var dActiveElement = null;
function _dom_trackActiveElement(evt) {
if (evt && evt.target) {
dActiveElement = evt.target;
console.log("focus on: " + dActiveElement.nodeName +
" id: " + dActiveElement.id);
} else {
console.log("focus else..");
}
}
if (document.addEventListener) {
document.addEventListener("focus",_dom_trackActiveElement,true);
}
function insertTextAtCursor(text) {
console.log("insertTextAtCursor : " + text);
if (dActiveElement.nodeName.toUpperCase() == "TEXTAREA") {
console.log("selection in textarea! id: " + dActiveElement.id);
var ta = dActiveElement;
var saveSelectionStart = ta.selectionStart;
var newvalue = ta.value.slice(0,ta.selectionStart) +
text + ta.value.slice(ta.selectionEnd,ta.length);
console.log("output : " + newvalue + ", len : " + newvalue.length);
var newSelectionEnd = ta.selectionStart + text.length;
ta.value = newvalue;
ta.selectionStart = ta.selectionEnd = (newSelectionEnd);
}
}

Specific UIWebView Selections (only entire words/sentences)

I want users to only be able to select an entire sentences within my UIWebView. I'm using my own UIMenuItem (a bookmark button) in a UIWebView. I am going to save this bookmark (core data) and would like to determine which sentence/verse the highlight is in. I am laying out the html programmatically (building up from a sqlite database), and have a <span id="x"> (where x is a variable integer) surrounding every sentence. I know that the Amazon Kindle app only lets users select entire words. How can I do this?
Thanks!
Did you tried setMarkedText:selectedRange:?
Apple developer lib
Update:
While you can't use setMarkedText inside the UIWebView there is no way but using JavaScript. I don't know, if you can manipulate the HTML page that you are showing or not? you can add this script in the page. If you can't manipulate the page you should load an iframe inside your UIWebView that loads your actual page and after the iframe add this script.
Here is the script:
document.addEventListener('mouseup', function(){
if(getSelection().anchorNode != null ){
var sel = getSelection(),
range = sel.getRangeAt(0),
nodeValue = sel.anchorNode.nodeValue,
lastCharIndex = range.endOffset,
firstCharIndex = range.startOffset,
lastChar = nodeValue.substr(lastCharIndex, 1),
firstChar = nodeValue.substr(firstCharIndex, 1);
while(lastChar != (" " || ".")){
lastChar = nodeValue.substr(lastCharIndex, 1);
lastCharIndex++;
};
while(firstChar != " "){
firstChar = nodeValue.substr(firstCharIndex, 1);
firstCharIndex--;
};
range.setEnd(sel.anchorNode, lastCharIndex-1);
sel.addRange(range);
range.setStart(sel.anchorNode, firstCharIndex+2);
sel.addRange(range);
}
}, false);
I tested this on my iPhone and it was working fine.
Here is the Demo (just select something).
I spent a lot time on it. I hope you enjoy it.

Tooltip triggered by text selection

I am looking to create a tooltip that is triggered by the selection of text (left-click dragging over text). Preferably by creating a JQuery plugin.
My ultimate goal is when a user selects/highlights a sentence, phrase, paragraph, it will trigger a tooltip. The tooltip will contain social sharing buttons that will allow a user to post the selection to their personal profile status.
So if you like a particular quote, you can select it, click share to twitter, it will call the twitter api to post the selection (if over the 140 characters it will add an ellipsis) with a shortened url back to the page of the selection.
Obviously this is going to take a bit of development, but as a front-end designer I just need to get the ball rolling. Thank you for any help you can provide.
An example of the functionality I desire is similar to how the apture extension functions:
http://www.apture.com/extension/
Here's a little demo: http://jsfiddle.net/sje397/fNt22/
It just monitors the selected text on a timer and tracks the mouse position, then creates a hovering div with a 'share' button at the mouse position whenever the selected text is not empty.
var mousePos;
$(document).mousemove(function (e) {
mousePos = {left: e.pageX + 20, top: e.pageY + 20};
});
var selectedText = '';
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;
}
}
function checkSelectionChanged() {
var current = getSelectedText();
if(current != selectedText) {
selectedText = current;
if(selectedText != '') {
$('#quote #text').text(selectedText);
$('#quote').offset(mousePos);
$('#quote').show();
} else {
$('#quote').hide();
}
}
}
setInterval(checkSelectionChanged, 1000);
I already wrote this plugin :)
http://www.latentmotion.com/search-and-share
You're welcome to adapt upon it all you like, as long as you give credit.
I've also written a somewhat slicker one, but never fully vetted it (it's kinda in alpha):
http://seox.org/pro-beta.html

Categories