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