PHP Classes

File: TreeMenu.js

Recommend this page to a friend!
  Classes of Richard Heyes   HTML_TreeMenu   TreeMenu.js   Download  
File: TreeMenu.js
Role: ???
Content type: text/plain
Description: The necessary javascript
Class: HTML_TreeMenu
Easy aPI to produce a dynamic tree menu
Author: By
Last change:
Date: 22 years ago
Size: 11,416 bytes
 

Contents

Class file image Download
// +----------------------------------------------------------------------+ // | PHP Version 4 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997-2002 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.02 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Author: Richard Heyes <richard@phpguru.org> | // | Harald Radi <harald.radi@nme.at> | // +----------------------------------------------------------------------+ // // $Id: TreeMenu.js,v 1.2 2002/06/18 23:28:35 richard Exp $ function TreeMenu(layer, iconpath, myname, linkTarget) { // Properties this.layer = layer; this.iconpath = iconpath; this.myname = myname; this.linkTarget = linkTarget; this.n = new Array(); this.branches = new Array(); this.branchStatus = new Array(); this.layerRelations = new Array(); this.childParents = new Array(); // Methods //this.preloadImages = preloadImages; this.drawMenu = drawMenu; this.toggleBranch = toggleBranch; this.swapImage = swapImage; this.doesMenu = doesMenu; this.doesPersistence = doesPersistence; this.getLayer = getLayer; this.saveExpandedStatus = saveExpandedStatus; this.loadExpandedStatus = loadExpandedStatus; this.resetBranches = resetBranches; } function TreeNode(title, icon, link, expanded) { this.title = title; this.icon = icon; this.link = link; this.expanded = expanded; this.n = new Array(); } /** * Preload images hack for CrapZilla */ function preloadImages() { var plustop = new Image; plustop.src = this.iconpath + '/plustop.gif'; var plusbottom = new Image; plusbottom.src = this.iconpath + '/plusbottom.gif'; var plus = new Image; plus.src = this.iconpath + '/plus.gif'; var minustop = new Image; minustop.src = this.iconpath + '/minustop.gif'; var minusbottom = new Image; minusbottom.src = this.iconpath + '/minusbottom.gif'; var minus = new Image; minus.src = this.iconpath + '/minus.gif'; } /** * Main function that draws the menu and assigns it * to the layer (or document.write()s it) */ function drawMenu()// OPTIONAL ARGS: nodes = [], level = [], prepend = '', expanded = false, visbility = 'inline', parentLayerID = null { /** * Necessary variables */ var output = ''; var modifier = ''; var layerID = ''; var parentLayerID = ''; /** * Parse any optional arguments */ var nodes = arguments[0] ? arguments[0] : this.n var level = arguments[1] ? arguments[1] : []; var prepend = arguments[2] ? arguments[2] : ''; var expanded = arguments[3] ? arguments[3] : false; var visibility = arguments[4] ? arguments[4] : 'inline'; var parentLayerID = arguments[5] ? arguments[5] : null; var currentlevel = level.length; for (var i=0; i<nodes.length; i++) { level[currentlevel] = i+1; layerID = this.layer + '_' + 'node_' + implode('_', level); /** * Store the child/parent relationship */ this.childParents[layerID] = parentLayerID; /** * Gif modifier */ if (i == 0 && parentLayerID == null) { modifier = nodes.length > 1 ? "top" : 'single'; } else if(i == (nodes.length-1)) { modifier = "bottom"; } else { modifier = ""; } /** * Single root branch is always expanded */ if (!doesMenu() || (parentLayerID == null && nodes.length == 1)) { expanded = true; } /** * Setup branch status and build an indexed array * of branch layer ids */ if (nodes[i].n.length > 1) { this.branchStatus[layerID] = expanded; this.branches[this.branches.length] = layerID; } /** * Setup toggle relationship */ if (!this.layerRelations[parentLayerID]) { this.layerRelations[parentLayerID] = new Array(); } this.layerRelations[parentLayerID][this.layerRelations[parentLayerID].length] = layerID; /** * Branch images */ var gifname = nodes[i].n.length && this.doesMenu() ? (expanded ? 'minus' : 'plus') : 'branch'; var iconimg = nodes[i].icon ? sprintf('<img src="%s/%s" align="top">', this.iconpath, nodes[i].icon) : ''; /** * Build the html to write to the document */ var divTag = sprintf('<div id="%s" style="display: %s; behavior: url(#default#userdata)">', layerID, visibility); var onClick = doesMenu() && nodes[i].n.length ? sprintf('onclick="%s.toggleBranch(\'%s\', true)" style="cursor: pointer; cursor: hand"', this.myname, layerID) : ''; var imgTag = sprintf('<img src="%s/%s%s.gif" align="top" border="0" name="img_%s" %s />', this.iconpath, gifname, modifier, layerID, onClick); var linkStart = nodes[i].link ? sprintf('<a href="%s" target="%s">', nodes[i].link, this.linkTarget) : ''; var linkEnd = nodes[i].link ? '</a>' : ''; output = sprintf('%s<nobr>%s%s%s%s%s%s</nobr><br></div>', divTag, prepend, parentLayerID == null && nodes.length == 1 ? '' : imgTag, iconimg, linkStart, nodes[i].title, linkEnd); /** * Write out the HTML */ if (this.doesMenu()) { this.getLayer(this.layer).innerHTML += output } else { document.write(output); } if (nodes[i].n.length) { /** * Determine what to prepend. If there is only one root * node then the prepend to pass to children is nothing. * Otherwise it depends on where we are in the tree. */ if (parentLayerID == null && nodes.length == 1) { var newPrepend = ''; } else if (i < (nodes.length - 1)) { var newPrepend = prepend + sprintf('<img src="%s/line.gif" align="top">', this.iconpath); } else { var newPrepend = prepend + sprintf('<img src="%s/linebottom.gif" align="top">', this.iconpath); } this.drawMenu(nodes[i].n, explode('_', implode('_', level)), // Seemingly necessary to enforce passing by value newPrepend, nodes[i].expanded, expanded ? 'inline' : 'none', layerID); } } } function toggleBranch(layerID, updateStatus) // OPTIONAL ARGS: noSave = false { var currentDisplay = this.getLayer(layerID).style.display; var newDisplay = (this.branchStatus[layerID] && currentDisplay == 'inline') ? 'none' : 'inline' for (var i=0; i<this.layerRelations[layerID].length; i++) { if (this.branchStatus[this.layerRelations[layerID][i]]) { this.toggleBranch(this.layerRelations[layerID][i], false); } this.getLayer(this.layerRelations[layerID][i]).style.display = newDisplay; } if (updateStatus) { this.branchStatus[layerID] = !this.branchStatus[layerID]; /** * Persistence */ if (this.doesPersistence() && !arguments[2]) { this.saveExpandedStatus(layerID, this.branchStatus[layerID]); } // Swap image this.swapImage(layerID); } } /** * Swaps the plus/minus branch images */ function swapImage(layerID) { imgSrc = document.images['img_' + layerID].src; re = /^(.*)(plus|minus)(bottom|top|single)?.gif$/ if (matches = imgSrc.match(re)) { document.images['img_' + layerID].src = sprintf('%s%s%s%s', matches[1], matches[2] == 'plus' ? 'minus' : 'plus', matches[3], '.gif'); } } /** * Can the browser handle the dynamic menu? */ function doesMenu() { return (is_ie5up || is_nav6up || is_gecko); } /** * Can the browser handle save the branch status */ function doesPersistence() { return is_ie5up; } /** * Returns the appropriate layer accessor */ function getLayer(layerID) { if (document.getElementById(layerID)) { return document.getElementById(layerID); } else if (document.all(layerID)) { return document.all(layerID); } } /** * Save the status of the layer */ function saveExpandedStatus(layerID, expanded) { document.all(layerID).setAttribute("expandedStatus", expanded); document.all(layerID).save(layerID); } /** * Load the status of the layer */ function loadExpandedStatus(layerID) { document.all(layerID).load(layerID); if (val = document.all(layerID).getAttribute("expandedStatus")) { return val; } else { return null; } } /** * Reset branch status */ function resetBranches() { if (!this.doesPersistence()) { return false; } for (var i=0; i<this.branches.length; i++) { var status = this.loadExpandedStatus(this.branches[i]); // Only update if it's supposed to be expanded and it's not already if (status == 'true' && this.branchStatus[this.branches[i]] != true) { if (this.childParents[this.branches[i]] == null || (in_array(this.childParents[this.branches[i]], this.branches) && this.branchStatus[this.childParents[this.branches[i]]])) { this.toggleBranch(this.branches[i], true, true); } else { this.branchStatus[this.branches[i]] = true; this.swapImage(this.branches[i]); } } } } /** * Javascript mini implementation of sprintf() */ function sprintf(strInput) { var strOutput = ''; var currentArg = 1; for (var i=0; i<strInput.length; i++) { if (strInput.charAt(i) == '%' && i != (strInput.length - 1) && typeof(arguments[currentArg]) != 'undefined') { switch (strInput.charAt(++i)) { case 's': strOutput += arguments[currentArg]; break; case '%': strOutput += '%'; break; } currentArg++; } else { strOutput += strInput.charAt(i); } } return strOutput; } function explode(seperator, input) { var output = []; var tmp = ''; skipEmpty = arguments[2] ? true : false; for (var i=0; i<input.length; i++) { if (input.charAt(i) == seperator) { if (tmp == '' && skipEmpty) { continue; } else { output[output.length] = tmp; tmp = ''; } } else { tmp += input.charAt(i); } } if (tmp != '' || !skipEmpty) { output[output.length] = tmp; } return output; } function implode(seperator, input) { var output = ''; for (var i=0; i<input.length; i++) { if (i == 0) { output += input[i]; } else { output += seperator + input[i]; } } return output; } function in_array(item, arr) { for (var i=0; i<arr.length; i++) { if (arr[i] == item) { return true; } } return false; }