[ Index ] |
|
Code source de Kupu-1.3.5 |
1 /***************************************************************************** 2 * 3 * Copyright (c) 2003-2005 Kupu Contributors. All rights reserved. 4 * 5 * This software is distributed under the terms of the Kupu 6 * License. See LICENSE.txt for license text. For a list of Kupu 7 * Contributors see CREDITS.txt. 8 * 9 *****************************************************************************/ 10 11 // $Id: kupudrawers.js 15812 2005-08-09 12:30:34Z duncan $ 12 13 function DrawerTool() { 14 /* a tool to open and fill drawers 15 16 this tool has to (and should!) only be instantiated once 17 */ 18 this.drawers = {}; 19 this.current_drawer = null; 20 21 this.initialize = function(editor) { 22 this.editor = editor; 23 this.isIE = this.editor.getBrowserName() == 'IE'; 24 // this essentially makes the drawertool a singleton 25 window.drawertool = this; 26 }; 27 28 this.registerDrawer = function(id, drawer, editor) { 29 this.drawers[id] = drawer; 30 drawer.initialize(editor || this.editor, this); 31 }; 32 33 this.openDrawer = function(id) { 34 /* open a drawer */ 35 if (this.current_drawer) { 36 this.closeDrawer(); 37 }; 38 var drawer = this.drawers[id]; 39 if (this.isIE) { 40 drawer.editor._saveSelection(); 41 } 42 drawer.createContent(); 43 drawer.editor.suspendEditing(); 44 this.current_drawer = drawer; 45 }; 46 47 this.updateState = function(selNode) { 48 }; 49 50 this.closeDrawer = function(button) { 51 if (!this.current_drawer) { 52 return; 53 }; 54 this.current_drawer.hide(); 55 this.current_drawer.editor.resumeEditing(); 56 this.current_drawer = null; 57 }; 58 59 // this.getDrawerEnv = function(iframe_win) { 60 // var drawer = null; 61 // for (var id in this.drawers) { 62 // var ldrawer = this.drawers[id]; 63 // // Note that we require drawers to provide us with an 64 // // element property! 65 // if (ldrawer.element.contentWindow == iframe_win) { 66 // drawer = ldrawer; 67 // }; 68 // }; 69 // if (!drawer) { 70 // this.editor.logMessage("Drawer not found", 1); 71 // return; 72 // }; 73 // return { 74 // 'drawer': drawer, 75 // 'drawertool': this, 76 // 'tool': drawer.tool 77 // }; 78 // }; 79 }; 80 81 DrawerTool.prototype = new KupuTool; 82 83 function Drawer(elementid, tool) { 84 /* base prototype for drawers */ 85 86 this.element = getFromSelector(elementid); 87 this.tool = tool; 88 89 this.initialize = function(editor, drawertool) { 90 this.editor = editor; 91 this.drawertool = drawertool; 92 }; 93 94 this.createContent = function() { 95 /* fill the drawer with some content */ 96 // here's where any intelligence and XSLT transformation and such 97 // is done 98 this.element.style.display = 'block'; 99 this.focusElement(); 100 }; 101 102 this.hide = function() { 103 this.element.style.display = 'none'; 104 this.focussed = false; 105 }; 106 107 this.focusElement = function() { 108 // IE can focus the drawer element, but Mozilla needs more help 109 this.focussed = false; 110 var iterator = new NodeIterator(this.element); 111 var currnode = iterator.next(); 112 while (currnode) { 113 if (currnode.tagName && (currnode.tagName.toUpperCase()=='BUTTON' || 114 (currnode.tagName.toUpperCase()=='INPUT' && !(/nofocus/.test(currnode.className))) 115 )) { 116 this.focussed = true; 117 function focusit() { 118 currnode.focus(); 119 } 120 timer_instance.registerFunction(this, focusit, 100); 121 return; 122 } 123 currnode = iterator.next(); 124 } 125 } 126 }; 127 128 function LinkDrawer(elementid, tool, wrap) { 129 /* Link drawer */ 130 this.element = getFromSelector(elementid); 131 this.tool = tool; 132 function wrap(id, tag) { 133 return '#'+this.element.id+' '+tag+'.'+id; 134 } 135 var input = getBaseTagClass(this.element, 'input', 'kupu-linkdrawer-input'); 136 var preview = getBaseTagClass(this.element, 'iframe', 'kupu-linkdrawer-preview'); 137 138 this.createContent = function() { 139 /* display the drawer */ 140 var currnode = this.editor.getSelectedNode(); 141 var linkel = this.editor.getNearestParentOfType(currnode, 'a'); 142 input.value = ""; 143 this.preview(); 144 if (linkel) { 145 input.value = linkel.getAttribute('href'); 146 } else { 147 input.value = 'http://'; 148 }; 149 this.element.style.display = 'block'; 150 this.focusElement(); 151 }; 152 153 this.save = function() { 154 /* add or modify a link */ 155 this.editor.resumeEditing(); 156 var url = input.value; 157 var target = '_self'; 158 if (this.target) target = this.target; 159 this.tool.createLink(url, null, null, target); 160 input.value = ''; 161 162 // XXX when reediting a link, the drawer does not close for 163 // some weird reason. BUG! Close the drawer manually until we 164 // find a fix: 165 this.drawertool.closeDrawer(); 166 }; 167 168 this.preview = function() { 169 preview.src = input.value; 170 if (this.editor.getBrowserName() == 'IE') { 171 preview.width = "800"; 172 preview.height = "365"; 173 preview.style.zoom = "60%"; 174 }; 175 } 176 this.preview_loaded = function() { 177 if (input.value != preview.src) { 178 input.value = preview.src; 179 } 180 } 181 }; 182 183 LinkDrawer.prototype = new Drawer; 184 185 function TableDrawer(elementid, tool) { 186 /* Table drawer */ 187 this.element = getFromSelector(elementid); 188 this.tool = tool; 189 190 this.addpanel = getBaseTagClass(this.element, 'div', 'kupu-tabledrawer-addtable'); 191 this.editpanel = getBaseTagClass(this.element, 'div', 'kupu-tabledrawer-edittable'); 192 var editclassselect = getBaseTagClass(this.element, 'select', 'kupu-tabledrawer-editclasschooser'); 193 var addclassselect = getBaseTagClass(this.element, 'select', 'kupu-tabledrawer-addclasschooser'); 194 var alignselect = getBaseTagClass(this.element, 'select', 'kupu-tabledrawer-alignchooser'); 195 var newrowsinput = getBaseTagClass(this.element, 'input', 'kupu-tabledrawer-newrows'); 196 var newcolsinput = getBaseTagClass(this.element, 'input', 'kupu-tabledrawer-newcols'); 197 var makeheadercheck = getBaseTagClass(this.element, 'input', 'kupu-tabledrawer-makeheader'); 198 199 this.createContent = function() { 200 var editor = this.editor; 201 var selNode = editor.getSelectedNode(); 202 203 function fixClasses(classselect) { 204 if (editor.config.table_classes) { 205 var classes = editor.config.table_classes['class']; 206 while (classselect.hasChildNodes()) { 207 classselect.removeChild(classselect.firstChild); 208 }; 209 for (var i=0; i < classes.length; i++) { 210 var classinfo = classes[i]; 211 var caption = classinfo.xcaption || classinfo; 212 var classname = classinfo.classname || classinfo; 213 214 var option = document.createElement('option'); 215 var content = document.createTextNode(caption); 216 option.appendChild(content); 217 option.setAttribute('value', classname); 218 classselect.appendChild(option); 219 }; 220 }; 221 }; 222 fixClasses(addclassselect); 223 fixClasses(editclassselect); 224 225 var table = editor.getNearestParentOfType(selNode, 'table'); 226 227 if (!table) { 228 // show add table drawer 229 show = this.addpanel; 230 hide = this.editpanel; 231 } else { 232 // show edit table drawer 233 show = this.editpanel; 234 hide = this.addpanel; 235 var align = this.tool._getColumnAlign(selNode); 236 selectSelectItem(alignselect, align); 237 selectSelectItem(editclassselect, table.className); 238 }; 239 hide.style.display = 'none'; 240 show.style.display = 'block'; 241 this.element.style.display = 'block'; 242 this.focusElement(); 243 }; 244 245 this.createTable = function() { 246 this.editor.resumeEditing(); 247 var rows = newrowsinput.value; 248 var cols = newcolsinput.value; 249 var style = addclassselect.value; 250 var add_header = makeheadercheck.checked; 251 this.tool.createTable(parseInt(rows), parseInt(cols), add_header, style); 252 this.drawertool.closeDrawer(); 253 }; 254 this.delTableRow = function() { 255 this.editor.resumeEditing(); 256 this.tool.delTableRow(); 257 this.editor.suspendEditing(); 258 }; 259 this.addTableRow = function() { 260 this.editor.resumeEditing(); 261 this.tool.addTableRow(); 262 this.editor.suspendEditing(); 263 }; 264 this.delTableColumn = function() { 265 this.editor.resumeEditing(); 266 this.tool.delTableColumn(); 267 this.editor.suspendEditing(); 268 }; 269 this.addTableColumn = function() { 270 this.editor.resumeEditing(); 271 this.tool.addTableColumn(); 272 this.editor.suspendEditing(); 273 }; 274 this.fixTable = function() { 275 this.editor.resumeEditing(); 276 this.tool.fixTable(); 277 this.editor.suspendEditing(); 278 }; 279 this.fixAllTables = function() { 280 this.editor.resumeEditing(); 281 this.tool.fixAllTables(); 282 this.editor.suspendEditing(); 283 }; 284 this.setTableClass = function(className) { 285 this.editor.resumeEditing(); 286 this.tool.setTableClass(className); 287 this.editor.suspendEditing(); 288 }; 289 this.setColumnAlign = function(align) { 290 this.editor.resumeEditing(); 291 this.tool.setColumnAlign(align); 292 this.editor.suspendEditing(); 293 }; 294 }; 295 296 TableDrawer.prototype = new Drawer; 297 298 function LibraryDrawer(tool, xsluri, libsuri, searchuri, baseelement) { 299 /* a drawer that loads XSLT and XML from the server 300 and converts the XML to XHTML for the drawer using the XSLT 301 302 there are 2 types of XML file loaded from the server: the first 303 contains a list of 'libraries', partitions for the data items, 304 and the second a list of data items for a certain library 305 306 all XML loading is done async, since sync loading can freeze Mozilla 307 */ 308 309 this.init = function(tool, xsluri, libsuri, searchuri, baseelement) { 310 /* This method is there to thin out the constructor and to be 311 able to inherit it in sub-prototypes. Don't confuse this 312 method with the component initializer (initialize()). 313 */ 314 // these are used in the XSLT. Maybe they should be 315 // parameterized or something, but we depend on so many other 316 // things implicitly anyway... 317 this.drawerid = 'kupu-librarydrawer'; 318 this.librariespanelid = 'kupu-librariespanel'; 319 this.resourcespanelid = 'kupu-resourcespanel'; 320 this.propertiespanelid = 'kupu-propertiespanel'; 321 322 if (baseelement) { 323 this.baseelement = getFromSelector(baseelement); 324 } else { 325 this.baseelement = getBaseTagClass(document.body, 'div', 'kupu-librarydrawer-parent'); 326 } 327 328 this.tool = tool; 329 this.element = document.getElementById(this.drawerid); 330 if (!this.element) { 331 var e = document.createElement('div'); 332 e.id = this.drawerid; 333 e.className = 'kupu-drawer '+this.drawerid; 334 this.baseelement.appendChild(e); 335 this.element = e; 336 } 337 this.shared.xsluri = xsluri; 338 this.shared.libsuri = libsuri; 339 this.shared.searchuri = searchuri; 340 341 // marker that gets set when a new image has been uploaded 342 this.shared.newimages = null; 343 344 // the following vars will be available after this.initialize() 345 // has been called 346 347 // this will be filled by this._libXslCallback() 348 this.shared.xsl = null; 349 // this will be filled by this.loadLibraries(), which is called 350 // somewhere further down the chain starting with 351 // this._libsXslCallback() 352 this.shared.xmldata = null; 353 354 }; 355 if (tool) { 356 this.init(tool, xsluri, libsuri, searchuri); 357 } 358 359 this.initialize = function(editor, drawertool) { 360 this.editor = editor; 361 this.drawertool = drawertool; 362 this.selecteditemid = ''; 363 364 // load the xsl and the initial xml 365 var wrapped_callback = new ContextFixer(this._libsXslCallback, this); 366 this._loadXML(this.shared.xsluri, wrapped_callback.execute); 367 }; 368 369 /*** bootstrapping ***/ 370 371 this._libsXslCallback = function(dom) { 372 /* callback for when the xsl for the libs is loaded 373 374 this is called on init and since the initial libs need 375 to be loaded as well (and everything is async with callbacks 376 so there's no way to wait until the XSL is loaded) this 377 will also make the first loadLibraries call 378 */ 379 this.shared.xsl = dom; 380 381 // Change by Paul to have cached xslt transformers for reuse of 382 // multiple transforms and also xslt params 383 try { 384 var xsltproc = new XSLTProcessor(); 385 this.shared.xsltproc = xsltproc; 386 xsltproc.importStylesheet(dom); 387 xsltproc.setParameter("", "drawertype", this.drawertype); 388 xsltproc.setParameter("", "drawertitle", this.drawertitle); 389 xsltproc.setParameter("", "showupload", this.showupload); 390 if (this.editor.config.captions) { 391 xsltproc.setParameter("", "usecaptions", 'yes'); 392 } 393 } catch(e) { 394 return; // No XSLT Processor, maybe IE 5.5? 395 } 396 }; 397 398 this.createContent = function() { 399 // Make sure the drawer XML is in the current Kupu instance 400 if (this.element.parentNode != this.baseelement) { 401 this.baseelement.appendChild(this.element); 402 } 403 // load the initial XML 404 if(!this.shared.xmldata) { 405 // Do a meaningful test to see if this is IE5.5 or some other 406 // editor-enabled version whose XML support isn't good enough 407 // for the drawers 408 if (!window.XSLTProcessor) { 409 alert("This function requires better XML support in your browser."); 410 return; 411 } 412 this.loadLibraries(); 413 } else { 414 if (this.shared.newimages) { 415 this.reloadCurrent(); 416 this.shared.newimages = null; 417 }; 418 this.updateDisplay(); 419 this.initialSelection(); 420 }; 421 422 // display the drawer div 423 this.element.style.display = 'block'; 424 }; 425 426 this._singleLibsXslCallback = function(dom) { 427 /* callback for then the xsl for single libs (items) is loaded 428 429 nothing special needs to be called here, since initially the 430 items pane will be empty 431 */ 432 this.singlelibxsl = dom; 433 }; 434 435 this.loadLibraries = function() { 436 /* load the libraries and display them in a redrawn drawer */ 437 var wrapped_callback = new ContextFixer(this._libsContentCallback, this); 438 this._loadXML(this.shared.libsuri, wrapped_callback.execute); 439 }; 440 441 this._libsContentCallback = function(dom) { 442 /* this is called when the libs xml is loaded 443 444 does the xslt transformation to set up or renew the drawer's full 445 content and adds the content to the drawer 446 */ 447 this.shared.xmldata = dom; 448 this.shared.xmldata.setProperty("SelectionLanguage", "XPath"); 449 450 // replace whatever is in there with our stuff 451 this.updateDisplay(this.drawerid); 452 this.initialSelection(); 453 }; 454 455 this.initialSelection = function() { 456 var libnode_path = '/libraries/library[@selected]'; 457 var libnode = this.shared.xmldata.selectSingleNode(libnode_path); 458 if (libnode) { 459 var id = libnode.getAttribute('id'); 460 this.selectLibrary(id); 461 } 462 } 463 464 this.updateDisplay = function(id) { 465 /* (re-)transform XML and (re-)display the necessary part 466 */ 467 if(!id) { 468 id = this.drawerid; 469 }; 470 try { 471 this.shared.xsltproc.setParameter("", "showupload", this.showupload); 472 } catch(e) {}; 473 var doc = this._transformXml(); 474 var sourcenode = doc.selectSingleNode('//*[@id="'+id+'"]'); 475 var targetnode = document.getElementById(id); 476 sourcenode = document.importNode(sourcenode, true); 477 Sarissa.copyChildNodes(sourcenode, targetnode); 478 if (!this.focussed) { 479 this.focusElement(); 480 } 481 482 if (this.editor.getBrowserName() == 'IE' && id == this.resourcespanelid) { 483 this.updateDisplay(this.drawerid); 484 }; 485 }; 486 487 this.deselectActiveCollection = function() { 488 /* Deselect the currently active collection or library */ 489 while (1) { 490 // deselect selected DOM node 491 var selected = this.shared.xmldata.selectSingleNode('//*[@selected]'); 492 if (!selected) { 493 return; 494 }; 495 selected.removeAttribute('selected'); 496 }; 497 }; 498 499 /*** Load a library ***/ 500 501 this.selectLibrary = function(id) { 502 /* unselect the currently selected lib and select a new one 503 504 the selected lib (libraries pane) will have a specific CSS class 505 (selected) 506 */ 507 // remove selection in the DOM 508 this.deselectActiveCollection(); 509 // as well as visual selection in CSS 510 // XXX this is slow, but we can't do XPath, unfortunately 511 var divs = this.element.getElementsByTagName('div'); 512 for (var i=0; i<divs.length; i++ ) { 513 if (divs[i].className == 'kupu-libsource-selected') { 514 divs[i].className = 'kupu-libsource'; 515 }; 516 }; 517 518 var libnode_path = '/libraries/library[@id="' + id + '"]'; 519 var libnode = this.shared.xmldata.selectSingleNode(libnode_path); 520 libnode.setAttribute('selected', '1'); 521 522 var items_xpath = "items"; 523 var items_node = libnode.selectSingleNode(items_xpath); 524 525 if (items_node && !this.shared.newimages) { 526 // The library has already been loaded before or was 527 // already provided with an items list. No need to do 528 // anything except for displaying the contents in the 529 // middle pane. Newimages is set if we've lately 530 // added an image. 531 this.updateDisplay(this.resourcespanelid); 532 this.updateDisplay(this.propertiespanelid); 533 } else { 534 // We have to load the library from XML first. 535 var src_uri = libnode.selectSingleNode('src/text()').nodeValue; 536 src_uri = src_uri.strip(); // needs kupuhelpers.js 537 // Now load the library into the items pane. Since we have 538 // to load the XML, do this via a call back 539 var wrapped_callback = new ContextFixer(this._libraryContentCallback, this); 540 this._loadXML(src_uri, wrapped_callback.execute, null); 541 this.shared.newimages = null; 542 }; 543 // instead of running the full transformations again we get a 544 // reference to the element and set the classname... 545 var newseldiv = document.getElementById(id); 546 newseldiv.className = 'kupu-libsource-selected'; 547 }; 548 549 this._libraryContentCallback = function(dom, src_uri) { 550 /* callback for when a library's contents (item list) is loaded 551 552 This is also used as he handler for reloading a standard 553 collection. 554 */ 555 var libnode = this.shared.xmldata.selectSingleNode('//*[@selected]'); 556 var itemsnode = libnode.selectSingleNode("items"); 557 var newitemsnode = dom.selectSingleNode("//items"); 558 559 // IE does not support importNode on XML document nodes. As an 560 // evil hack, clonde the node instead. 561 562 if (this.editor.getBrowserName() == 'IE') { 563 newitemsnode = newitemsnode.cloneNode(true); 564 } else { 565 newitemsnode = this.shared.xmldata.importNode(newitemsnode, true); 566 } 567 if (!itemsnode) { 568 // We're loading this for the first time 569 libnode.appendChild(newitemsnode); 570 } else { 571 // User has clicked reload 572 libnode.replaceChild(newitemsnode, itemsnode); 573 }; 574 this.updateDisplay(this.resourcespanelid); 575 this.updateDisplay(this.propertiespanelid); 576 }; 577 578 /*** Load a collection ***/ 579 580 this.selectCollection = function(id) { 581 this.deselectActiveCollection(); 582 583 // First turn off current selection, if any 584 this.removeSelection(); 585 586 var leafnode_path = "//collection[@id='" + id + "']"; 587 var leafnode = this.shared.xmldata.selectSingleNode(leafnode_path); 588 589 // Case 1: We've already loaded the data, so we just need to 590 // refer to the data by id. 591 var loadedInNode = leafnode.getAttribute('loadedInNode'); 592 if (loadedInNode) { 593 var collnode_path = "/libraries/collection[@id='" + loadedInNode + "']"; 594 var collnode = this.shared.xmldata.selectSingleNode(collnode_path); 595 if (collnode) { 596 collnode.setAttribute('selected', '1'); 597 this.updateDisplay(this.resourcespanelid); 598 this.updateDisplay(this.propertiespanelid); 599 return; 600 }; 601 }; 602 603 // Case 2: We've already loaded the data, but there hasn't 604 // been a reference made yet. So, make one :) 605 uri = leafnode.selectSingleNode('uri/text()').nodeValue; 606 uri = (new String(uri)).strip(); // needs kupuhelpers.js 607 var collnode_path = "/libraries/collection/uri[text()='" + uri + "']/.."; 608 var collnode = this.shared.xmldata.selectSingleNode(collnode_path); 609 if (collnode) { 610 id = collnode.getAttribute('id'); 611 leafnode.setAttribute('loadedInNode', id); 612 collnode.setAttribute('selected', '1'); 613 this.updateDisplay(this.resourcespanelid); 614 this.updateDisplay(this.propertiespanelid); 615 return; 616 }; 617 618 // Case 3: We've not loaded the data yet, so we need to load it 619 // this is just so we can find the leafnode much easier in the 620 // callback. 621 leafnode.setAttribute('selected', '1'); 622 var src_uri = leafnode.selectSingleNode('src/text()').nodeValue; 623 src_uri = src_uri.strip(); // needs kupuhelpers.js 624 var wrapped_callback = new ContextFixer(this._collectionContentCallback, this); 625 this._loadXML(src_uri, wrapped_callback.execute, null); 626 }; 627 628 this._collectionContentCallback = function(dom, src_uri) { 629 // Unlike with libraries, we don't have to find a node to hook 630 // our results into (UNLESS we've hit the reload button, but 631 // that is handled in _libraryContentCallback anyway). 632 // We need to give the newly retrieved data a unique ID, we 633 // just use the time. 634 date = new Date(); 635 time = date.getTime(); 636 637 // attach 'loadedInNode' attribute to leaf node so Case 1 638 // applies next time. 639 var leafnode = this.shared.xmldata.selectSingleNode('//*[@selected]'); 640 leafnode.setAttribute('loadedInNode', time); 641 this.deselectActiveCollection() 642 643 var collnode = dom.selectSingleNode('/collection'); 644 collnode.setAttribute('id', time); 645 collnode.setAttribute('selected', '1'); 646 647 var libraries = this.shared.xmldata.selectSingleNode('/libraries'); 648 649 // IE does not support importNode on XML documet nodes 650 if (this.editor.getBrowserName() == 'IE') { 651 collnode = collnode.cloneNode(true); 652 } else { 653 collnode = this.shared.xmldata.importNode(collnode, true); 654 } 655 libraries.appendChild(collnode); 656 this.updateDisplay(this.resourcespanelid); 657 this.updateDisplay(this.propertiespanelid); 658 }; 659 660 /*** Reloading a collection or library ***/ 661 662 this.reloadCurrent = function() { 663 // Reload current collection or library 664 this.showupload = ''; 665 var current = this.shared.xmldata.selectSingleNode('//*[@selected]'); 666 // make sure we're dealing with a collection even though a 667 // resource might be selected 668 if (current.tagName == "resource") { 669 current.removeAttribute("selected"); 670 current = current.parentNode; 671 current.setAttribute("selected", "1"); 672 }; 673 var src_node = current.selectSingleNode('src'); 674 if (!src_node) { 675 // simply do nothing if the library cannot be reloaded. This 676 // is currently the case w/ search result libraries. 677 return; 678 }; 679 680 var src_uri = src_node.selectSingleNode('text()').nodeValue; 681 682 src_uri = src_uri.strip(); // needs kupuhelpers.js 683 684 var wrapped_callback = new ContextFixer(this._libraryContentCallback, this); 685 this._loadXML(src_uri, wrapped_callback.execute); 686 }; 687 688 this.removeSelection = function() { 689 // turn off current selection, if any 690 var oldselxpath = '/libraries/*[@selected]//resource[@selected]'; 691 var oldselitem = this.shared.xmldata.selectSingleNode(oldselxpath); 692 if (oldselitem) { 693 oldselitem.removeAttribute("selected"); 694 }; 695 if (this.selecteditemid) { 696 var item = document.getElementById(this.selecteditemid); 697 if (item) { 698 var span = item.getElementsByTagName('span'); 699 if (span.length > 0) { 700 span = span[0]; 701 span.className = span.className.replace(' selected-item', ''); 702 } 703 } 704 this.selecteditemid = ''; 705 } 706 this.showupload = ''; 707 } 708 709 this.selectUpload = function() { 710 this.removeSelection(); 711 this.showupload = 'yes'; 712 this.updateDisplay(this.resourcespanelid); 713 this.updateDisplay(this.propertiespanelid); 714 } 715 /*** Selecting a resource ***/ 716 717 this.selectItem = function (item, id) { 718 /* select an item in the item pane, show the item's metadata */ 719 720 // First turn off current selection, if any 721 this.removeSelection(); 722 723 // Grab XML DOM node for clicked "resource" and mark it selected 724 var newselxpath = '/libraries/*[@selected]//resource[@id="' + id + '"]'; 725 var newselitem = this.shared.xmldata.selectSingleNode(newselxpath); 726 newselitem.setAttribute("selected", "1"); 727 //this.updateDisplay(this.resourcespanelid); 728 this.updateDisplay(this.propertiespanelid); 729 730 // Don't want to reload the resource panel xml as it scrolls to 731 // the top. 732 var span = item.getElementsByTagName('span'); 733 if (span.length > 0) { 734 span = span[0]; 735 span.className += ' selected-item'; 736 } 737 this.selecteditemid = id; 738 if (this.editor.getBrowserName() == 'IE') { 739 var ppanel = document.getElementById(this.propertiespanelid) 740 var height = ppanel.clientHeight; 741 if (height > ppanel.scrollHeight) height = ppanel.scrollHeight; 742 if (height < 260) height = 260; 743 document.getElementById(this.resourcespanelid).style.height = height+'px'; 744 } 745 return; 746 } 747 748 749 this.search = function() { 750 /* search */ 751 var searchvalue = getFromSelector('kupu-searchbox-input').value; 752 //XXX make search variable configurable 753 var body = 'SearchableText=' + escape(searchvalue); 754 755 // the search uri might contain query parameters in HTTP GET 756 // style. We want to do a POST though, so find any possible 757 // parameters, trim them from the URI and append them to the 758 // POST body instead. 759 var chunks = this.shared.searchuri.split('?'); 760 var searchuri = chunks[0]; 761 if (chunks[1]) { 762 body += "&" + chunks[1]; 763 }; 764 var wrapped_callback = new ContextFixer(this._searchCallback, this); 765 this._loadXML(searchuri, wrapped_callback.execute, body); 766 }; 767 768 this._searchCallback = function(dom) { 769 var resultlib = dom.selectSingleNode("/library"); 770 771 var items = resultlib.selectNodes("items/*"); 772 if (!items.length) { 773 alert("No results found."); 774 return; 775 }; 776 777 // we need to give the newly retrieved data a unique ID, we 778 // just use the time. 779 date = new Date(); 780 time = date.getTime(); 781 resultlib.setAttribute("id", time); 782 783 // deselect the previous collection and mark the result 784 // library as selected 785 this.deselectActiveCollection(); 786 resultlib.setAttribute("selected", "1"); 787 788 // now hook the result library into our DOM 789 if (this.editor.getBrowserName() == 'IE') { 790 resultlib = resultlib.cloneNode(true); 791 } else { 792 this.shared.xmldata.importNode(resultlib, true); 793 } 794 var libraries = this.shared.xmldata.selectSingleNode("/libraries"); 795 libraries.appendChild(resultlib); 796 797 this.updateDisplay(this.drawerid); 798 var newseldiv = getFromSelector(time); 799 newseldiv.className = 'selected'; 800 }; 801 802 this.save = function() { 803 /* save the element, should be implemented on subclasses */ 804 throw "Not yet implemented"; 805 }; 806 807 /*** Auxiliary methods ***/ 808 809 this._transformXml = function() { 810 /* transform this.shared.xmldata to HTML using this.shared.xsl and return it */ 811 var doc = Sarissa.getDomDocument(); 812 var result = this.shared.xsltproc.transformToDocument(this.shared.xmldata); 813 return result; 814 }; 815 816 this._loadXML = function(uri, callback, body) { 817 /* load the XML from a uri 818 819 calls callback with one arg (the XML DOM) when done 820 the (optional) body arg should contain the body for the request 821 */ 822 var xmlhttp = new XMLHttpRequest(); 823 var method = 'GET'; 824 if (body) { 825 method = 'POST'; 826 } else { 827 // be sure that body is null and not an empty string or 828 // something 829 body = null; 830 }; 831 xmlhttp.open(method, uri, true); 832 // use ContextFixer to wrap the Sarissa callback, both for isolating 833 // the 'this' problem and to be able to pass in an extra argument 834 // (callback) 835 var wrapped_callback = new ContextFixer(this._sarissaCallback, xmlhttp, 836 callback, uri); 837 xmlhttp.onreadystatechange = wrapped_callback.execute; 838 if (method == "POST") { 839 // by default, we would send a 'text/xml' request, which 840 // is a dirty lie; explicitly set the content type to what 841 // a web server expects from a POST. 842 xmlhttp.setRequestHeader('content-type', 'application/x-www-form-urlencoded'); 843 }; 844 xmlhttp.send(body); 845 }; 846 847 this._sarissaCallback = function(user_callback, uri) { 848 /* callback for Sarissa 849 when the callback is called because the data's ready it 850 will get the responseXML DOM and call user_callback 851 with the DOM as the first argument and the uri loaded 852 as the second 853 854 note that this method should be called in the context of an 855 xmlhttp object 856 */ 857 var errmessage = 'Error loading XML: '; 858 if (uri) { 859 errmessage = 'Error loading ' + uri + ':'; 860 }; 861 if (this.readyState == 4) { 862 if (this.status && this.status != 200) { 863 alert(errmessage + this.status); 864 throw "Error loading XML"; 865 }; 866 var dom = this.responseXML; 867 user_callback(dom, uri); 868 }; 869 }; 870 }; 871 872 LibraryDrawer.prototype = new Drawer; 873 LibraryDrawer.prototype.shared = {}; // Shared data 874 875 function ImageLibraryDrawer(tool, xsluri, libsuri, searchuri, baseelement) { 876 /* a specific LibraryDrawer for images */ 877 878 this.drawertitle = "Insert Image"; 879 this.drawertype = "image"; 880 this.showupload = ''; 881 if (tool) { 882 this.init(tool, xsluri, libsuri, searchuri, baseelement); 883 } 884 885 886 // upload, on submit/insert press 887 this.uploadImage = function() { 888 var form = document.kupu_upload_form; 889 if (!form || form.node_prop_image.value=='') return; 890 891 if (form.node_prop_caption.value == "") { 892 alert("Please enter a title for the image you are uploading"); 893 return; 894 }; 895 896 var targeturi = this.shared.xmldata.selectSingleNode('/libraries/*[@selected]/uri/text()').nodeValue 897 document.kupu_upload_form.action = targeturi + "/kupuUploadImage"; 898 document.kupu_upload_form.submit(); 899 }; 900 901 // called for example when no permission to upload for some reason 902 this.cancelUpload = function(msg) { 903 var s = this.shared.xmldata.selectSingleNode('/libraries/*[@selected]'); 904 s.removeAttribute("selected"); 905 this.updateDisplay(); 906 if (msg != '') { 907 alert(msg); 908 }; 909 }; 910 911 // called by onLoad within document sent by server 912 this.finishUpload = function(url) { 913 this.editor.resumeEditing(); 914 var imgclass = 'image-inline'; 915 if (this.editor.config.captions) { 916 imgclass += " captioned"; 917 }; 918 this.tool.createImage(url, null, imgclass); 919 this.shared.newimages = 1; 920 this.drawertool.closeDrawer(); 921 }; 922 923 924 this.save = function() { 925 this.editor.resumeEditing(); 926 /* create an image in the iframe according to collected data 927 from the drawer */ 928 var selxpath = '//resource[@selected]'; 929 var selnode = this.shared.xmldata.selectSingleNode(selxpath); 930 931 // If no image resource is selected, check for upload 932 if (!selnode) { 933 var uploadbutton = this.shared.xmldata.selectSingleNode("/libraries/*[@selected]//uploadbutton"); 934 if (uploadbutton) { 935 this.uploadImage(); 936 }; 937 return; 938 }; 939 940 var uri = selnode.selectSingleNode('uri/text()').nodeValue; 941 uri = uri.strip(); // needs kupuhelpers.js 942 var alt = getFromSelector('image_alt').value; 943 944 var radios = document.getElementsByName('image-align'); 945 for (var i = 0; i < radios.length; i++) { 946 if (radios[i].checked) { 947 var imgclass = radios[i].value; 948 }; 949 }; 950 951 var caption = document.getElementsByName('image-caption'); 952 if (caption && caption.length>0 && caption[0].checked) { 953 imgclass += " captioned"; 954 }; 955 956 this.tool.createImage(uri, alt, imgclass); 957 this.drawertool.closeDrawer(); 958 }; 959 }; 960 961 ImageLibraryDrawer.prototype = new LibraryDrawer; 962 ImageLibraryDrawer.prototype.shared = {}; // Shared data 963 964 function LinkLibraryDrawer(tool, xsluri, libsuri, searchuri, baseelement) { 965 /* a specific LibraryDrawer for links */ 966 967 this.drawertitle = "Insert Link"; 968 this.drawertype = "link"; 969 this.showupload = ''; 970 if (tool) { 971 this.init(tool, xsluri, libsuri, searchuri, baseelement); 972 } 973 974 this.save = function() { 975 this.editor.resumeEditing(); 976 /* create a link in the iframe according to collected data 977 from the drawer */ 978 var selxpath = '//resource[@selected]'; 979 var selnode = this.shared.xmldata.selectSingleNode(selxpath); 980 if (!selnode) { 981 return; 982 }; 983 984 var uri = selnode.selectSingleNode('uri/text()').nodeValue; 985 uri = uri.strip(); // needs kupuhelpers.js 986 var title = ''; 987 title = selnode.selectSingleNode('title/text()').nodeValue; 988 title = title.strip(); 989 990 // XXX requiring the user to know what link type to enter is a 991 // little too much I think. (philiKON) 992 var type = null; 993 var name = getFromSelector('link_name').value; 994 var target = null; 995 if (getFromSelector('link_target') && getFromSelector('link_target').value != '') 996 target = getFromSelector('link_target').value; 997 998 this.tool.createLink(uri, type, name, target, title); 999 this.drawertool.closeDrawer(); 1000 }; 1001 }; 1002 1003 LinkLibraryDrawer.prototype = new LibraryDrawer; 1004 LinkLibraryDrawer.prototype.shared = {}; // Shared data 1005 1006 /* Function to suppress enter key in drawers */ 1007 function HandleDrawerEnter(event, clickid) { 1008 var key; 1009 event = event || window.event; 1010 key = event.which || event.keyCode; 1011 1012 if (key==13) { 1013 if (clickid) { 1014 var button = document.getElementById(clickid); 1015 if (button) { 1016 button.click(); 1017 } 1018 } 1019 event.cancelBubble = true; 1020 if (event.stopPropogation) event.stopPropogation(); 1021 1022 return false; 1023 } 1024 return true; 1025 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 15:30:41 2007 | par Balluche grâce à PHPXref 0.7 |