[ Index ] |
|
Code source de Plume CMS 1.2.2 |
1 function jsToolBar(textarea) { 2 if (!document.createElement) { return; } 3 4 if (!textarea) { return; } 5 6 if ((typeof(document["selection"]) == "undefined") 7 && (typeof(textarea["setSelectionRange"]) == "undefined")) { 8 return; 9 } 10 11 this.textarea = textarea; 12 13 this.editor = document.createElement('div'); 14 this.editor.className = 'jstEditor'; 15 16 this.textarea.parentNode.insertBefore(this.editor,this.textarea); 17 this.editor.appendChild(this.textarea); 18 19 this.toolbar = document.createElement("div"); 20 this.toolbar.className = 'jstElements'; 21 this.editor.parentNode.insertBefore(this.toolbar,this.editor); 22 23 // Dragable resizing (only for gecko) 24 if (this.editor.addEventListener) 25 { 26 this.handle = document.createElement('div'); 27 this.handle.className = 'jstHandle'; 28 var dragStart = this.resizeDragStart; 29 var This = this; 30 this.handle.addEventListener('mousedown',function(event) { dragStart.call(This,event); },false); 31 32 this.editor.parentNode.insertBefore(this.handle,this.editor.nextSibling); 33 } 34 35 this.context = null; 36 this.toolNodes = {}; // lorsque la toolbar est dessinée , cet objet est garni 37 // de raccourcis vers les éléments DOM correspondants aux outils. 38 } 39 40 function jsButton(title, fn, scope, className) { 41 this.title = title || null; 42 this.fn = fn || function(){}; 43 this.scope = scope || null; 44 this.className = className || null; 45 } 46 jsButton.prototype.draw = function() { 47 if (!this.scope) return null; 48 49 var button = document.createElement('button'); 50 button.setAttribute('type','button'); 51 if (this.className) button.className = this.className; 52 button.title = this.title; 53 var span = document.createElement('span'); 54 span.appendChild(document.createTextNode(this.title)); 55 button.appendChild(span); 56 57 if (this.icon != undefined) { 58 button.style.backgroundImage = 'url('+this.icon+')'; 59 } 60 if (typeof(this.fn) == 'function') { 61 var This = this; 62 button.onclick = function() { try { This.fn.apply(This.scope, arguments) } catch (e) {} return false; }; 63 } 64 return button; 65 } 66 67 function jsSpace(id) { 68 this.id = id || null; 69 this.width = null; 70 } 71 jsSpace.prototype.draw = function() { 72 var span = document.createElement('span'); 73 if (this.id) span.id = this.id; 74 span.appendChild(document.createTextNode(String.fromCharCode(160))); 75 span.className = 'jstSpacer'; 76 if (this.width) span.style.marginRight = this.width+'px'; 77 78 return span; 79 } 80 81 function jsCombo(title, options, scope, className) { 82 this.title = title || null; 83 this.options = options || null; 84 this.scope = scope || null; 85 this.className = className || null; 86 } 87 jsCombo.prototype.draw = function() { 88 if (!this.scope || !this.options) return null; 89 90 var select = document.createElement('select'); 91 if (this.className) select.className = className; 92 select.title = this.title; 93 94 for (var o in this.options) { 95 // aOption == {label: aLabel, fn: aFunction} 96 var opt = this.options[o]; 97 var option = document.createElement('option'); 98 option.value = o; 99 option.appendChild(document.createTextNode(opt.label)); 100 select.appendChild(option); 101 } 102 103 var This = this; 104 select.onchange = function() { 105 // pour l'instant on associe une fonction par option. 106 // l'autre solution est d'attacher une fonction globable auxquelle on passe 107 // un argument dépendant de l'option sélectionnée ( ce serait peut être plus 108 // léger en lignes de code...mais pas sûr..) 109 var option = This.options[this.value]; 110 if (typeof option.fn != 'function') return false; 111 try { 112 option.fn.apply(This.scope); 113 //option.fn.apply(This.scope, arguments); 114 } catch (e) { alert(e); } 115 116 return false; 117 } 118 119 return select; 120 } 121 122 123 jsToolBar.prototype = { 124 base_url: '', 125 mode: 'xhtml', 126 elements: {}, 127 128 getMode: function() { 129 return this.mode; 130 }, 131 132 setMode: function(mode) { 133 this.mode = mode || 'xhtml'; 134 }, 135 136 switchMode: function(mode) { 137 mode = mode || 'xhtml'; 138 this.draw(mode); 139 }, 140 141 button: function(toolName) { 142 var tool = this.elements[toolName]; 143 if (typeof tool.fn[this.mode] != 'function') return null; 144 var b = new jsButton(tool.title, tool.fn[this.mode], this, 'jstb_'+toolName); 145 if (tool.icon != undefined) b.icon = tool.icon; 146 return b; 147 }, 148 space: function(toolName) { 149 var tool = new jsSpace(toolName) 150 if (this.elements[toolName].width !== undefined) 151 tool.width = this.elements[toolName].width; 152 return tool; 153 }, 154 combo: function(toolName) { 155 var tool = this.elements[toolName]; 156 var options = {}; 157 var length = 0; 158 for (var o in tool.options) { 159 var opt = tool.options[o]; 160 if (typeof opt.fn[this.mode] != 'function') continue; 161 options[o] = {label: opt.label, fn: opt.fn[this.mode]}; 162 length++; 163 } 164 if (length == 0) return null; 165 166 return new jsCombo(tool.title, options, this); 167 }, 168 draw: function(mode) { 169 this.setMode(mode); 170 171 // Empty toolbar 172 while (this.toolbar.hasChildNodes()) { 173 this.toolbar.removeChild(this.toolbar.firstChild) 174 } 175 this.toolNodes = {}; // vide les raccourcis DOM/**/ 176 177 // Draw toolbar elements 178 var b, tool, newTool; 179 180 for (var i in this.elements) { 181 b = this.elements[i]; 182 183 var disabled = 184 b.type == undefined || b.type == '' 185 || (b.disabled != undefined && b.disabled) 186 || (b.context != undefined && b.context != null && b.context != this.context); 187 188 if (!disabled && typeof this[b.type] == 'function') { 189 tool = this[b.type](i); 190 if (tool) newTool = tool.draw(); 191 if (newTool) { 192 this.toolNodes[i] = newTool; //mémorise l'accès DOM pour usage éventuel ultérieur 193 this.toolbar.appendChild(newTool); 194 } 195 } 196 } 197 }, 198 199 singleTag: function(stag,etag) { 200 stag = stag || null; 201 etag = etag || stag; 202 203 if (!stag || !etag) { return; } 204 205 this.encloseSelection(stag,etag); 206 }, 207 208 encloseSelection: function(prefix, suffix, fn) { 209 this.textarea.focus(); 210 211 prefix = prefix || ''; 212 suffix = suffix || ''; 213 214 var start, end, sel, scrollPos, subst, res; 215 216 if (typeof(document["selection"]) != "undefined") { 217 sel = document.selection.createRange().text; 218 } else if (typeof(this.textarea["setSelectionRange"]) != "undefined") { 219 start = this.textarea.selectionStart; 220 end = this.textarea.selectionEnd; 221 scrollPos = this.textarea.scrollTop; 222 sel = this.textarea.value.substring(start, end); 223 } 224 225 if (sel.match(/ $/)) { // exclude ending space char, if any 226 sel = sel.substring(0, sel.length - 1); 227 suffix = suffix + " "; 228 } 229 230 if (typeof(fn) == 'function') { 231 res = (sel) ? fn.call(this,sel) : fn(''); 232 } else { 233 res = (sel) ? sel : ''; 234 } 235 236 subst = prefix + res + suffix; 237 238 if (typeof(document["selection"]) != "undefined") { 239 var range = document.selection.createRange().text = subst; 240 this.textarea.caretPos -= suffix.length; 241 } else if (typeof(this.textarea["setSelectionRange"]) != "undefined") { 242 this.textarea.value = this.textarea.value.substring(0, start) + subst + 243 this.textarea.value.substring(end); 244 if (sel) { 245 this.textarea.setSelectionRange(start + subst.length, start + subst.length); 246 } else { 247 this.textarea.setSelectionRange(start + prefix.length, start + prefix.length); 248 } 249 this.textarea.scrollTop = scrollPos; 250 } 251 }, 252 253 stripBaseURL: function(url) { 254 if (this.base_url != '') { 255 var pos = url.indexOf(this.base_url); 256 if (pos == 0) { 257 url = url.substr(this.base_url.length); 258 } 259 } 260 261 return url; 262 } 263 }; 264 265 /** Resizer 266 -------------------------------------------------------- */ 267 jsToolBar.prototype.resizeSetStartH = function() { 268 this.dragStartH = this.textarea.offsetHeight + 0; 269 }; 270 jsToolBar.prototype.resizeDragStart = function(event) { 271 var This = this; 272 this.dragStartY = event.clientY; 273 this.resizeSetStartH(); 274 document.addEventListener('mousemove', this.dragMoveHdlr=function(event){This.resizeDragMove(event);}, false); 275 document.addEventListener('mouseup', this.dragStopHdlr=function(event){This.resizeDragStop(event);}, false); 276 }; 277 278 jsToolBar.prototype.resizeDragMove = function(event) { 279 this.textarea.style.height = (this.dragStartH+event.clientY-this.dragStartY)+'px'; 280 }; 281 282 jsToolBar.prototype.resizeDragStop = function(event) { 283 document.removeEventListener('mousemove', this.dragMoveHdlr, false); 284 document.removeEventListener('mouseup', this.dragStopHdlr, false); 285 }; 286 287 // Elements definition ------------------------------------ 288 // block format (paragraph, headers) 289 jsToolBar.prototype.elements.blocks = { 290 type: 'combo', 291 title: 'block format', 292 options: { 293 none: { label: '-- none --', fn: {} }, // only for wysiwyg mode 294 nonebis: {label: '- block format -', fn: {} }, // only for xhtml mode 295 p: { label: 'Paragraph', fn: {} }, 296 h1: { label: 'Header 1', fn: {} }, 297 h2: { label: 'Header 2', fn: {} }, 298 h3: { label: 'Header 3', fn: {} }, 299 h4: { label: 'Header 4', fn: {} }, 300 h5: { label: 'Header 5', fn: {} }, 301 h6: { label: 'Header 6', fn: {} } 302 } 303 } 304 jsToolBar.prototype.elements.blocks.options.nonebis.fn.xhtml = function() { 305 this.textarea.focus(); 306 }; 307 jsToolBar.prototype.elements.blocks.options.p.fn.xhtml = function() { 308 this.singleTag('<p>','</p>'); 309 }; 310 jsToolBar.prototype.elements.blocks.options.h1.fn.xhtml = function() { 311 this.singleTag('<h1>','</h1>'); 312 }; 313 jsToolBar.prototype.elements.blocks.options.h2.fn.xhtml = function() { 314 this.singleTag('<h2>','</h2>'); 315 }; 316 jsToolBar.prototype.elements.blocks.options.h3.fn.xhtml = function() { 317 this.singleTag('<h3>','</h3>'); 318 }; 319 jsToolBar.prototype.elements.blocks.options.h4.fn.xhtml = function() { 320 this.singleTag('<h4>','</h4>'); 321 }; 322 jsToolBar.prototype.elements.blocks.options.h5.fn.xhtml = function() { 323 this.singleTag('<h5>','</h5>'); 324 }; 325 jsToolBar.prototype.elements.blocks.options.h1.fn.xhtml = function() { 326 this.singleTag('<h6>','</h6>'); 327 }; 328 329 jsToolBar.prototype.elements.blocks.options.nonebis.fn.wiki = function() { 330 this.textarea.focus(); 331 }; 332 jsToolBar.prototype.elements.blocks.options.h2.fn.wiki = function() { 333 this.encloseSelection('!!!'); 334 }; 335 jsToolBar.prototype.elements.blocks.options.h3.fn.wiki = function() { 336 this.encloseSelection('!!'); 337 }; 338 jsToolBar.prototype.elements.blocks.options.h4.fn.wiki = function() { 339 this.encloseSelection('!'); 340 }; 341 /* jsToolBar.prototype.elements.blocks.options.h5.fn.wiki = function() { 342 this.encloseSelection('!'); 343 }; */ 344 345 // spacer 346 jsToolBar.prototype.elements.space0 = {type: 'space'} 347 348 // strong 349 jsToolBar.prototype.elements.strong = { 350 type: 'button', 351 title: 'Strong emphasis', 352 fn: { 353 wiki: function() { this.singleTag('__') }, 354 xhtml: function() { this.singleTag('<strong>','</strong>') } 355 } 356 } 357 358 // em 359 jsToolBar.prototype.elements.em = { 360 type: 'button', 361 title: 'Emphasis', 362 fn: { 363 wiki: function() { this.singleTag("''") }, 364 xhtml: function() { this.singleTag('<em>','</em>') } 365 } 366 } 367 368 // ins 369 jsToolBar.prototype.elements.ins = { 370 type: 'button', 371 title: 'Inserted', 372 fn: { 373 // wiki: function() { this.singleTag('++') }, 374 xhtml: function() { this.singleTag('<ins>','</ins>') } 375 } 376 } 377 378 // del 379 jsToolBar.prototype.elements.del = { 380 type: 'button', 381 title: 'Deleted', 382 fn: { 383 // wiki: function() { this.singleTag('--') }, 384 xhtml: function() { this.singleTag('<del>','</del>') } 385 } 386 } 387 388 // quote 389 jsToolBar.prototype.elements.quote = { 390 type: 'button', 391 title: 'Inline quote', 392 fn: { 393 wiki: function() { this.singleTag('{{','}}') }, 394 xhtml: function() { this.singleTag('<q>','</q>') } 395 } 396 } 397 398 // code 399 jsToolBar.prototype.elements.code = { 400 type: 'button', 401 title: 'Code', 402 fn: { 403 wiki: function() { this.singleTag('@@') }, 404 xhtml: function() { this.singleTag('<code>','</code>')} 405 } 406 } 407 408 // spacer 409 jsToolBar.prototype.elements.space1 = {type: 'space'} 410 411 // br 412 jsToolBar.prototype.elements.br = { 413 type: 'button', 414 title: 'Line break', 415 fn: { 416 wiki: function() { this.encloseSelection("%%%\n",'') }, 417 xhtml: function() { this.encloseSelection("<br />\n",'')} 418 } 419 } 420 421 // spacer 422 jsToolBar.prototype.elements.space2 = {type: 'space'} 423 424 // blockquote 425 jsToolBar.prototype.elements.blockquote = { 426 type: 'button', 427 title: 'Blockquote', 428 fn: { 429 xhtml: function() { this.singleTag('<blockquote>','</blockquote>') }, 430 wiki: function() { 431 this.encloseSelection("\n",'', 432 function(str) { 433 str = str.replace(/\r/g,''); 434 return '> '+str.replace(/\n/g,"\n> "); 435 }); 436 } 437 } 438 } 439 440 // pre 441 jsToolBar.prototype.elements.pre = { 442 type: 'button', 443 title: 'Preformated text', 444 fn: { 445 wiki: function() { 446 this.encloseSelection("\n",'', 447 function(str) { 448 str = str.replace(/\r/g,''); 449 return ' '+str.replace(/\n/g,"\n "); 450 }); 451 }, //wiki: function() { this.singleTag("///\n","\n///") }, 452 xhtml: function() { this.singleTag('<pre>','</pre>') } 453 } 454 } 455 456 // ul 457 jsToolBar.prototype.elements.ul = { 458 type: 'button', 459 title: 'Unordered list', 460 fn: { 461 wiki: function() { 462 this.encloseSelection('','',function(str) { 463 str = str.replace(/\r/g,''); 464 return '* '+str.replace(/\n/g,"\n* "); 465 }); 466 }, 467 xhtml: function() { 468 this.encloseSelection('','',function(str) { 469 str = str.replace(/\r/g,''); 470 str = str.replace(/\n/g,"</li>\n <li>"); 471 return "<ul>\n <li>"+str+"</li>\n</ul>"; 472 }); 473 } 474 } 475 } 476 477 // ol 478 jsToolBar.prototype.elements.ol = { 479 type: 'button', 480 title: 'Ordered list', 481 fn: { 482 wiki: function() { 483 this.encloseSelection('','',function(str) { 484 str = str.replace(/\r/g,''); 485 return '# '+str.replace(/\n/g,"\n# "); 486 }); 487 }, 488 xhtml: function() { 489 this.encloseSelection('','',function(str) { 490 str = str.replace(/\r/g,''); 491 str = str.replace(/\n/g,"</li>\n <li>"); 492 return "<ol>\n <li>"+str+"</li>\n</ol>"; 493 }); 494 } 495 } 496 } 497 498 // spacer 499 jsToolBar.prototype.elements.space3 = {type: 'space'} 500 501 // link 502 jsToolBar.prototype.elements.link = { 503 type: 'button', 504 title: 'Link', 505 fn: {}, 506 href_prompt: 'Please give page URL:', 507 hreflang_prompt: 'Language of this page:', 508 default_hreflang: '', 509 prompt: function(href,hreflang) { 510 href = href || ''; 511 hreflang = hreflang || this.elements.link.default_hreflang; 512 513 href = window.prompt(this.elements.link.href_prompt,href); 514 if (!href) { return false; } 515 516 hreflang = window.prompt(this.elements.link.hreflang_prompt, 517 hreflang); 518 519 return { href: this.stripBaseURL(href), hreflang: hreflang }; 520 } 521 } 522 523 jsToolBar.prototype.elements.link.fn.xhtml = function() { 524 var link = this.elements.link.prompt.call(this); 525 if (link) { 526 var stag = '<a href="'+link.href+'"'; 527 if (link.hreflang) { stag = stag+' hreflang="'+link.hreflang+'"'; } 528 if (link.title) { stag = stag+' title="'+link.title+'"'; } 529 stag = stag+'>'; 530 var etag = '</a>'; 531 532 this.encloseSelection(stag,etag); 533 } 534 }; 535 jsToolBar.prototype.elements.link.fn.wiki = function() { 536 var link = this.elements.link.prompt.call(this); 537 if (link) { 538 var stag = '['; 539 var etag = '|'+link.href; 540 if (link.hreflang) { etag = etag+'|'+link.hreflang; } 541 etag = etag+']'; 542 543 this.encloseSelection(stag,etag); 544 } 545 }; 546 547 // img 548 jsToolBar.prototype.elements.img = { 549 type: 'button', 550 title: 'External image', 551 src_prompt: 'Please give image URL:', 552 fn: {}, 553 prompt: function(src) { 554 src = src || ''; 555 return this.stripBaseURL(window.prompt(this.elements.img.src_prompt,src)); 556 } 557 }; 558 jsToolBar.prototype.elements.img.fn.xhtml = function() { 559 var src = this.elements.img.prompt.call(this); 560 if (src) { 561 this.encloseSelection('','',function(str) { 562 if (str) { 563 return '<img src="'+src+'" alt="'+str+'" />'; 564 } else { 565 return '<img src="'+src+'" alt="" />'; 566 } 567 }); 568 } 569 }; 570 jsToolBar.prototype.elements.img.fn.wiki = function() { 571 var src = this.elements.img.prompt.call(this); 572 if (src) { 573 this.encloseSelection('','',function(str) { 574 if (str) { 575 return '(('+src+'|'+str+'))'; 576 } else { 577 return '(('+src+'))'; 578 } 579 }); 580 } 581 };
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Mon Nov 26 11:57:01 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |