[ Index ] |
|
Code source de Horde 3.1.3 |
1 /** 2 * Horde Tree Javascript Class 3 * 4 * Provides the javascript class to create dynamic trees. 5 * 6 * Copyright 2003-2006 Marko Djukic <marko@oblo.com> 7 * 8 * See the enclosed file COPYING for license information (GPL). If you did not 9 * receive this file, see http://www.fsf.org/copyleft/gpl.html. 10 * 11 * $Horde: horde/templates/javascript/tree.js,v 1.62.2.11 2006/01/01 21:29:15 jan Exp $ 12 * 13 * @author Marko Djukic <marko@oblo.com> 14 * @package Horde_Tree 15 * @since Horde 3.0 16 */ 17 function Horde_Tree(instanceName) 18 { 19 /* Set up this class instance for function calls from the page. */ 20 this._instanceName = instanceName; 21 22 /* Image variables. */ 23 this.imgDir = '<?php echo $GLOBALS['registry']->getImageDir('horde') . '/tree'; ?>'; 24 this.imgBlank = 'blank.png'; 25 this.imgFolder = 'folder.png'; 26 this.imgFolderOpen = 'folderopen.png'; 27 28 /* Variables that change based on text direction. */ 29 <?php if (empty($GLOBALS['nls']['rtl'][$GLOBALS['language']])): ?> 30 this.floatDir = 'float:left;'; 31 this.imgLine = 'line.png'; 32 this.imgJoin = 'join.png'; 33 this.imgJoinBottom = 'joinbottom.png'; 34 this.imgPlus = 'plus.png'; 35 this.imgPlusBottom = 'plusbottom.png'; 36 this.imgPlusOnly = 'plusonly.png'; 37 this.imgMinus = 'minus.png'; 38 this.imgMinusBottom = 'minusbottom.png'; 39 this.imgMinusOnly = 'minusonly.png'; 40 this.imgNullOnly = 'nullonly.png'; 41 this.imgLeaf = 'leaf.png'; 42 <?php else: ?> 43 this.floatDir = 'float:right;'; 44 this.imgLine = 'rev-line.png'; 45 this.imgJoin = 'rev-join.png'; 46 this.imgJoinBottom = 'rev-joinbottom.png'; 47 this.imgPlus = 'rev-plus.png'; 48 this.imgPlusBottom = 'rev-plusbottom.png'; 49 this.imgPlusOnly = 'rev-plusonly.png'; 50 this.imgMinus = 'rev-minus.png'; 51 this.imgMinusBottom = 'rev-minusbottom.png'; 52 this.imgMinusOnly = 'rev-minusonly.png'; 53 this.imgNullOnly = 'rev-nullonly.png'; 54 this.imgLeaf = 'rev-leaf.png'; 55 <?php endif; ?> 56 57 /* Tree building variables. */ 58 this.renderStatic = false; 59 this.target = ''; 60 this.header = new Array(); 61 this.rootNodes = new Array(); 62 this.nodes = new Array(); 63 this.node_pos = new Array(); 64 this.dropline = new Array(); 65 this.output = ''; 66 } 67 68 Horde_Tree.prototype.setImgDir = function(imgDir) 69 { 70 this.imgDir = imgDir; 71 } 72 73 Horde_Tree.prototype.renderTree = function(rootNodes, renderStatic) 74 { 75 this.rootNodes = rootNodes; 76 this.renderStatic = renderStatic; 77 this.nodes = eval('n_' + this._instanceName); 78 this.header = eval('h_' + this._instanceName); 79 this.options = eval('o_' + this._instanceName); 80 this.target = 't_' + this._instanceName; 81 this._renderTree(); 82 } 83 84 Horde_Tree.prototype._renderTree = function() 85 { 86 this.output = ''; 87 if (!this.options['hideHeaders']) { 88 this.output = this._buildHeader(); 89 } 90 for (var i = 0; i < this.rootNodes.length; i++) { 91 this.buildTree(this.rootNodes[i]); 92 } 93 document.getElementById(this.target).innerHTML = this.output; 94 this._correctWidthForScrollbar(); 95 // If using alternating row shading, work out correct shade. 96 if (this.options['alternate']) { 97 this.stripe(); 98 } 99 } 100 101 /** 102 * Returns the HTML code for a header row, if necessary. 103 * 104 * @access private 105 * 106 * @return string The HTML code of the header row or an empty string. 107 */ 108 Horde_Tree.prototype._buildHeader = function() 109 { 110 if (!this.header.length) { 111 return ''; 112 } 113 114 var html = '<div>'; 115 for (var i = 0; i < this.header.length; i++) { 116 html += '<div'; 117 if (this.header[i]['class']) { 118 html += ' class="' + this.header[i]['class'] + '"'; 119 } 120 121 var style = this.floatDir; 122 if (this.header[i]['width']) { 123 style += 'width:' + this.header[i]['width'] + ';'; 124 } 125 if (this.header[i]['align']) { 126 style += 'text-align:' + this.header[i]['align'] + ';'; 127 } 128 129 html += ' style="' + style + '"'; 130 html += '>'; 131 html += this.header[i]['html'] ? this.header[i]['html'] : ' '; 132 html += '</div>'; 133 } 134 135 return html + '</div>'; 136 } 137 138 /** 139 * Recursive function to walk through the tree array and build 140 * the output. 141 */ 142 Horde_Tree.prototype.buildTree = function(nodeId) 143 { 144 this.output += this.buildLine(nodeId); 145 146 if (typeof(this.nodes[nodeId]['children']) != 'undefined') { 147 var numSubnodes = this.nodes[nodeId]['children'].length; 148 if (numSubnodes > 0) { 149 if (this.nodes[nodeId]['expanded']) { 150 rowStyle = 'display:block;'; 151 } else { 152 rowStyle = 'display:none;'; 153 } 154 this.output += '<div id="nodeChildren_' + nodeId + '" style="' + rowStyle + '">'; 155 156 for (var c = 0; c < numSubnodes; c++) { 157 var childNodeId = this.nodes[nodeId]['children'][c]; 158 this.node_pos[childNodeId] = new Array(); 159 this.node_pos[childNodeId]['pos'] = c + 1; 160 this.node_pos[childNodeId]['count'] = numSubnodes; 161 this.buildTree(childNodeId); 162 } 163 164 this.output += '</div>'; 165 } 166 } 167 168 return true; 169 } 170 171 Horde_Tree.prototype.buildLine = function(nodeId) 172 { 173 var style = ''; 174 var rowClass = 'treeRow'; 175 if (this.nodes[nodeId]['class']) { 176 rowClass += ' ' + this.nodes[nodeId]['class']; 177 } 178 179 var line = '<div class="' + rowClass + '">'; 180 181 // If we have headers, track which logical "column" we're in for 182 // any given cell of content. 183 var column = 0; 184 185 if (typeof(this.nodes[nodeId]['extra']) != 'undefined' && 186 typeof(this.nodes[nodeId]['extra'][0]) != 'undefined') { 187 var extra = this.nodes[nodeId]['extra'][0]; 188 for (var c = 0; c < extra.length; c++) { 189 style = this.floatDir; 190 if (this.header[column] && this.header[column]['width']) { 191 style += 'width:' + this.header[column]['width'] + ';'; 192 } 193 line += '<div style="' + style + '">' + extra[c] + '</div>'; 194 column++; 195 } 196 for (var d = c; d < extraColsLeft; d++) { 197 style = this.floatDir; 198 if (this.header[column] && this.header[column]['width']) { 199 style += 'width:' + this.header[column]['width'] + ';'; 200 } 201 line += '<div style="' + style + '"> </div>'; 202 column++; 203 } 204 } else { 205 for (var c = 0; c < extraColsLeft; c++) { 206 style = this.floatDir; 207 if (this.header[column] && this.header[column]['width']) { 208 style += 'width:' + this.header[column]['width'] + ';'; 209 } 210 line += '<div style="' + style + '"> </div>'; 211 column++; 212 } 213 } 214 215 style = this.floatDir; 216 if (this.header[column] && this.header[column]['width']) { 217 style += 'width:' + this.header[column]['width'] + ';'; 218 } 219 line += '<div style="' + style + '">'; 220 221 if (this.options['multiline']) { 222 line += '<table cellspacing="0"><tr><td>'; 223 } 224 225 for (var i = this.renderStatic ? 1 : 0; i < this.nodes[nodeId]['indent']; i++) { 226 if (this.dropline[i] && this.options['lines']) { 227 line += '<img src="' + this.imgDir + '/' + this.imgLine + '" alt="| " height="20" width="20" />'; 228 } else { 229 line += '<img src="' + this.imgDir + '/' + this.imgBlank + '" alt=" " height="20" width="20" />'; 230 } 231 } 232 line += this._setNodeToggle(nodeId); 233 if (this.options['multiline']) { 234 line += '</td><td>'; 235 } 236 line += this._setLabel(nodeId); 237 238 if (this.options['multiline']) { 239 line += '</td></tr></table>'; 240 } 241 242 line += '</div>'; 243 column++; 244 245 if (typeof(this.nodes[nodeId]['extra']) != 'undefined' && 246 typeof(this.nodes[nodeId]['extra'][1]) != 'undefined') { 247 var extra = this.nodes[nodeId]['extra'][1]; 248 for (var c = 0; c < extra.length; c++) { 249 style = this.floatDir; 250 if (this.header[column] && this.header[column]['width']) { 251 style += 'width:' + this.header[column]['width'] + ';'; 252 } 253 line += '<div style="' + style + '">' + extra[c] + '</div>'; 254 column++; 255 } 256 for (var d = c; d < extraColsRight; d++) { 257 style = this.floatDir; 258 if (this.header[column] && this.header[column]['width']) { 259 style += 'width:' + this.header[column]['width'] + ';'; 260 } 261 line += '<div style="' + style + '"> </div>'; 262 column++; 263 } 264 } else { 265 for (var c = 0; c < extraColsRight; c++) { 266 style = this.floatDir; 267 if (this.header[column] && this.header[column]['width']) { 268 style += 'width:' + this.header[column]['width'] + ';'; 269 } 270 line += '<div style="' + style + '"> </div>'; 271 column++; 272 } 273 } 274 line += '</div>'; 275 276 return line; 277 } 278 279 Horde_Tree.prototype._setLabel = function(nodeId) 280 { 281 label = this.nodes[nodeId]['label']; 282 283 if (this.nodes[nodeId]['url']) { 284 var urlClass = ''; 285 if (this.nodes[nodeId]['urlclass']) { 286 urlClass = ' class="' + this.nodes[nodeId]['urlclass'] + '"'; 287 } else if (this.options['urlclass']) { 288 urlClass = ' class="' + this.options['urlclass'] + '"'; 289 } 290 291 var target = ''; 292 if (this.nodes[nodeId]['target']) { 293 target = ' target="' + this.nodes[nodeId]['target'] + '"'; 294 } else if (this.options['target']) { 295 target = ' target="' + this.options['target'] + '"'; 296 } 297 298 var onclick = ''; 299 if (this.nodes[nodeId]['onclick']) { 300 onclick = ' onclick="' + this.nodes[nodeId]['onclick'] + '"'; 301 } 302 303 return '<a' + urlClass + ' href="' + this.nodes[nodeId]['url'] + '"' + target + onclick + '>' + this._setNodeIcon(nodeId) + label + '</a>'; 304 } else { 305 return '<span class="toggle" onclick="' + this._instanceName + '.toggle(\'' + nodeId + '\')">' + this._setNodeIcon(nodeId) + label + '</span>'; 306 } 307 } 308 309 Horde_Tree.prototype._setNodeToggle = function(nodeId) 310 { 311 var attrib = ''; 312 if (this.nodes[nodeId]['indent'] == '0' && 313 typeof(this.nodes[nodeId]['children']) != 'undefined') { 314 // Top level with children. 315 this.dropline[0] = false; 316 if (this.renderStatic) { 317 return ''; 318 } else { 319 attrib = ' style="cursor:pointer" onclick="' + this._instanceName + '.toggle(\'' + nodeId + '\')"'; 320 } 321 } else if (this.nodes[nodeId]['indent'] != '0' && 322 typeof(this.nodes[nodeId]['children']) == 'undefined') { 323 // Node no children. 324 if (this.node_pos[nodeId]['pos'] < this.node_pos[nodeId]['count']) { 325 // Not last node. 326 this.dropline[this.nodes[nodeId]['indent']] = true; 327 } else { 328 this.dropline[this.nodes[nodeId]['indent']] = false; 329 } 330 } else if (typeof(this.nodes[nodeId]['children']) != 'undefined') { 331 // Node with children. 332 if (this.node_pos[nodeId]['pos'] < this.node_pos[nodeId]['count']) { 333 // Not last node. 334 this.dropline[this.nodes[nodeId]['indent']] = true; 335 } else { 336 // Last node. 337 this.dropline[this.nodes[nodeId]['indent']] = false; 338 } 339 if (!this.renderStatic) { 340 attrib = ' style="cursor:pointer" onclick="' + this._instanceName + '.toggle(\'' + nodeId + '\')"'; 341 } 342 } else { 343 // Top level node with no children. 344 if (this.renderStatic) { 345 return ''; 346 } 347 this.dropline[0] = false; 348 } 349 350 nodeToggle = this._getNodeToggle(nodeId); 351 img = '<img id="nodeToggle_' + nodeId + '" src="' + this.imgDir + '/' + nodeToggle[0] + '" '; 352 if (nodeToggle[1]) { 353 img += 'alt="' + nodeToggle[1] + '" '; 354 } 355 img += attrib + ' height="20" width="20" />'; 356 return img; 357 } 358 359 Horde_Tree.prototype._getNodeToggle = function(nodeId) 360 { 361 var nodeToggle = new Array('', ''); 362 if (this.nodes[nodeId]['indent'] == '0' && 363 typeof(this.nodes[nodeId]['children']) != 'undefined') { 364 // Top level with children. 365 if (this.renderStatic) { 366 return nodeToggle; 367 } else if (!this.options['lines']) { 368 nodeToggle[0] = this.imgBlank; 369 nodeToggle[1] = ' ' 370 } else if (this.nodes[nodeId]['expanded']) { 371 nodeToggle[0] = this.imgMinusOnly; 372 nodeToggle[1] = '-'; 373 } else { 374 nodeToggle[0] = this.imgPlusOnly; 375 nodeToggle[1] = '+'; 376 } 377 } else if (this.nodes[nodeId]['indent'] != '0' && 378 typeof(this.nodes[nodeId]['children']) == 'undefined') { 379 // Node no children. 380 if (this.node_pos[nodeId]['pos'] < this.node_pos[nodeId]['count']) { 381 // Not last node. 382 if (this.options['lines']) { 383 nodeToggle[0] = this.imgJoin; 384 nodeToggle[1] = '|-'; 385 } else { 386 nodeToggle[0] = this.imgBlank; 387 nodeToggle[1] = ' '; 388 } 389 } else { 390 // Last node. 391 if (this.options['lines']) { 392 nodeToggle[0] = this.imgJoinBottom; 393 nodeToggle[1] = '`-'; 394 } else { 395 nodeToggle[0] = this.imgBlank; 396 nodeToggle[1] = ' '; 397 } 398 } 399 } else if (typeof(this.nodes[nodeId]['children']) != 'undefined') { 400 // Node with children. 401 if (this.node_pos[nodeId]['pos'] < this.node_pos[nodeId]['count']) { 402 // Not last node. 403 if (!this.options['lines']) { 404 nodeToggle[0] = this.imgBlank; 405 nodeToggle[1] = ' '; 406 } else if (this.renderStatic) { 407 nodeToggle[0] = this.imgJoin; 408 nodeToggle[1] = '|-'; 409 } else if (this.nodes[nodeId]['expanded']) { 410 nodeToggle[0] = this.imgMinus; 411 nodeToggle[1] = '-'; 412 } else { 413 nodeToggle[0] = this.imgPlus; 414 nodeToggle[1] = '+'; 415 } 416 } else { 417 // Last node. 418 if (!this.options['lines']) { 419 nodeToggle[0] = this.imgBlank; 420 nodeToggle[1] = ' '; 421 } else if (this.renderStatic) { 422 nodeToggle[0] = this.imgJoinBottom; 423 nodeToggle[1] = '`-'; 424 } else if (this.nodes[nodeId]['expanded']) { 425 nodeToggle[0] = this.imgMinusBottom; 426 nodeToggle[1] = '-'; 427 } else { 428 nodeToggle[0] = this.imgPlusBottom; 429 nodeToggle[1] = '+'; 430 } 431 } 432 } else { 433 // Top level node with no children. 434 if (this.renderStatic) { 435 return nodeToggle; 436 } 437 if (this.options['lines']) { 438 nodeToggle[0] = this.imgNullOnly; 439 nodeToggle[1] = ' '; 440 } else { 441 nodeToggle[0] = this.imgBlank; 442 nodeToggle[1] = ' '; 443 } 444 } 445 446 return nodeToggle; 447 } 448 449 Horde_Tree.prototype._setNodeIcon = function(nodeId) 450 { 451 var imgDir = (typeof(this.nodes[nodeId]['icondir']) != 'undefined') ? 452 this.nodes[nodeId]['icondir'] : 453 this.imgDir; 454 if (imgDir) { 455 imgDir += '/'; 456 } 457 458 if (typeof(this.nodes[nodeId]['icon']) != 'undefined') { 459 // Node has a user defined icon. 460 if (!this.nodes[nodeId]['icon']) { 461 return ''; 462 } 463 if (typeof(this.nodes[nodeId]['iconopen']) != 'undefined' && this.nodes[nodeId]['expanded']) { 464 img = this.nodes[nodeId]['iconopen']; 465 } else { 466 img = this.nodes[nodeId]['icon']; 467 } 468 } else { 469 // Use standard icon set. 470 if (typeof(this.nodes[nodeId]['children']) != 'undefined') { 471 // Node with children. 472 img = (this.nodes[nodeId]['expanded']) ? this.imgFolderOpen 473 : this.imgFolder; 474 } else { 475 // Node no children. 476 img = this.imgLeaf; 477 } 478 } 479 480 var imgtxt = '<img src="' + imgDir + img + '"'; 481 482 if (typeof(this.nodes[nodeId]['iconalt']) != 'undefined') { 483 imgtxt += ' alt="' + this.nodes[nodeId]['iconalt'] + '"'; 484 } 485 486 return imgtxt + ' /> '; 487 } 488 489 Horde_Tree.prototype.toggle = function(nodeId) 490 { 491 this.nodes[nodeId]['expanded'] = !this.nodes[nodeId]['expanded']; 492 if (this.nodes[nodeId]['expanded']) { 493 if (node = document.getElementById('nodeChildren_' + nodeId)) { 494 node.style.display = 'block'; 495 } 496 } else { 497 if (node = document.getElementById('nodeChildren_' + nodeId)) { 498 node.style.display = 'none'; 499 } 500 } 501 502 // If using alternating row shading, work out correct shade. 503 if (this.options['alternate']) { 504 this.stripe(); 505 } 506 507 nodeToggle = this._getNodeToggle(nodeId); 508 if (toggle = document.getElementById('nodeToggle_' + nodeId)) { 509 toggle.src = this.imgDir + '/' + nodeToggle[0]; 510 toggle.alt = nodeToggle[1]; 511 } 512 513 this.saveState(nodeId, this.nodes[nodeId]['expanded']) 514 } 515 516 Horde_Tree.prototype.stripe = function() 517 { 518 // The element to start striping. 519 var id = arguments[0] ? arguments[0] : this.target; 520 521 // The flag we'll use to keep track of whether the current row is 522 // odd or even. 523 var even = arguments[1] ? arguments[1] : false; 524 525 // Obtain a reference to the tree parent element. 526 var tree = document.getElementById(id); 527 if (!tree) { 528 return even; 529 } 530 531 // Iterate over each child div. 532 for (var i = 0; i < tree.childNodes.length; i++) { 533 if (tree.childNodes[i].id.indexOf('nodeChildren') != -1) { 534 if (this.nodes[tree.childNodes[i].id.replace('nodeChildren_', '')]['expanded']) { 535 even = this.stripe(tree.childNodes[i].id, even); 536 } 537 } else { 538 tree.childNodes[i].className = tree.childNodes[i].className.replace(' rowEven', '').replace(' rowOdd', ''); 539 tree.childNodes[i].className += even ? ' rowEven' : ' rowOdd'; 540 541 // Flip from odd to even, or vice-versa. 542 even = !even; 543 } 544 } 545 546 return even; 547 } 548 549 Horde_Tree.prototype.saveState = function(nodeId, expanded) 550 { 551 var newCookie = ''; 552 var oldCookie = this._getCookie(this._instanceName + '_expanded'); 553 if (expanded) { 554 // Expand requested so add to cookie. 555 newCookie = (oldCookie) ? oldCookie + ',' : ''; 556 newCookie = newCookie + nodeId; 557 } else { 558 // Collapse requested so remove from cookie. 559 var nodes = oldCookie.split(','); 560 var newNodes = new Array(); 561 for (var i = 0; i < nodes.length; i++) { 562 if (nodes[i] != nodeId) { 563 newNodes[newNodes.length] = nodes[i]; 564 } 565 } 566 newCookie = newNodes.join(','); 567 } 568 this._setCookie(this._instanceName + '_expanded', newCookie); 569 } 570 571 Horde_Tree.prototype._getCookie = function(name) 572 { 573 var dc = document.cookie; 574 var prefix = name + '=exp'; 575 var begin = dc.indexOf('; ' + prefix); 576 if (begin == -1) { 577 begin = dc.indexOf(prefix); 578 if (begin != 0) { 579 return ''; 580 } 581 } else { 582 begin += 2; 583 } 584 var end = document.cookie.indexOf(';', begin); 585 if (end == -1) { 586 end = dc.length; 587 } 588 return unescape(dc.substring(begin + prefix.length, end)); 589 } 590 591 Horde_Tree.prototype._setCookie = function(name, value) 592 { 593 var curCookie = name + '=exp' + escape(value); 594 curCookie += ';DOMAIN=<?php echo $GLOBALS['conf']['cookie']['domain']; ?>;PATH=<?php echo $GLOBALS['conf']['cookie']['path']; ?>;'; 595 document.cookie = curCookie; 596 } 597 598 Horde_Tree.prototype._correctWidthForScrollbar = function() 599 { 600 <?php if ($GLOBALS['browser']->hasQuirk('scrollbar_in_way')): ?> 601 // Correct for frame scrollbar in IE by determining if a scrollbar is present, 602 // and if not readjusting the marginRight property to 0 603 // See http://www.xs4all.nl/~ppk/js/doctypes.html for why this works 604 if (document.documentElement.clientHeight == document.documentElement.offsetHeight) { 605 // no scrollbar present, take away extra margin 606 document.body.style.marginRight = '0'; 607 } else { 608 document.body.style.marginRight = '15px'; 609 } 610 <?php endif; ?> 611 }
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 |