sidonath (owner)

Revisions

  • 4ac435 sidonath Thu Jan 29 04:54:04 -0800 2009
gist: 54526 Download_button fork
public
Public Clone URL: git://gist.github.com/54526.git
Embed All Files: show embed
bottom-posting.user.js #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// ==UserScript==
// @name Gmail Bottom Posting v3
// @namespace http://z3c.info/
// @description Inserts the caret _after_ the quoted text when replying to emails using Gmail. Please view source for full credits.
// @include https://mail.google.tld/mail/*
// @include http://mail.google.tld/mail/*
// @include https://mail.google.tld/a/*
// @include http://mail.google.tld/a/*
// ==/UserScript==
 
/**
* Original script author: Herik N (http://userscripts.org/scripts/show/8041)
*
* Modified by: Rob Wilkerson (http://userscripts.org/scripts/show/14256)
* Comments:
* This is Henrik N's script with a few trivial modifications to support
* Gmail's new interface and a couple of cosmetic "improvements" that I prefer.
* The credit is his.
*
* Modified by: Damir Zekić
* Comments:
* Added some sexy OO and support for rich-text editor.
*/
 
function RichTextFormatter(editor)
{
    var body = editor.document.body;
 
    this.isReply = function()
    {
        // Gmail seems to put two different reply lines depending on the type
        // of the mail being replied to
        // * replying to plain-text mails:
        // 2008/10/23 J Smith <j.smith@gmail.com>
        // * replying to HTML mails:
        // On Thu, Oct 23, 2008 at 09:30, J Smith <jsmith@gmail.com> wrote:
        //
        // In first case in rich-text editor there is no colon in the end.
        return body.innerHTML.match(
            /^\<br\>\<br\>\<div class="\w+"\>\w+.*?\<br\>/);
    };
 
    this.format = function()
    {
        // remove signature from quotes
        var bq = body.getElementsByTagName('blockquote');
        for (var i = 0; i < bq.length; i++) {
            var qt = bq[i].innerHTML;
            qt = qt.replace(/\<br\>\n?\-\-(.|\n)*/, '');
            bq[i].innerHTML = qt;
        }
 
        // remove initial and trailing breaklines
        var t = body.innerHTML;
        t = t.replace(/^(\<br\>)+/, '');
        t = t.replace(/(\<br\>)+$/, '');
        body.innerHTML = t;
    };
 
    this.setCaretPosition = function()
    {
        var range = editor.getSelection().getRangeAt(0);
        // offset is based on number of nodes in body tag
        var caretOffset = 2;
        range.setStart(body, caretOffset);
    };
}
 
function PlainTextFormatter(editor)
{
    var body = editor.value;
 
    this.isReply = function()
    {
        return body.match(/^\n\n\w.*?:\n>/);
    };
 
    this.format = function()
    {
        // strip initial and trailing line breaks
     body = body.replace(/^\n+/, '');
     body = body.replace(/\n+$/, '');
 
        // remove signature from quoted text
        body = body.replace(/\> \-\- ?\n(> .*\n)+(>\n)?/, '');
 
        // assign new body
        editor.value = body;
    };
 
    this.setCaretPosition = function()
    {
     var signatureBegins = body.lastIndexOf("\n-- \n");
     var endOfContent = caretPosition = (signatureBegins == -1)
            ? body.length
            : signatureBegins;
 
        // there is a signature
     if (signatureBegins != -1) {
            caretPosition--;
     }
 
     editor.scrollTop = editor.scrollHeight;
    
        // a tiny timeout is necessary, or the caret won't move
     setTimeout(
            function() {
                // place caret at end
                editor.setSelectionRange(caretPosition, caretPosition);
     },
     1
     );
    };
}
 
function format(editor)
{
    var tf = (editor.name == "body")
        ? new PlainTextFormatter(editor)
        : new RichTextFormatter(editor);
 
    if (tf.isReply()) {
        tf.format();
        tf.setCaretPosition();
    }
}
 
if (frames.length > 3) {
    // frame in which Gmail UI is rendered
    var canvasFrame = frames[3];
 
    // handle all changes to the DOM Subtree
    canvasFrame.addEventListener(
        'DOMSubtreeModified',
        function() {
            if (canvasFrame.frames.length > 0) {
                // editor frame
                var editorFrame = canvasFrame.frames[0];
 
                // wait for editor frame to load
                editorFrame.addEventListener(
                    'load',
                    function() {
                        format(editorFrame);
                    },
                    false);
            }
        },
        true);
}
 
document.addEventListener(
    'focus',
    function(e) {
     // bail if the focused element is not a reply form
     if (!e.target.id || e.target.name != 'body') {
      return;
     }
 
        format(e.target);
    },
    true
);