1

I am writing a script to insert presaved html content into Gmail's editable iframe in the compose page mentioned below. This script is only to be used in Greasemonkey on Firefox. So I don't need to consider any other browser.

Currently it inserts the text once and then gets bugged. I guess because range.setStart() expects first parameter is a node, which createContextualFragment() does not return.

Is there any other way to add html at current cursor's position and then move cursor to the end of the added html (not to the end of all content)?

https://mail.google.com/mail/?view=cm&fs=1&tf=1&source=mailto&to=example@example.com

function insertTextAtCursor(text) {
    var sel, range, html, textNode;
    if (window.frames[3].window.frames[0].getSelection()) {
        sel = window.frames[3].window.frames[0].getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();
            textNode = range.createContextualFragment(text);
            //textNode = document.createTextNode(text);
            range.insertNode( textNode );
            range.setStart(textNode, textNode.length);
            range.setEnd(textNode, textNode.length);
            sel.removeAllRanges();
            sel.addRange(range);
            window.frames[3].window.frames[0].focus();
        }
    }
}

Update 1: If i comment the code to move the cursor after inserting html then its no longer bugged, but the cursor stays in the same place.

//range.setStart(textNode, textNode.length);
//range.setEnd(textNode, textNode.length);
sel.removeAllRanges();
//sel.addRange(range);
Rob
  • 4,927
  • 12
  • 49
  • 54

1 Answers1

1

got you something.

with the help from this answer, i wrote this:

  1. paste your text/html at the cursor position
  2. move the cursor to the end of the text area

save this as test.html to test it locally

<html>

<head>
    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    <script>
    jQuery.fn.extend({
        insertAtCaret: function(myValue){
          return this.each(function(i) {
            if (document.selection) {
              //For browsers like Internet Explorer
              this.focus();
              sel = document.selection.createRange();
              sel.text = myValue;
              this.focus();
            }
            else if (this.selectionStart || this.selectionStart == '0') {
              //For browsers like Firefox and Webkit based
              var startPos = this.selectionStart;
              var endPos = this.selectionEnd;
              var scrollTop = this.scrollTop;
              this.value = this.value.substring(0, startPos)+myValue+this.value.substring(endPos,this.value.length);
              this.focus();
              this.selectionStart = startPos + myValue.length;
              this.selectionEnd = startPos + myValue.length;
              this.scrollTop = scrollTop;
            } 
            else {
              this.value += myValue;
              this.focus();
            }
          })
        }
    });

    var myhtml = '<b> this html will be <i>added</i> to the </b> cursor position (and will move to the end)';
    var movetotheendof = '';
    $(window).load(function(){
        $('#btnpastepre').click(function() {
            $('#txtarea').insertAtCaret(myhtml)
            movetotheendof = $('#txtarea').val()
            $('#txtarea').val("").val(movetotheendof)
        })
    });
    </script>
</head>

<body>

    <div id="formcontainer">
        <button id="btnpastepre">click to paste</button>

        <form id="formulario">
            <textarea id="txtarea" cols=60 rows=20></textarea>
        </form>
    </div>

</body>

</html>

or click here to test it online: http://jsfiddle.net/RASG/Vwwm4/

Now all you have to do is change it according to your needs (gmail or any other site)

EDIT

I forgot that you wanted a GM script :)
Here it is

// ==UserScript==
// @name        TESTE 3
// @namespace   TESTE 3
// @description TESTE 3
// @require     http://code.jquery.com/jquery.min.js
// @include     *
// @version     1
// ==/UserScript==


jQuery.fn.extend({
    insertAtCaret: function(myValue){
        return this.each(function(i) {
            if (document.selection) {
                //For browsers like Internet Explorer
                this.focus();
                sel = document.selection.createRange();
                sel.text = myValue;
                this.focus();
            }
            else if (this.selectionStart || this.selectionStart == '0') {
                //For browsers like Firefox and Webkit based
                var startPos = this.selectionStart;
                var endPos = this.selectionEnd;
                var scrollTop = this.scrollTop;
                this.value = this.value.substring(0, startPos)+myValue+this.value.substring(endPos,this.value.length);
                this.focus();
                this.selectionStart = startPos + myValue.length;
                this.selectionEnd = startPos + myValue.length;
                this.scrollTop = scrollTop;
            } 
            else {
                this.value += myValue;
                this.focus();
            }
        })
    }
});

var myhtml = '<b> this html will be <i>added</i> to the </b> cursor position (and will move to the end)';
var movetotheendof = '';

$(window).load(function(){
    $('#btnpastepre').click(function() {
        $('#txtarea').insertAtCaret(myhtml)
        movetotheendof = $('#txtarea').val()
        $('#txtarea').val("").val(movetotheendof)
    })
})

Just create an html file with this content to test it

<html>
<head>
    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
    <div id="formcontainer">
        <button id="btnpastepre">click to paste</button>
        <form id="formulario">
            <textarea id="txtarea" cols=60 rows=20></textarea>
        </form>
    </div>
</body>
</html>
Community
  • 1
  • 1
RASG
  • 5,988
  • 4
  • 26
  • 47