[ Index ] |
|
Code source de Horde 3.1.3 |
1 // Context Menu Plugin for HTMLArea-3.0 2 // Sponsored by www.americanbible.org 3 // Implementation by Mihai Bazon, http://dynarch.com/mishoo/ 4 // 5 // (c) dynarch.com 2003-2005. 6 // Distributed under the same terms as HTMLArea itself. 7 // This notice MUST stay intact for use (see license.txt). 8 // 9 // $Id: context-menu.js,v 1.6 2005/01/20 17:49:03 mishoo Exp $ 10 11 HTMLArea.loadStyle("menu.css", "ContextMenu"); 12 13 function ContextMenu(editor) { 14 this.editor = editor; 15 }; 16 17 ContextMenu._pluginInfo = { 18 name : "ContextMenu", 19 version : "1.0", 20 developer : "Mihai Bazon", 21 developer_url : "http://dynarch.com/mishoo/", 22 c_owner : "dynarch.com", 23 sponsor : "American Bible Society", 24 sponsor_url : "http://www.americanbible.org", 25 license : "htmlArea" 26 }; 27 28 ContextMenu.prototype.onGenerate = function() { 29 var self = this; 30 var doc = this.editordoc = this.editor._iframe.contentWindow.document; 31 HTMLArea._addEvents(doc, ["contextmenu"], 32 function (event) { 33 return self.popupMenu(HTMLArea.is_ie ? self.editor._iframe.contentWindow.event : event); 34 }); 35 this.currentMenu = null; 36 }; 37 38 ContextMenu.prototype.getContextMenu = function(target) { 39 var self = this; 40 var editor = this.editor; 41 var config = editor.config; 42 var menu = []; 43 var tbo = this.editor.plugins.TableOperations; 44 if (tbo) tbo = tbo.instance; 45 var i18n = ContextMenu.I18N; 46 47 var selection = editor.hasSelectedText(); 48 if (selection) 49 menu.push([ i18n["Cut"], function() { editor.execCommand("cut"); }, null, config.btnList["cut"][1] ], 50 [ i18n["Copy"], function() { editor.execCommand("copy"); }, null, config.btnList["copy"][1] ]); 51 menu.push([ i18n["Paste"], function() { editor.execCommand("paste"); }, null, config.btnList["paste"][1] ]); 52 53 var currentTarget = target; 54 var elmenus = []; 55 var tmp; 56 57 var link = null; 58 var table = null; 59 var tr = null; 60 var td = null; 61 var img = null; 62 63 function tableOperation(opcode) { 64 tbo.buttonPress(editor, opcode); 65 }; 66 67 function insertPara(currentTarget, after) { 68 var el = currentTarget; 69 var par = el.parentNode; 70 var p = editor._doc.createElement("p"); 71 p.appendChild(editor._doc.createElement("br")); 72 par.insertBefore(p, after ? el.nextSibling : el); 73 var sel = editor._getSelection(); 74 var range = editor._createRange(sel); 75 if (!HTMLArea.is_ie) { 76 sel.removeAllRanges(); 77 range.selectNodeContents(p); 78 range.collapse(true); 79 sel.addRange(range); 80 } else { 81 range.moveToElementText(p); 82 range.collapse(true); 83 range.select(); 84 } 85 }; 86 87 for (; target; target = target.parentNode) { 88 var tag = target.tagName; 89 if (!tag) 90 continue; 91 tag = tag.toLowerCase(); 92 switch (tag) { 93 case "img": 94 img = target; 95 elmenus.push(null, 96 [ i18n["Image Properties"], 97 function() { 98 editor._insertImage(img); 99 }, 100 i18n["Show the image properties dialog"], 101 config.btnList["insertimage"][1] ] 102 ); 103 break; 104 case "a": 105 link = target; 106 elmenus.push(null, 107 [ i18n["Modify Link"], 108 function() { editor.execCommand("createlink", true); }, 109 i18n["Current URL is"] + ': ' + link.href, 110 config.btnList["createlink"][1] ], 111 112 [ i18n["Check Link"], 113 function() { window.open(link.href); }, 114 i18n["Opens this link in a new window"] ], 115 116 [ i18n["Remove Link"], 117 function() { 118 if (confirm(i18n["Please confirm that you want to unlink this element."] + "\n" + 119 i18n["Link points to:"] + " " + link.href)) { 120 while (link.firstChild) 121 link.parentNode.insertBefore(link.firstChild, link); 122 link.parentNode.removeChild(link); 123 } 124 }, 125 i18n["Unlink the current element"] ] 126 ); 127 break; 128 case "td": 129 td = target; 130 if (!tbo) break; 131 elmenus.push(null, 132 [ i18n["Cell Properties"], 133 function() { tableOperation("TO-cell-prop"); }, 134 i18n["Show the Table Cell Properties dialog"], 135 config.btnList["TO-cell-prop"][1] ], 136 [ i18n["Delete Cell"], 137 function() { tableOperation("TO-cell-delete"); }, null, 138 config.btnList["TO-cell-delete"][1] ] 139 ); 140 break; 141 case "tr": 142 tr = target; 143 if (!tbo) break; 144 elmenus.push(null, 145 [ i18n["Row Properties"], 146 function() { tableOperation("TO-row-prop"); }, 147 i18n["Show the Table Row Properties dialog"], 148 config.btnList["TO-row-prop"][1] ], 149 150 [ i18n["Insert Row Before"], 151 function() { tableOperation("TO-row-insert-above"); }, 152 i18n["Insert a new row before the current one"], 153 config.btnList["TO-row-insert-above"][1] ], 154 155 [ i18n["Insert Row After"], 156 function() { tableOperation("TO-row-insert-under"); }, 157 i18n["Insert a new row after the current one"], 158 config.btnList["TO-row-insert-under"][1] ], 159 160 [ i18n["Delete Row"], 161 function() { tableOperation("TO-row-delete"); }, 162 i18n["Delete the current row"], 163 config.btnList["TO-row-delete"][1] ] 164 ); 165 break; 166 case "table": 167 table = target; 168 if (!tbo) break; 169 elmenus.push(null, 170 [ i18n["Table Properties"], 171 function() { tableOperation("TO-table-prop"); }, 172 i18n["Show the Table Properties dialog"], 173 config.btnList["TO-table-prop"][1] ], 174 175 [ i18n["Insert Column Before"], 176 function() { tableOperation("TO-col-insert-before"); }, 177 i18n["Insert a new column before the current one"], 178 config.btnList["TO-col-insert-before"][1] ], 179 180 [ i18n["Insert Column After"], 181 function() { tableOperation("TO-col-insert-after"); }, 182 i18n["Insert a new column after the current one"], 183 config.btnList["TO-col-insert-after"][1] ], 184 185 [ i18n["Delete Column"], 186 function() { tableOperation("TO-col-delete"); }, 187 i18n["Delete the current column"], 188 config.btnList["TO-col-delete"][1] ] 189 ); 190 break; 191 case "body": 192 elmenus.push(null, 193 [ i18n["Justify Left"], 194 function() { editor.execCommand("justifyleft"); }, null, 195 config.btnList["justifyleft"][1] ], 196 [ i18n["Justify Center"], 197 function() { editor.execCommand("justifycenter"); }, null, 198 config.btnList["justifycenter"][1] ], 199 [ i18n["Justify Right"], 200 function() { editor.execCommand("justifyright"); }, null, 201 config.btnList["justifyright"][1] ], 202 [ i18n["Justify Full"], 203 function() { editor.execCommand("justifyfull"); }, null, 204 config.btnList["justifyfull"][1] ] 205 ); 206 break; 207 } 208 } 209 210 if (selection && !link) 211 menu.push(null, [ i18n["Make link"], 212 function() { editor.execCommand("createlink", true); }, 213 i18n["Create a link"], 214 config.btnList["createlink"][1] ]); 215 216 for (var i = 0; i < elmenus.length; ++i) 217 menu.push(elmenus[i]); 218 219 if (!/html|body/i.test(currentTarget.tagName)) { 220 table ? (tmp = table, table = null) : (tmp = currentTarget); 221 menu.push(null, 222 [ i18n["Remove the"] + " <" + tmp.tagName + "> " + i18n["Element"], 223 function() { 224 if (confirm(i18n["Please confirm that you want to remove this element:"] + " " + 225 tmp.tagName)) { 226 var el = tmp; 227 var p = el.parentNode; 228 p.removeChild(el); 229 if (HTMLArea.is_gecko) { 230 if (p.tagName.toLowerCase() == "td" && !p.hasChildNodes()) 231 p.appendChild(editor._doc.createElement("br")); 232 editor.forceRedraw(); 233 editor.focusEditor(); 234 editor.updateToolbar(); 235 if (table) { 236 var save_collapse = table.style.borderCollapse; 237 table.style.borderCollapse = "collapse"; 238 table.style.borderCollapse = "separate"; 239 table.style.borderCollapse = save_collapse; 240 } 241 } 242 } 243 }, 244 i18n["Remove this node from the document"] ], 245 [ i18n["Insert paragraph before"], 246 function() { insertPara(tmp, false); }, 247 i18n["Insert a paragraph before the current node"] ], 248 [ i18n["Insert paragraph after"], 249 function() { insertPara(tmp, true); }, 250 i18n["Insert a paragraph after the current node"] ] 251 ); 252 } 253 return menu; 254 }; 255 256 ContextMenu.prototype.popupMenu = function(ev) { 257 var self = this; 258 var i18n = ContextMenu.I18N; 259 if (this.currentMenu) 260 this.currentMenu.parentNode.removeChild(this.currentMenu); 261 function getPos(el) { 262 var r = { x: el.offsetLeft, y: el.offsetTop }; 263 if (el.offsetParent) { 264 var tmp = getPos(el.offsetParent); 265 r.x += tmp.x; 266 r.y += tmp.y; 267 } 268 return r; 269 }; 270 function documentClick(ev) { 271 ev || (ev = window.event); 272 if (!self.currentMenu) { 273 alert(i18n["How did you get here? (Please report!)"]); 274 return false; 275 } 276 var el = HTMLArea.is_ie ? ev.srcElement : ev.target; 277 for (; el != null && el != self.currentMenu; el = el.parentNode); 278 if (el == null) 279 self.closeMenu(); 280 //HTMLArea._stopEvent(ev); 281 //return false; 282 }; 283 var keys = []; 284 function keyPress(ev) { 285 ev || (ev = window.event); 286 HTMLArea._stopEvent(ev); 287 if (ev.keyCode == 27) { 288 self.closeMenu(); 289 return false; 290 } 291 var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase(); 292 for (var i = keys.length; --i >= 0;) { 293 var k = keys[i]; 294 if (k[0].toLowerCase() == key) 295 k[1].__msh.activate(); 296 } 297 }; 298 self.closeMenu = function() { 299 self.currentMenu.parentNode.removeChild(self.currentMenu); 300 self.currentMenu = null; 301 HTMLArea._removeEvent(document, "mousedown", documentClick); 302 HTMLArea._removeEvent(self.editordoc, "mousedown", documentClick); 303 if (keys.length > 0) 304 HTMLArea._removeEvent(self.editordoc, "keypress", keyPress); 305 if (HTMLArea.is_ie) 306 self.iePopup.hide(); 307 }; 308 var target = HTMLArea.is_ie ? ev.srcElement : ev.target; 309 var ifpos = getPos(self.editor._iframe); 310 var x = ev.clientX + ifpos.x; 311 var y = ev.clientY + ifpos.y; 312 313 var div; 314 var doc; 315 if (!HTMLArea.is_ie) { 316 doc = document; 317 } else { 318 // IE stinks 319 var popup = this.iePopup = window.createPopup(); 320 doc = popup.document; 321 doc.open(); 322 doc.write("<html><head><style type='text/css'>@import url(" + _editor_url + "plugins/ContextMenu/menu.css); html, body { padding: 0px; margin: 0px; overflow: hidden; border: 0px; }</style></head><body unselectable='yes'></body></html>"); 323 doc.close(); 324 } 325 div = doc.createElement("div"); 326 if (HTMLArea.is_ie) 327 div.unselectable = "on"; 328 div.oncontextmenu = function() { return false; }; 329 div.className = "htmlarea-context-menu"; 330 if (!HTMLArea.is_ie) 331 div.style.left = div.style.top = "0px"; 332 doc.body.appendChild(div); 333 334 var table = doc.createElement("table"); 335 div.appendChild(table); 336 table.cellSpacing = 0; 337 table.cellPadding = 0; 338 var parent = doc.createElement("tbody"); 339 table.appendChild(parent); 340 341 var options = this.getContextMenu(target); 342 for (var i = 0; i < options.length; ++i) { 343 var option = options[i]; 344 var item = doc.createElement("tr"); 345 parent.appendChild(item); 346 if (HTMLArea.is_ie) 347 item.unselectable = "on"; 348 else item.onmousedown = function(ev) { 349 HTMLArea._stopEvent(ev); 350 return false; 351 }; 352 if (!option) { 353 item.className = "separator"; 354 var td = doc.createElement("td"); 355 td.className = "icon"; 356 var IE_IS_A_FUCKING_SHIT = '>'; 357 if (HTMLArea.is_ie) { 358 td.unselectable = "on"; 359 IE_IS_A_FUCKING_SHIT = " unselectable='on' style='height=1px'> "; 360 } 361 td.innerHTML = "<div" + IE_IS_A_FUCKING_SHIT + "</div>"; 362 var td1 = td.cloneNode(true); 363 td1.className = "label"; 364 item.appendChild(td); 365 item.appendChild(td1); 366 } else { 367 var label = option[0]; 368 item.className = "item"; 369 item.__msh = { 370 item: item, 371 label: label, 372 action: option[1], 373 tooltip: option[2] || null, 374 icon: option[3] || null, 375 activate: function() { 376 self.closeMenu(); 377 self.editor.focusEditor(); 378 this.action(); 379 } 380 }; 381 label = label.replace(/_([a-zA-Z0-9])/, "<u>$1</u>"); 382 if (label != option[0]) 383 keys.push([ RegExp.$1, item ]); 384 label = label.replace(/__/, "_"); 385 var td1 = doc.createElement("td"); 386 if (HTMLArea.is_ie) 387 td1.unselectable = "on"; 388 item.appendChild(td1); 389 td1.className = "icon"; 390 if (item.__msh.icon) 391 td1.innerHTML = "<img align='middle' src='" + item.__msh.icon + "' />"; 392 var td2 = doc.createElement("td"); 393 if (HTMLArea.is_ie) 394 td2.unselectable = "on"; 395 item.appendChild(td2); 396 td2.className = "label"; 397 td2.innerHTML = label; 398 item.onmouseover = function() { 399 this.className += " hover"; 400 self.editor._statusBarTree.innerHTML = this.__msh.tooltip || ' '; 401 }; 402 item.onmouseout = function() { this.className = "item"; }; 403 item.oncontextmenu = function(ev) { 404 this.__msh.activate(); 405 if (!HTMLArea.is_ie) 406 HTMLArea._stopEvent(ev); 407 return false; 408 }; 409 item.onmouseup = function(ev) { 410 var timeStamp = (new Date()).getTime(); 411 if (timeStamp - self.timeStamp > 500) 412 this.__msh.activate(); 413 if (!HTMLArea.is_ie) 414 HTMLArea._stopEvent(ev); 415 return false; 416 }; 417 //if (typeof option[2] == "string") 418 //item.title = option[2]; 419 } 420 } 421 422 if (!HTMLArea.is_ie) { 423 var dx = x + div.offsetWidth - window.innerWidth + 4; 424 var dy = y + div.offsetHeight - window.innerHeight + 4; 425 if (dx > 0) x -= dx; 426 if (dy > 0) y -= dy; 427 div.style.left = x + "px"; 428 div.style.top = y + "px"; 429 } else { 430 // determine the size (did I mention that IE stinks?) 431 var foobar = document.createElement("div"); 432 foobar.className = "htmlarea-context-menu"; 433 foobar.innerHTML = div.innerHTML; 434 document.body.appendChild(foobar); 435 var w = foobar.offsetWidth; 436 var h = foobar.offsetHeight; 437 document.body.removeChild(foobar); 438 this.iePopup.show(ev.screenX, ev.screenY, w, h); 439 } 440 441 this.currentMenu = div; 442 this.timeStamp = (new Date()).getTime(); 443 444 HTMLArea._addEvent(document, "mousedown", documentClick); 445 HTMLArea._addEvent(this.editordoc, "mousedown", documentClick); 446 if (keys.length > 0) 447 HTMLArea._addEvent(this.editordoc, "keypress", keyPress); 448 449 HTMLArea._stopEvent(ev); 450 return false; 451 };
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 18:01:28 2007 | par Balluche grâce à PHPXref 0.7 |