| 1 | var opts = { |
|---|
| 2 | 'enableForTextBoxes' : false, |
|---|
| 3 | 'pasteOnMiddleClick' : false, |
|---|
| 4 | 'copyAsPlainText' : false, |
|---|
| 5 | 'includeUrl' : false, |
|---|
| 6 | 'prependUrl' : false, |
|---|
| 7 | 'includeUrlText' : "", |
|---|
| 8 | 'includeUrlCommentCountEnabled' : false, |
|---|
| 9 | 'includeUrlCommentCount' : 5, |
|---|
| 10 | 'mouseDownTarget' : null |
|---|
| 11 | }; |
|---|
| 12 | |
|---|
| 13 | //----------------------------------------------------------------------------- |
|---|
| 14 | // window.localStorage is available, but doesn't appear to be initialized |
|---|
| 15 | // when accessed from content scripts so I'm using message passing and a |
|---|
| 16 | // background page to get the info. |
|---|
| 17 | //----------------------------------------------------------------------------- |
|---|
| 18 | chrome.extension.sendRequest( |
|---|
| 19 | { |
|---|
| 20 | "type" : "config", |
|---|
| 21 | "keys" : [ |
|---|
| 22 | "enableForTextBoxes", "pasteOnMiddleClick", "copyAsPlainText", |
|---|
| 23 | "includeUrl", "prependUrl", "includeUrlText", |
|---|
| 24 | "includeUrlCommentCountEnabled", "includeUrlCommentCount" |
|---|
| 25 | ] |
|---|
| 26 | }, |
|---|
| 27 | function (resp) { |
|---|
| 28 | opts.enableForTextBoxes = |
|---|
| 29 | (resp.enableForTextBoxes === "true") ? true : false; |
|---|
| 30 | opts.pasteOnMiddleClick = |
|---|
| 31 | (resp.pasteOnMiddleClick === "true") ? true : false; |
|---|
| 32 | opts.copyAsPlainText = (resp.copyAsPlainText === "true") ? true : false; |
|---|
| 33 | opts.includeUrl = (resp.includeUrl === "true") ? true : false; |
|---|
| 34 | opts.prependUrl = (resp.prependUrl === "true") ? true : false; |
|---|
| 35 | opts.includeUrlCommentCountEnabled = |
|---|
| 36 | (resp.includeUrlCommentCountEnabled === "true") ? true : false; |
|---|
| 37 | opts.includeUrlCommentCount = |
|---|
| 38 | (isNaN(resp.includeUrlCommentCount)) ? 5 : resp.includeUrlCommentCount; |
|---|
| 39 | opts.includeUrlText = |
|---|
| 40 | (resp.includeUrlText === " ") ? "" : resp.includeUrlText; |
|---|
| 41 | } |
|---|
| 42 | ); |
|---|
| 43 | |
|---|
| 44 | //----------------------------------------------------------------------------- |
|---|
| 45 | // The mouseup target is the element at the point the mouseup event occurs. |
|---|
| 46 | // It is possible to select text within a text field but have the mouse cursor |
|---|
| 47 | // move outside of the text field which makes it impossible to tell if a text |
|---|
| 48 | // field element was involved in the selection. In order to work around this |
|---|
| 49 | // the mousedown target is used to determine if a text field is involved. |
|---|
| 50 | // |
|---|
| 51 | // It is only important if the user wants to exclude selections from text |
|---|
| 52 | // fields |
|---|
| 53 | // |
|---|
| 54 | // The if is always evaluating to false because the message passing hasn't |
|---|
| 55 | // occurred by the time this code segment is executed. I'm leaving it in |
|---|
| 56 | // as a placeholder in case localStorage gets initialized directly for content |
|---|
| 57 | // pages. |
|---|
| 58 | //----------------------------------------------------------------------------- |
|---|
| 59 | if (!opts.enableForTextBoxes) { |
|---|
| 60 | document.body.addEventListener( |
|---|
| 61 | "mousedown", |
|---|
| 62 | function (e) { |
|---|
| 63 | opts.mouseDownTarget = e.target; |
|---|
| 64 | }, |
|---|
| 65 | false |
|---|
| 66 | ); |
|---|
| 67 | } |
|---|
| 68 | |
|---|
| 69 | document.body.addEventListener( |
|---|
| 70 | "mouseup", |
|---|
| 71 | function (e) { |
|---|
| 72 | var rv, s, el, text; |
|---|
| 73 | |
|---|
| 74 | if (opts.pasteOnMiddleClick && e.button === 1) { |
|---|
| 75 | try { |
|---|
| 76 | chrome.extension.sendRequest( |
|---|
| 77 | { |
|---|
| 78 | "type" : "paste", |
|---|
| 79 | "text" : text, |
|---|
| 80 | }, |
|---|
| 81 | function(text) { |
|---|
| 82 | var el = e.target; |
|---|
| 83 | var p1, p2; |
|---|
| 84 | |
|---|
| 85 | if ( |
|---|
| 86 | e.target.nodeName === "INPUT" || |
|---|
| 87 | e.target.nodeName === "TEXTAREA" |
|---|
| 88 | ) { |
|---|
| 89 | p1 = el.value.substring(0,el.selectionStart); |
|---|
| 90 | p2 = el.value.substring(el.selectionEnd); |
|---|
| 91 | |
|---|
| 92 | el.value = p1 + text + p2; |
|---|
| 93 | } else { |
|---|
| 94 | console.log( |
|---|
| 95 | e.target.nodeName+" is not a valid element to paste into" |
|---|
| 96 | ); |
|---|
| 97 | } |
|---|
| 98 | } |
|---|
| 99 | ); |
|---|
| 100 | } catch (ex) { |
|---|
| 101 | console.log("Caught exception: "+ex); |
|---|
| 102 | } |
|---|
| 103 | return; |
|---|
| 104 | } |
|---|
| 105 | //------------------------------------------------------------------------- |
|---|
| 106 | |
|---|
| 107 | if ( |
|---|
| 108 | !opts.enableForTextBoxes && |
|---|
| 109 | (opts.mouseDownTarget.nodeName === "INPUT" || |
|---|
| 110 | opts.mouseDownTarget.nodeName === "TEXTAREA") |
|---|
| 111 | ){ |
|---|
| 112 | return; |
|---|
| 113 | } |
|---|
| 114 | |
|---|
| 115 | //------------------------------------------------------------------------- |
|---|
| 116 | // I'm having to force this setting as of Chrome 6 because of a change in |
|---|
| 117 | // Chrome 6 (actually in webkit) that disables execCommand. It still |
|---|
| 118 | // works in background pages which means the copy as plain text option |
|---|
| 119 | // still works. |
|---|
| 120 | //------------------------------------------------------------------------- |
|---|
| 121 | //opts.copyAsPlainText = true; |
|---|
| 122 | //------------------------------------------------------------------------- |
|---|
| 123 | |
|---|
| 124 | var comment, count=0, flag=true; |
|---|
| 125 | try { |
|---|
| 126 | s = window.getSelection(); |
|---|
| 127 | text = s.toString(); |
|---|
| 128 | |
|---|
| 129 | //----------------------------------------------------------------------- |
|---|
| 130 | // Don't execute the copy if nothing is selected. |
|---|
| 131 | //----------------------------------------------------------------------- |
|---|
| 132 | if (text.length <= 0) { |
|---|
| 133 | return; |
|---|
| 134 | } |
|---|
| 135 | |
|---|
| 136 | if (opts.copyAsPlainText || opts.includeUrl) { |
|---|
| 137 | count = (text.split(/\s+/)).length; |
|---|
| 138 | |
|---|
| 139 | if ( |
|---|
| 140 | opts.includeUrlCommentCountEnabled && |
|---|
| 141 | count <= opts.includeUrlCommentCount |
|---|
| 142 | ) { |
|---|
| 143 | flag = false; |
|---|
| 144 | } |
|---|
| 145 | |
|---|
| 146 | if (opts.includeUrl && opts.includeUrlText && flag) { |
|---|
| 147 | comment = opts.includeUrlText; |
|---|
| 148 | |
|---|
| 149 | if (opts.includeUrlText.indexOf('$title') >= 0) { |
|---|
| 150 | comment = comment.replace(/\$title/g, document.title); |
|---|
| 151 | } |
|---|
| 152 | |
|---|
| 153 | if (opts.includeUrlText.indexOf('$url') >= 0) { |
|---|
| 154 | comment = comment.replace(/\$url/g, document.URL); |
|---|
| 155 | } |
|---|
| 156 | |
|---|
| 157 | if (opts.includeUrlText.indexOf('$crlf') >= 0) { |
|---|
| 158 | comment = comment.replace(/\$crlf/g, "\n"); |
|---|
| 159 | } |
|---|
| 160 | |
|---|
| 161 | if (opts.prependUrl) { |
|---|
| 162 | text = comment + "\n" + text; |
|---|
| 163 | } else { |
|---|
| 164 | text += "\n" + comment; |
|---|
| 165 | } |
|---|
| 166 | } |
|---|
| 167 | |
|---|
| 168 | chrome.extension.sendRequest( |
|---|
| 169 | { |
|---|
| 170 | "type" : "reformat", |
|---|
| 171 | "text" : text, |
|---|
| 172 | } |
|---|
| 173 | ); |
|---|
| 174 | } else { |
|---|
| 175 | rv = document.execCommand("copy"); |
|---|
| 176 | } |
|---|
| 177 | } catch (ex) { |
|---|
| 178 | console.log("Caught exception: "+ex); |
|---|
| 179 | } |
|---|
| 180 | return; |
|---|
| 181 | }, |
|---|
| 182 | false |
|---|
| 183 | ); |
|---|