/* Render threaded lists with Horde_Tree. */
$current = key($threads);
if (!$template_file && isset($threads[$current]['indent'])) {
- $tree = Horde_Tree::factory('threads', 'html');
+ $tree = $GLOBALS['injector']->getInstance('Horde_Tree')->getTree('threads', 'Html');
$tree->setOption(array('multiline' => $bodies,
'lines' => !$bodies));
$tree->setHeader(array(
->getScope()
->listGalleries($params);
- $tree = Horde_Tree::factory('gallery_tree', 'Select');
+ $tree = $GLOBALS['injector']->getInstance('Horde_Tree')->getTree('gallery_tree', 'Select');
- /* Remove the ignored gallery, make sure it's also not the selected gallery */
+ /* Remove the ignored gallery, make sure it's also not the selected
+ * gallery */
if ($params->ignore) {
if ($params->selected == $params->ignore) {
$params->selected = null;
<?php
$params = array('icondir' => Horde_Themes::img(), 'icon' => '');
-$tree = Horde_Tree::factory('account_tree', 'Javascript');
+$tree = $GLOBALS['injector']->getInstance('Horde_Tree')->getTree('account_tree', 'Javascript');
foreach ($accounts as $accountId => $account) {
$params['icon'] = $account['icon'];
--- /dev/null
+<?php
+/**
+ * @category Horde
+ * @package Core
+ */
+class Horde_Core_Binder_Tree implements Horde_Injector_Binder
+{
+ public function create(Horde_Injector $injector)
+ {
+ return new Horde_Core_Factory_Tree($injector);
+ }
+
+ public function equals(Horde_Injector_Binder $binder)
+ {
+ return false;
+ }
+}
--- /dev/null
+<?php
+/**
+ * A Horde_Injector:: based Horde_Tree:: factory.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package Core
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Core
+ */
+
+/**
+ * A Horde_Injector:: based Horde_Tree:: factory.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Horde
+ * @package Core
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Core
+ */
+class Horde_Core_Factory_Tree
+{
+ /**
+ * The injector.
+ *
+ * @var Horde_Injector
+ */
+ private $_injector;
+
+ /**
+ * Singleton instances.
+ *
+ * @var array
+ */
+ private $_instances = array();
+
+ /**
+ * Constructor.
+ *
+ * @param Horde_Injector $injector The injector to use.
+ */
+ public function __construct(Horde_Injector $injector)
+ {
+ $this->_injector = $injector;
+ }
+
+ /**
+ * Return the Horde_Tree:: instance.
+ *
+ * @param string $name The name of this tree instance.
+ * @param mixed $renderer The type of tree renderer.
+ * @param array $params Any additional parameters the constructor
+ * needs.
+ *
+ * @return Horde_Tree The singleton instance.
+ * @throws Horde_Tree_Exception
+ */
+ public function getTree($name, $renderer, array $params = array())
+ {
+ $renderer = Horde_String::lower($renderer);
+ $id = $name . '|' . $renderer;
+
+ if (!isset($this->_instances[$id])) {
+ switch ($renderer) {
+ case 'html':
+ $renderer = 'Horde_Core_Tree_Html';
+ break;
+
+ case 'javascript':
+ $renderer = 'Horde_Core_Tree_Javascript';
+ break;
+ }
+
+ $this->_instances[$id] = Horde_Tree::factory($name, $renderer, $params);
+ }
+
+ return $this->_instances[$id];
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Horde_Core_Tree_Html:: class extends the Horde_Tree_Html class to
+ * provide for creation of Horde-specific URLs.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author Michael Slusarz <slusarz@curecanti.org>
+ * @category Horde
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @package Core
+ */
+class Horde_Core_Tree_Html extends Horde_Tree_Html
+{
+ /**
+ * Images array.
+ *
+ * @var array
+ */
+ protected $_images = array(
+ 'line' => 'line.png',
+ 'blank' => 'blank.png',
+ 'join' => 'join.png',
+ 'join_bottom' => 'joinbottom.png',
+ 'plus' => 'plus.png',
+ 'plus_bottom' => 'plusbottom.png',
+ 'plus_only' => 'plusonly.png',
+ 'minus' => 'minus.png',
+ 'minus_bottom' => 'minusbottom.png',
+ 'minus_only' => 'minusonly.png',
+ 'null_only' => 'nullonly.png',
+ 'folder' => 'folder.png',
+ 'folderopen' => 'folderopen.png',
+ 'leaf' => 'leaf.png'
+ );
+
+ /**
+ * Constructor.
+ *
+ * @param string $name @see parent::__construct().
+ * @param array $params @see parent::__construct().
+ */
+ public function __construct($name, array $params = array())
+ {
+ parent::__construct($name, $params);
+
+ if (!isset($_SESSION['horde_tree'][$this->_instance])) {
+ $_SESSION['horde_tree'][$this->_instance] = array();
+ }
+
+ if (!empty($GLOBALS['nls']['rtl'][$GLOBALS['language']])) {
+ $no_rev = array('blank', 'folder', 'folder_open');
+ foreach (array_diff(array_keys($this->_images), $no_rev) as $key) {
+ $this->_images[$key] = 'rev-' . $this->_images[$key];
+ }
+ }
+
+ foreach (array_keys($this->_images) as $key) {
+ $this->_images[$key] = strval(Horde_Themes::img('tree/' . $this->_images[$key], array('app' => 'horde')));
+ }
+ }
+
+ /**
+ * Generate a link URL tag.
+ *
+ * @param string $node_id The node ID.
+ *
+ * @return string The link tag.
+ */
+ protected function _generateUrlTag($node_id)
+ {
+ return Horde::link(Horde::selfUrl()->add(self::TOGGLE . $this->_instance, $node_id));
+ }
+
+ /**
+ * Adds a node to the node tree array.
+ *
+ * @param string $id The unique node id.
+ * @param string $parent The parent's unique node id.
+ * @param string $label The text label for the node.
+ * @param string $indent Deprecated, this is calculated automatically
+ * based on the parent node.
+ * @param boolean $expanded Is this level expanded or not.
+ * @param array $params Any other parameters to set (@see
+ * addNodeParams() for full details).
+ * @param array $extra_right Any other columns to display to the right of
+ * the tree.
+ * @param array $extra_left Any other columns to display to the left of
+ * the tree.
+ */
+ public function addNode($id, $parent, $label, $indent = null,
+ $expanded = true, $params = array(),
+ $extra_right = array(), $extra_left = array())
+ {
+ $sess = $_SESSION['horde_tree'][$this->_instance];
+ $toggle_id = Horde_Util::getFormData(self::TOGGLE . $this->_instance);
+
+ if ($id == $toggle_id) {
+ /* We have a URL toggle request for this node. */
+ $expanded = $_SESSION['horde_tree'][$this->_instance]['expanded'][$id] = isset($sess['expanded'][$id])
+ /* Use session state if it is set. */
+ ? (!$sess['expanded'][$id])
+ /* Otherwise use what was passed through the function. */
+ : (!$expanded);
+ } elseif (isset($sess['expanded'][$id])) {
+ /* If we have a saved session state use it. */
+ $expanded = $sess['expanded'][$id];
+ }
+
+ parent::addNode($id, $parent, $label, $indent, $expanded, $params, $extra_right, $extra_left);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Horde_Core_Tree_Javascript:: class extends the Horde_Core_Tree_Html
+ * class to provide a javascript rendering of a tree.
+ *
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author Marko Djukic <marko@oblo.com>
+ * @author Michael Slusarz <slusarz@curecanti.org>
+ * @category Horde
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @package Core
+ */
+class Horde_Core_Tree_Javascript extends Horde_Core_Tree_Html
+{
+ /**
+ * Constructor.
+ *
+ * @param string $name @see parent::__construct().
+ * @param array $params @see parent::__construct().
+ */
+ public function __construct($name, array $params = array())
+ {
+ parent::__construct($name, $params);
+
+ Horde::addScriptFile('prototype.js', 'horde');
+ Horde::addScriptFile('hordetree.js', 'horde');
+
+ /* Check for a javascript session state. */
+ if (isset($_COOKIE[$this->_instance . '_expanded'])) {
+ /* Remove "exp" prefix from cookie value. */
+ $nodes = explode(',', substr($_COOKIE[$this->_instance . '_expanded'], 3));
+
+ /* Save nodes to the session. */
+ $_SESSION['horde_tree'][$this->_instance]['expanded'] = array_combine(
+ $nodes,
+ array_fill(0, count($nodes), true)
+ );
+ }
+ }
+
+ /**
+ * Provide a simpler renderer to fallback to.
+ *
+ * @return string The next best renderer.
+ */
+ public function fallback()
+ {
+ return 'Horde_Core_Tree_Html';
+ }
+
+ /**
+ * Returns the tree.
+ *
+ * @param boolean $static If true the tree nodes can't be expanded and
+ * collapsed and the tree gets rendered expanded.
+ *
+ * @return string The HTML code of the rendered tree.
+ */
+ public function getTree($static = false)
+ {
+ $this->_static = $static;
+
+ $opts = array(
+ 'extraColsLeft' => $this->_extra_cols_left,
+ 'extraColsRight' => $this->_extra_cols_right,
+ 'header' => $this->_header,
+ 'options' => $this->_options,
+ 'target' => $this->_instance,
+
+ 'cookieDomain' => $GLOBALS['conf']['cookie']['domain'],
+ 'cookiePath' => $GLOBALS['conf']['cookie']['path'],
+
+ 'scrollbar_in_way' => $GLOBALS['browser']->hasQuirk('scrollbar_in_way'),
+
+ 'imgBlank' => $this->_images['blank'],
+ 'imgFolder' => $this->_images['folder'],
+ 'imgFolderOpen' => $this->_images['folderopen'],
+ 'imgLine' => $this->_images['line'],
+ 'imgJoin' => $this->_images['join'],
+ 'imgJoinBottom' => $this->_images['join_bottom'],
+ 'imgPlus' => $this->_images['plus'],
+ 'imgPlusBottom' => $this->_images['plus_bottom'],
+ 'imgPlusOnly' => $this->_images['plus_only'],
+ 'imgMinus' => $this->_images['minus'],
+ 'imgMinusBottom' => $this->_images['minus_bottom'],
+ 'imgMinusOnly' => $this->_images['minus_only'],
+ 'imgNullOnly' => $this->_images['null_only'],
+ 'imgLeaf' => $this->_images['leaf'],
+
+ 'floatDir' => (empty($GLOBALS['nls']['rtl'][$GLOBALS['language']]) ? 'float:left;' : 'float:right')
+ );
+
+ Horde::addInlineScript(array(
+ 'window.' . $this->_instance . ' = new Horde_Tree(' . Horde_Serialize::serialize($opts, Horde_Serialize::JSON, $GLOBALS['registry']->getCharset()) . ')',
+ $this->renderNodeDefinitions()
+ ), 'dom');
+
+ return '<div id="' . $this->_instance . '"></div>';
+ }
+
+ /**
+ * Check the current environment to see if we can render the HTML tree.
+ * We check for DOM support in the browser.
+ *
+ * @return boolean Whether or not this backend will function.
+ */
+ public function isSupported()
+ {
+ return $GLOBALS['browser']->hasFeature('dom');
+ }
+
+ /**
+ * Returns just the JS node definitions as a string.
+ *
+ * @return string The Javascript node array definitions.
+ */
+ public function renderNodeDefinitions()
+ {
+ $this->_buildIndents($this->_root_nodes);
+
+ return 'window.' . $this->_instance . '.renderTree(' . Horde_Serialize::serialize($this->_nodes, Horde_Serialize::JSON, $GLOBALS['registry']->getCharset()) . ',' . Horde_Serialize::serialize($this->_root_nodes, Horde_Serialize::JSON, $GLOBALS['registry']->getCharset()) . ',' . ($this->_static ? 'true' : 'false') . ');';
+ }
+
+}
'Horde_SessionHandler' => new Horde_Core_Binder_SessionHandler(),
'Horde_Share' => new Horde_Core_Binder_Share(),
'Horde_Template' => new Horde_Core_Binder_Template(),
+ 'Horde_Tree' => new Horde_Core_Binder_Tree(),
'Horde_Token' => new Horde_Core_Binder_Token(),
'Horde_Vfs' => new Horde_Core_Binder_Vfs(),
'Net_DNS_Resolver' => new Horde_Core_Binder_Dns()
<file name="Share.php" role="php" />
<file name="Template.php" role="php" />
<file name="Token.php" role="php" />
+ <file name="Tree.php" role="php" />
<file name="Twitter.php" role="php" />
<file name="Vfs.php" role="php" />
</dir> <!-- /lib/Horde/Core/Binder -->
<file name="Ldap.php" role="php" />
<file name="LoginTasks.php" role="php" />
<file name="Share.php" role="php" />
+ <file name="Tree.php" role="php" />
<file name="Vfs.php" role="php" />
</dir> <!-- /lib/Horde/Core/Factory -->
<dir name="Log">
<file name="Emoticons.php" role="php" />
</dir> <!-- /lib/Horde/Core/Text/Filter -->
</dir> <!-- /lib/Horde/Core/Text -->
+ <dir name="Tree">
+ <file name="Html.php" role="php" />
+ <file name="Javascript.php" role="php" />
+ </dir> <!-- /lib/Horde/Core/Tree -->
<file name="Autoloader.php" role="php" />
</dir> <!-- /lib/Horde/Core -->
<dir name="Exception">
<name>Text_Filter</name>
<channel>pear.horde.org</channel>
</package>
+ <package>
+ <name>Tree</name>
+ <channel>pear.horde.org</channel>
+ </package>
</optional>
</dependencies>
<phprelease>
<install as="Horde/Core/Binder/SessionHandler.php" name="lib/Horde/Core/Binder/SessionHandler.php" />
<install as="Horde/Core/Binder/Share.php" name="lib/Horde/Core/Binder/Share.php" />
<install as="Horde/Core/Binder/Template.php" name="lib/Horde/Core/Binder/Template.php" />
+ <install as="Horde/Core/Binder/Tree.php" name="lib/Horde/Core/Binder/Tree.php" />
<install as="Horde/Core/Binder/Token.php" name="lib/Horde/Core/Binder/Token.php" />
<install as="Horde/Core/Binder/Twitter.php" name="lib/Horde/Core/Binder/Twitter.php" />
<install as="Horde/Core/Binder/Vfs.php" name="lib/Horde/Core/Binder/Vfs.php" />
<install as="Horde/Core/Factory/Ldap.php" name="lib/Horde/Core/Factory/Ldap.php" />
<install as="Horde/Core/Factory/LoginTasks.php" name="lib/Horde/Core/Factory/LoginTasks.php" />
<install as="Horde/Core/Factory/Share.php" name="lib/Horde/Core/Factory/Share.php" />
+ <install as="Horde/Core/Factory/Tree.php" name="lib/Horde/Core/Factory/Tree.php" />
<install as="Horde/Core/Factory/Vfs.php" name="lib/Horde/Core/Factory/Vfs.php" />
<install as="Horde/Core/Log/Logger.php" name="lib/Horde/Core/Log/Logger.php" />
<install as="Horde/Core/LoginTasks/Backend/Horde.php" name="lib/Horde/Core/LoginTasks/Backend/Horde.php" />
<install as="Horde/Core/Prefs/Ui.php" name="lib/Horde/Core/Prefs/Ui.php" />
<install as="Horde/Core/Prefs/Ui/Widgets.php" name="lib/Horde/Core/Prefs/Ui/Widgets.php" />
<install as="Horde/Core/Text/Filter/Emoticons.php" name="lib/Horde/Core/Text/Filter/Emoticons.php" />
+ <install as="Horde/Core/Tree/Html.php" name="lib/Horde/Core/Tree/Html.php" />
+ <install as="Horde/Core/Tree/Javascript.php" name="lib/Horde/Core/Tree/Javascript.php" />
<install as="Horde/Exception/HookNotSet.php" name="lib/Horde/Exception/HookNotSet.php" />
<install as="Horde/Registry/Api.php" name="lib/Horde/Registry/Api.php" />
<install as="Horde/Registry/Application.php" name="lib/Horde/Registry/Application.php" />
<?php
/**
* The Horde_Tree:: class provides a tree view of hierarchical information. It
- * allows for expanding/collapsing of branches and maintains their state.
+ * allows for expanding/collapsing of branches.
*
* Copyright 2003-2010 The Horde Project (http://www.horde.org/)
*
*
* @author Marko Djukic <marko@oblo.com>
* @category Horde
- * @package Horde_Tree
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @package Tree
*/
class Horde_Tree
{
const TOGGLE = 'ht_toggle_';
/**
- * Singleton instances.
- *
- * @var array
- */
- static protected $_instances = array();
-
- /**
* The name of this instance.
*
* @var string
);
/**
- * Image directory location.
- *
- * @var string
- */
- protected $_img_dir = '';
-
- /**
- * Images array.
- *
- * @var array
- */
- protected $_images = array(
- 'line' => 'line.png',
- 'blank' => 'blank.png',
- 'join' => 'join.png',
- 'join_bottom' => 'joinbottom.png',
- 'plus' => 'plus.png',
- 'plus_bottom' => 'plusbottom.png',
- 'plus_only' => 'plusonly.png',
- 'minus' => 'minus.png',
- 'minus_bottom' => 'minusbottom.png',
- 'minus_only' => 'minusonly.png',
- 'null_only' => 'nullonly.png',
- 'folder' => 'folder.png',
- 'folderopen' => 'folderopen.png',
- 'leaf' => 'leaf.png'
- );
-
- /**
* Stores the sorting criteria temporarily.
*
* @var string
protected $_sortCriteria;
/**
- * Use session to store cached Tree data?
- *
- * @var boolean
- */
- protected $_usesession = true;
-
- /**
* Should the tree be rendered statically?
*
* @var boolean
protected $_static = false;
/**
- * Attempts to return a reference to a concrete instance.
- * It will only create a new instance if no instance with the same
- * parameters currently exists.
- *
- * This method must be invoked as:
- * $var = Horde_Tree::singleton($name[, $renderer[, $params]]);
- *
- * @param mixed $name @see Horde_Tree::factory.
- * @param string $renderer @see Horde_Tree::factory.
- * @param array $params @see Horde_Tree::factory.
- *
- * @return Horde_Tree The concrete instance.
- * @throws Horde_Exception
- */
- static public function singleton($name, $renderer, $params = array())
- {
- ksort($params);
- $id = $name . ':' . $renderer . ':' . serialize($params);
-
- if (!isset(self::$_instances[$id])) {
- self::$_instances[$id] = self::factory($name, $renderer, $params);
- if (!self::$_instances[$id]->isSupported()) {
- $renderer = self::fallback($renderer);
- return self::singleton($name, $renderer, $params);
- }
- }
-
- return self::$_instances[$id];
- }
-
- /**
* Attempts to return a concrete instance.
*
- * @param string $name The name of this tree instance.
- * @param mixed $renderer The type of concrete subclass to return. This
- * is based on the rendering driver. The code is
- * dynamically included.
- * @param array $params Any additional parameters the constructor
- * needs.
+ * @param string $name The name of this tree instance.
+ * @param string $renderer Either the tree renderer driver or a full
+ * class name to use.
+ * @param array $params Any additional parameters the constructor
+ * needs.
*
* @return Horde_Tree The newly created concrete instance.
- * @throws Horde_Exception
+ * @throws Horde_Tree_Exception
*/
static public function factory($name, $renderer, $params = array())
{
+ $ob = null;
+
+ /* Base drivers (in Tree/ directory). */
$class = __CLASS__ . '_' . ucfirst($renderer);
if (class_exists($class)) {
- return new $class($name, $params);
+ $ob = new $class($name, $params);
+ } else {
+ /* Explicit class name, */
+ $class = $renderer;
+ if (class_exists($class)) {
+ $ob = new $class($name, $params);
+ }
}
- throw new Horde_Exception('Horde_Tree renderer not found: ' . $renderer);
+ if ($ob) {
+ if ($ob->isSupported()) {
+ return $ob;
+ }
+
+ return self::factory($name, $ob->fallback(), $params);
+ }
+
+ throw new Horde_Tree_Exception(__CLASS__ . ' renderer not found: ' . $renderer);
}
/**
- * Try to fall back to a simpler renderer.
- *
- * @paran string $renderer The renderer that we can't handle.
+ * Provide a simpler renderer to fallback to.
*
* @return string The next best renderer.
- * @throws Horde_Exception
+ * @throws Horde_Tree_Exception
*/
- public function fallback($renderer)
+ public function fallback()
{
- switch ($renderer) {
- case 'javascript':
- return 'html';
-
- case 'html':
- throw new Horde_Exception('No fallback renderer found.');
- }
+ throw new Horde_Tree_Exception('No fallback renderer found.');
}
/**
* Constructor.
*
* @param string $name The name of this tree instance.
- * @param array $params Additional parameters:
+ * @param array $params Additional parameters.
* <pre>
- * 'nosession' - (boolean) If true, do not store tree data in session.
+ * alternate - (boolean) Alternate shading in the table?
+ * class - (string) The class to use for the table.
+ * hideHeaders - (boolean) Don't render any HTML for the header row, just
+ * use the widths.
+ * lines - (boolean) Show tree lines?
+ * multiline - (boolean) Do the node labels contain linebreaks?
* </pre>
*/
- public function __construct($name, $params = array())
+ public function __construct($name, array $params = array())
{
$this->_instance = $name;
- $this->_usesession = empty($params['nosession']);
- unset($params['nosession']);
$this->setOption($params);
+ }
- /* Set up the session for later to save tree states. */
- if ($this->_usesession &&
- !isset($_SESSION['horde_tree'][$this->_instance])) {
- $_SESSION['horde_tree'][$this->_instance] = array();
- }
-
- $this->_img_dir = Horde_Themes::img(null, array('app' => 'horde', 'notheme' => true)) . '/tree';
-
- if (!empty($GLOBALS['nls']['rtl'][$GLOBALS['language']])) {
- $rev_imgs = array(
- 'line', 'join', 'join_bottom', 'plus', 'plus_bottom',
- 'plus_only', 'minus', 'minus_bottom', 'minus_only',
- 'null_only', 'leaf'
- );
- foreach ($rev_imgs as $val) {
- $this->_images[$val] = 'rev-' . $this->_images[$val];
- }
- }
+ /**
+ * Returns the tree.
+ *
+ * @param boolean $static If true the tree nodes can't be expanded and
+ * collapsed and the tree gets rendered expanded.
+ *
+ * @return string The HTML code of the rendered tree.
+ */
+ public function getTree($static = false)
+ {
+ return '';
}
/**
/**
* Sets an option.
*
- * @param mixed $option The option name -or- an array of option name/value
- * pairs. Available options:
- * <pre>
- * alternate - (boolean) Alternate shading in the table?
- * class - (string) The class to use for the table.
- * hideHeaders - (boolean) Don't render any HTML for the header row, just
- * use the widths.
- * lines - (boolean) Show tree lines?
- * multiline - (boolean) Do the node labels contain linebreaks?
- * </pre>
+ * @param mixed $option The option name -or- an array of option
+ * name/value pairs. See constructor for available
+ * options.
* @param mixed $value The option's value.
*/
public function setOption($options, $value = null)
$extra_right = array(), $extra_left = array())
{
$this->_nodes[$id]['label'] = $label;
-
- if ($this->_usesession) {
- $session_state = $_SESSION['horde_tree'][$this->_instance];
- $toggle_id = Horde_Util::getFormData(self::TOGGLE . $this->_instance);
- if ($id == $toggle_id) {
- /* We have a url toggle request for this node. */
- if (isset($session_state['expanded'][$id])) {
- /* Use session state if it is set. */
- $expanded = (!$session_state['expanded'][$id]);
- } else {
- /* Otherwise use what was passed through the
- * function. */
- $expanded = (!$expanded);
- }
-
- /* Save this state to session. */
- $_SESSION['horde_tree'][$this->_instance]['expanded'][$id] = $expanded;
- } elseif (isset($session_state['expanded'][$id])) {
- /* If we have a saved session state use it. */
- $expanded = $session_state['expanded'][$id];
- }
- }
-
$this->_nodes[$id]['expanded'] = $expanded;
/* If any params included here add them now. */
return true;
}
- /**
- * Returns just the JS node definitions as a string.
- *
- * @return string The Javascript node array definitions.
- */
- public function renderNodeDefinitions()
- {
- }
-
}
--- /dev/null
+<?php
+/**
+ * Exception handler for the Horde_Tree package.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @category Horde
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @package Tree
+ */
+class Horde_Tree_Exception extends Horde_Exception_Prior
+{
+}
*
* @author Marko Djukic <marko@oblo.com>
* @category Horde
- * @package Horde_Tree
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @package Tree
*/
class Horde_Tree_Html extends Horde_Tree
{
/**
- * TODO
+ * Node list.
*
* @var array
*/
protected $_nodes = array();
/**
- * TODO
+ * Node position list.
*
* @var array
*/
protected $_node_pos = array();
/**
- * TODO
+ * Drop line cache.
*
* @var array
*/
protected $_alt_count = 0;
/**
+ * Images array.
+ *
+ * @var array
+ */
+ protected $_images = array(
+ 'line' => null,
+ 'blank' => null,
+ 'join' => null,
+ 'join_bottom' => null,
+ 'plus' => null,
+ 'plus_bottom' => null,
+ 'plus_only' => null,
+ 'minus' => null,
+ 'minus_bottom' => null,
+ 'minus_only' => null,
+ 'null_only' => null,
+ 'folder' => null,
+ 'folderopen' => null,
+ 'leaf' => null
+ );
+
+ /**
* Returns the tree.
*
* @param boolean $static If true the tree nodes can't be expanded and
}
for ($i = $this->_static ? 1 : 0; $i < $this->_nodes[$node_id]['indent']; $i++) {
- $line .= '<img src="' . $this->_img_dir . '/';
+ $line .= '<img src="';
if ($this->_dropline[$i] && $this->getOption('lines', false, true)) {
$line .= $this->_images['line'] . '" '
- . 'alt="| " ';
+ . 'alt="| "';
} else {
$line .= $this->_images['blank'] . '" '
- . 'alt=" " ';
+ . 'alt=" "';
}
- $line .= 'height="20" width="20" style="vertical-align:middle" />';
+ $line .= ' />';
}
$line .= $this->_setNodeToggle($node_id) . $this->_setNodeIcon($node_id);
if ($this->getOption('multiline')) {
$img = $this->_images['plus_only'];
$alt = '+';
}
+
if (!$this->_static) {
- $url = Horde_Util::addParameter(Horde::selfUrl(), self::TOGGLE . $this->_instance, $node_id);
- $link_start = Horde::link($url);
+ $link_start = $this->_generateUrlTag($node_id);
}
} elseif (($this->_nodes[$node_id]['indent'] != 0) &&
!isset($this->_nodes[$node_id]['children'])) {
}
$this->_dropline[$this->_nodes[$node_id]['indent']] = false;
}
+
if (!$this->_static) {
- $url = Horde_Util::addParameter(Horde::selfUrl(), self::TOGGLE . $this->_instance, $node_id);
- $link_start = Horde::link($url);
+ $link_start = $this->_generateUrlTag($node_id);
}
} else {
/* Top level node with no children. */
$link_end = ($link_start) ? '</a>' : '';
- $img = $link_start . '<img src="' . $this->_img_dir . '/' . $img . '"'
+ $img = $link_start . '<img class="treeToggle" src="' . $img . '"'
. (isset($alt) ? ' alt="' . $alt . '"' : '')
- . ' height="20" width="20" style="vertical-align:middle" border="0" />'
+ . ' />'
. $link_end;
return $img;
}
/**
+ * Generate a link URL.
+ *
+ * @param string $node_id The node ID.
+ *
+ * @return string The link tag.
+ */
+ protected function _generateUrlTag($node_id)
+ {
+ $url = new Horde_Url($_SERVER['PHP_SELF']);
+ $url->add(self::TOGGLE . $this->_instance, $node_id);
+
+ return '<a href="' . strval($url) . '">';
+ }
+
+ /**
* Sets the icon for the node.
*
* @param string $node_id The Node ID.
*/
protected function _setNodeIcon($node_id)
{
- $img_dir = isset($this->_nodes[$node_id]['icondir']) ? $this->_nodes[$node_id]['icondir'] : $this->_img_dir;
- if ($img_dir) {
- $img_dir .= '/';
- }
-
if (isset($this->_nodes[$node_id]['icon'])) {
if (empty($this->_nodes[$node_id]['icon'])) {
return '';
}
}
- $imgtxt = '<img src="' . $img_dir . $img . '"';
+ $imgtxt = '<img class="treeIcon" src="' . $img . '"';
/* Does the node have user defined alt text? */
if (isset($this->_nodes[$node_id]['iconalt'])) {
+++ /dev/null
-<?php
-/**
- * The Horde_Tree_Javascript:: class extends the Horde_Tree class to provide
- * javascript specific rendering functions.
- *
- * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @author Marko Djukic <marko@oblo.com>
- * @category Horde
- * @package Horde_Tree
- */
-class Horde_Tree_Javascript extends Horde_Tree
-{
- /**
- * Constructor.
- *
- * @param string $name @see Horde_Tree::__construct().
- * @param array $params @see Horde_Tree::__construct().
- */
- public function __construct($tree_name, $params = array())
- {
- parent::__construct($tree_name, $params);
-
- /* Check for a javascript session state. */
- if ($this->_usesession &&
- isset($_COOKIE[$this->_instance . '_expanded'])) {
- /* Remove "exp" prefix from cookie value. */
- $nodes = explode(',', substr($_COOKIE[$this->_instance . '_expanded'], 3));
-
- /* Make sure there are no previous nodes stored in the
- * session. */
- $_SESSION['horde_tree'][$this->_instance]['expanded'] = array();
-
- /* Save nodes to the session. */
- foreach ($nodes as $id) {
- $_SESSION['horde_tree'][$this->_instance]['expanded'][$id] = true;
- }
- }
-
- Horde::addScriptFile('prototype.js', 'horde');
- Horde::addScriptFile('hordetree.js', 'horde');
- }
-
- /**
- * Returns the tree.
- *
- * @param boolean $static If true the tree nodes can't be expanded and
- * collapsed and the tree gets rendered expanded.
- *
- * @return string The HTML code of the rendered tree.
- */
- public function getTree($static = false)
- {
- $this->_static = $static;
-
- $opts = array(
- 'extraColsLeft' => $this->_extra_cols_left,
- 'extraColsRight' => $this->_extra_cols_right,
- 'header' => $this->_header,
- 'options' => $this->_options,
- 'target' => $this->_instance,
-
- 'cookieDomain' => $GLOBALS['conf']['cookie']['domain'],
- 'cookiePath' => $GLOBALS['conf']['cookie']['path'],
-
- 'scrollbar_in_way' => $GLOBALS['browser']->hasQuirk('scrollbar_in_way'),
-
- 'imgDir' => $this->_img_dir,
- 'imgBlank' => $this->_images['blank'],
- 'imgFolder' => $this->_images['folder'],
- 'imgFolderOpen' => $this->_images['folderopen'],
- 'imgLine' => $this->_images['line'],
- 'imgJoin' => $this->_images['join'],
- 'imgJoinBottom' => $this->_images['join_bottom'],
- 'imgPlus' => $this->_images['plus'],
- 'imgPlusBottom' => $this->_images['plus_bottom'],
- 'imgPlusOnly' => $this->_images['plus_only'],
- 'imgMinus' => $this->_images['minus'],
- 'imgMinusBottom' => $this->_images['minus_bottom'],
- 'imgMinusOnly' => $this->_images['minus_only'],
- 'imgNullOnly' => $this->_images['null_only'],
- 'imgLeaf' => $this->_images['leaf'],
-
- 'floatDir' => empty($GLOBALS['nls']['rtl'][$GLOBALS['language']]) ? 'float:left;' : 'float:right'
- );
-
- Horde::addInlineScript(array(
- 'window.' . $this->_instance . ' = new Horde_Tree(' . Horde_Serialize::serialize($opts, Horde_Serialize::JSON, $GLOBALS['registry']->getCharset()) . ')',
- $this->renderNodeDefinitions()
- ), 'dom');
-
- return '<div id="' . $this->_instance . '"></div>';
- }
-
- /**
- * Check the current environment to see if we can render the HTML tree.
- * We check for DOM support in the browser.
- *
- * @return boolean Whether or not this backend will function.
- */
- public function isSupported()
- {
- return $GLOBALS['browser']->hasFeature('dom');
- }
-
- /**
- * Returns just the JS node definitions as a string.
- *
- * @return string The Javascript node array definitions.
- */
- public function renderNodeDefinitions()
- {
- $this->_buildIndents($this->_root_nodes);
-
- return 'window.' . $this->_instance . '.renderTree(' . Horde_Serialize::serialize($this->_nodes, Horde_Serialize::JSON, $GLOBALS['registry']->getCharset()) . ',' . Horde_Serialize::serialize($this->_root_nodes, Horde_Serialize::JSON, $GLOBALS['registry']->getCharset()) . ',' . ($this->_static ? 'true' : 'false') . ');';
- }
-
-}
*
* @author Ben Chavet <ben@horde.org>
* @category Horde
- * @package Horde_Tree
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @package Tree
*/
class Horde_Tree_Select extends Horde_Tree
{
/**
- * TODO
+ * Node list.
*
* @var array
*/
protected $_nodes = array();
/**
- * Constructor.
+ * Should the tree be rendered statically?
*
- * @param string $name @see Horde_Tree::__construct().
- * @param array $params @see Horde_Tree::__construct().
+ * @var boolean
*/
- public function __construct($tree_name, $params = array())
- {
- parent::__construct($tree_name, $params);
- $this->_static = true;
- }
+ protected $_static = true;
/**
* Returns the tree.
*/
protected function _buildTree($node_id)
{
- $selected = $this->_nodes[$node_id]['selected'] ? ' selected="selected"' : '';
+ $selected = $this->_nodes[$node_id]['selected']
+ ? ' selected="selected"'
+ : '';
$output = '<option value="' . htmlspecialchars($node_id) . '"' . $selected . '>' .
- str_repeat(' ', (int)$this->_nodes[$node_id]['indent']) . htmlspecialchars($this->_nodes[$node_id]['label']) .
+ str_repeat(' ', intval($this->_nodes[$node_id]['indent'])) . htmlspecialchars($this->_nodes[$node_id]['label']) .
'</option>';
if (isset($this->_nodes[$node_id]['children']) &&
$this->_nodes[$node_id]['expanded']) {
$num_subnodes = count($this->_nodes[$node_id]['children']);
- for ($c = 0; $c < $num_subnodes; $c++) {
+ for ($c = 0; $c < $num_subnodes; ++$c) {
$child_node_id = $this->_nodes[$node_id]['children'][$c];
$output .= $this->_buildTree($child_node_id);
}
<name>Tree</name>
<channel>pear.horde.org</channel>
<summary>Horde Tree API</summary>
- <description>The Horde_Tree:: class provides a tree view of hierarchical information. It allows for expanding/collapsing of branches and maintains their state. It can work together with javascript code to achieve this in DHTML on supported browsers.
+ <description>The Horde_Tree:: package provides a tree view of hierarchical information. It allows for expanding/collapsing of branches and maintains their state.
</description>
<lead>
<name>Chuck Hagenbuch</name>
<api>beta</api>
</stability>
<license uri="http://www.gnu.org/copyleft/gpl.html">GPL</license>
- <notes>* Initial Horde 4 package.
+ <notes>* Remove dependency on horde/Core.
+ * Move javascript renderer to horde/Core.
+ * Add Horde_Tree_Exception::.
+ * Initial Horde 4 package.
</notes>
<contents>
<dir name="/">
<dir name="lib">
<dir name="Horde">
<dir name="Tree">
+ <file name="Exception.php" role="php" />
<file name="Html.php" role="php" />
- <file name="Javascript.php" role="php" />
<file name="Select.php" role="php" />
</dir> <!-- /lib/Horde/Tree -->
<file name="Tree.php" role="php" />
<min>1.7.0</min>
</pearinstaller>
<package>
- <name>Core</name>
+ <name>Exception</name>
<channel>pear.horde.org</channel>
</package>
<package>
</dependencies>
<phprelease>
<filelist>
+ <install name="lib/Horde/Tree/Exception.php" as="Horde/Tree/Exception.php" />
<install name="lib/Horde/Tree/Html.php" as="Horde/Tree/Html.php" />
- <install name="lib/Horde/Tree/Javascript.php" as="Horde/Tree/Javascript.php" />
<install name="lib/Horde/Tree/Select.php" as="Horde/Tree/Select.php" />
<install name="lib/Horde/Tree.php" as="Horde/Tree.php" />
</filelist>
Horde::fatal($deliverables, __FILE__, __LINE__);
}
- $tree = Horde_Tree::factory('deliverables', 'javascript');
+ $tree = $GLOBALS['injector']->getInstance('Horde_Tree')->getTree('deliverables', 'Javascript');
$tree->setOption(array('class' => 'item',
'alternate' => true));
$device_node = $icondir + array('icon' => 'mobile.png');
$user_node = $icondir + array('icon' => 'user.png');
$users = array();
-$tree = Horde_Tree::factory('admin_devices', 'Javascript');
+
+$tree = $injector->getInstance('Horde_Tree')->getTree('admin_devices', 'Javascript');
$tree->setOption(array('alternate' => true));
$tree->setHeader(array(
array('width' => '30%'),
Horde_Registry::appInit('horde', array('admin' => true));
require_once 'Horde/DataTree.php';
-$tree = Horde_Tree::factory('datatree', 'Javascript');
+$tree = $injector->getInstance('Horde_Tree')->getTree('datatree', 'Javascript');
$tree->setOption('alternate', true);
$driver = $conf['datatree']['driver'];
$delete_img = Horde::img('delete.png', _("Delete Group"));
/* Set up the tree. */
-$tree = Horde_Tree::factory('admin_groups', 'Javascript');
+$tree = $injector->getInstance('Horde_Tree')->getTree('admin_groups', 'Javascript');
$tree->setOption(array('alternate' => true, 'hideHeaders' => true));
$tree->setHeader(array(array('width' => '50%')));
}
for (i = this.renderStatic ? 1 : 0; i < node.indent; ++i) {
- o.push('<img src="' + this.opts.imgDir + '/');
+ o.push('<img src="');
if (this.dropline[i] && this.opts.options.lines) {
o.push(this.opts.imgLine + '" alt="|');
} else {
o.push(this.opts.imgBlank + '" alt="');
}
- o.push(' " height="20" width="20" />');
+ o.push(' " />');
}
o.push(this._setNodeToggle(nodeId));
if (this.renderStatic) {
return '';
}
- attrib = ' style="cursor:pointer" onclick="' + this.opts.target + '.toggle(' + nodeId.toJSON().gsub('"', '"') + ')"';
+ attrib = ' onclick="' + this.opts.target + '.toggle(' + nodeId.toJSON().gsub('"', '"') + ')"';
} else if (node.indent != '0' && Object.isUndefined(node.children)) {
// Node no children.
this.dropline[node.indent] = (this.node_pos[nodeId].pos < this.node_pos[nodeId].count);
} else if (!Object.isUndefined(node.children)) {
this.dropline[node.indent] = (this.node_pos[nodeId].pos < this.node_pos[nodeId].count);
if (!this.renderStatic) {
- attrib = ' style="cursor:pointer" onclick="' + this.opts.target + '.toggle(' + nodeId.toJSON().gsub('"', '"') + ')"';
+ attrib = ' onclick="' + this.opts.target + '.toggle(' + nodeId.toJSON().gsub('"', '"') + ')"';
}
} else {
// Top level node with no children.
this.dropline[0] = false;
}
- img.push('<img id="nodeToggle_' + nodeId + '" src="' + this.opts.imgDir + '/' + nodeToggle[0] + '" ');
+ img.push('<img class="treeToggle" id="nodeToggle_' + nodeId + '" src="' + nodeToggle[0] + '" ');
if (nodeToggle[1]) {
img.push('alt="' + nodeToggle[1] + '" ');
}
- img.push(attrib + ' height="20" width="20" />');
+ img.push(attrib + ' />');
return img.join('');
},
var img = [],
node = this.nodes[nodeId];
- img.push('<img id="nodeIcon_' + nodeId + '" src="');
+ img.push('<img class="treeIcon" id="nodeIcon_' + nodeId + '" src="');
// Image directory.
- if (!Object.isUndefined(node.icondir)) {
- if (node.icondir) {
- img.push(node.icondir + '/');
- }
- } else if (this.opts.imgDir) {
- img.push(this.opts.imgDir + '/');
+ if (!Object.isUndefined(node.icondir) && node.icondir) {
+ img.push(node.icondir + '/');
}
// Image.
img.push(' alt="' + node.iconalt + '"');
}
- img.push(' /> ');
+ img.push(' />');
return img.join('');
},
toggle: function(nodeId)
{
- var icon, nodeToggle, toggle, children
+ var icon, nodeToggle, toggle, children,
node = this.nodes[nodeId],
src = [];
children.setStyle({ display: node.expanded ? 'block' : 'none' });
}
- // Toggle the node's icon if it has seperate open and closed
+ // Toggle the node's icon if it has separate open and closed
// icons.
- if (!Object.isUndefined(node.iconopen) &&
- (icon = $('nodeIcon_' + nodeId))) {
+ if (icon = $('nodeIcon_' + nodeId)) {
// Image directory.
- if (!Object.isUndefined(node.icondir)) {
- if (node.icondir) {
- src.push(node.icondir + '/');
- }
- } else if (this.opts.imgDir) {
- src.push(this.opts.imgDir + '/');
+ if (!Object.isUndefined(node.icondir) && node.icondir) {
+ src.push(node.icondir + '/');
}
// Image.
nodeToggle = this._getNodeToggle(nodeId);
if (toggle = $('nodeToggle_' + nodeId)) {
- toggle.src = this.opts.imgDir + '/' + nodeToggle[0];
+ toggle.src = nodeToggle[0];
toggle.alt = nodeToggle[1];
}
$tabs->addTab(_("Sea_rch"), $sidebar_url, 'search');
/* Set up the tree. */
- $tree = Horde_Tree::factory('horde_menu', 'Javascript');
+ $tree = $injector->getInstance('Horde_Tree')->getTree('horde_menu', 'Javascript');
$tree->setOption(array('target' => 'help_main'));
$contents = '';
}
/* Tree styles. */
+.treeIcon {
+ padding-right: 5px;
+}
.treeRow {
overflow: hidden;
min-height: 20px;
clear: both;
}
+.treeToggle {
+ cursor: pointer;
+}
/* Menu styles. */
#menu {
$folders = array();
}
- $tree = Horde_Tree::factory('folder_select', 'select');
+ $tree = $GLOBALS['injector']->getInstance('Horde_Tree')->getTree('folder_select', 'Select');
foreach ($folders as $folder_name => $folder) {
/* Selected or not? */
if (!is_a($folders, 'PEAR_Error')) {
$params = array('icon' => 'folder.png',
'iconopen' => 'folderopen.png');
- $tree = Horde_Tree::factory('folder_tree', 'javascript', array('alternate' => true));
+ $tree = $GLOBALS['injector']->getInstance('Horde_Tree')->getTree('folder_tree', 'Javascript');
+ $tree->setOption(array('alternate' => true));
$expand = $prefs->getValue('expand_tree');
if ($expand == 'none') {
$expand = false;