From 3041544c31ae331eeee2aac4e8ab9f3edbd2eaa7 Mon Sep 17 00:00:00 2001 From: Silvio Date: Thu, 15 Oct 2009 17:40:53 -0300 Subject: Rewriting to be taxonomy-oriented --- jquery_drawer.module | 308 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 246 insertions(+), 62 deletions(-) diff --git a/jquery_drawer.module b/jquery_drawer.module index 7d3996a..adaa7bc 100644 --- a/jquery_drawer.module +++ b/jquery_drawer.module @@ -3,10 +3,10 @@ /** * @file - * Implementation of a Finder Dropdown Menu. + * Implementation of a jQuery Drawer. * - * This module implements the Finder Dropdown menu described - * at http://www.alistapart.com/articles/complexdynamiclists. + * This module implements the jQuery.drawer navigation menu + * from http://lib.metatype.jp/jquery_drawer/sample.html */ /** @@ -37,9 +37,10 @@ function jquery_drawer_block($op = 'list', $delta = 0, $edit = array()) { case 'configure': $form['jquery_drawer'] = array( '#type' => 'select', - '#title' => t('Select the menu to list'), - '#default_value' => variable_get('jquery_drawer', 'navigation:0'), - '#options' => menu_parent_options(menu_get_menus(), 0), + '#title' => t('Select the vocabulary to list'), + '#default_value' => variable_get('jquery_drawer', '1'), + // TODO: won't work with taxonomy_get_vocabularies() + '#options' => menu_parent_options(taxonomy_get_vocabularies(), 0), ); return $form; @@ -48,12 +49,26 @@ function jquery_drawer_block($op = 'list', $delta = 0, $edit = array()) { break; case 'view': - $menu = explode(':', variable_get('jquery_drawer', 'navigation:0')); + $menu = explode(':', variable_get('jquery_drawer', '1')); $block['content'] = theme('jquery_drawer', $menu[0], $menu[1]); return $block; } } +/** + * Implementation of hook_menu(); + */ +function jquery_drawer_menu() { + $items['jquery_drawer'] = array( + 'title' => 'jQuery Drawer', + 'description' => 'Displays content inside a jQuery Drawer.', + 'page callback' => 'jquery_drawer_page', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + return $items; +} + /** * Implementation of hook_theme(); */ @@ -78,96 +93,225 @@ function jquery_drawer_theme() { } /** - * Generate the menu. + * Drawer logic. */ function theme_jquery_drawer($menu_name, $mlid) { - $item_class = "jquery-drawer-menu-item"; - $sub_item_class = "jquery-drawer-sub-menu-item"; - - // Find menu item in the menu tree - - $menu_tree = menu_tree_all_data($menu_name); - $menu_link = menu_link_load($mlid); - - if ($mlid != 0) { - for ($i=1; $i<10; $i++) { - foreach ($menu_tree as $menu_item) { - if ($menu_item["link"]['mlid'] == $mlid) { - $menu = $menu_item['below']; - break 2; - } - else { - if ($menu_item["link"]['mlid'] == $menu_link['p'. $i]) { - $menu_tree = $menu_item['below']; - break; - } - } - } + // Get all terms from a given vocabulary + $vocabulary = variable_get('jquery_drawer', '1'); + $terms = jquery_drawer_taxonomy_get_tree($vocabulary); + + foreach ($terms as $term) { + // Just show parent terms + if (taxonomy_get_parents($term->tid) == array()) { + $menu[] = $term; } } - else { - $menu = $menu_tree; + + // Build the drawer + $output = jquery_drawer_build($menu); + return $output; +} + +/** + * Drawer rendering. + * + * @ingroup themeable + */ +function jquery_drawer_build($menu) { + + $output = ''; + $output .= '
'; + $output .= '
'; + return $output; + +} + +/** + * Menu callback. + */ +function jquery_drawer_page($tid = null) { + // First render all nodes whose parent is $term + + $output = ''; + $nodes = taxonomy_select_nodes(array($tid)); + + while ($node = db_fetch_object($nodes)) { + $link['title'] = $node->title; + $link['href'] = 'node/' . $node->nid; + $output .= theme('jquery_drawer_link', $link); } - // Don't display anything if the selected menu has no children + // Then render all nodes whose terms are children of $term + + $vocabulary = variable_get('jquery_drawer', '1'); + $terms = jquery_drawer_taxonomy_get_tree($vocabulary, $tid); - if (!$menu) { - return; + foreach ($terms as $term) { + $filter[] = $term->tid; } - // Backup active menu trail and set a new one + $query = 'SELECT node.nid, node.title, term_node.tid FROM {node} LEFT JOIN + {term_node} ON term_node.nid = node.nid WHERE term_node.tid IN (%s) + AND node.status = "1"'; - $active_menu_name = menu_get_active_menu_name(); - menu_set_active_menu_name($menu_name); + $result = db_query(db_rewrite_sql($query), implode(',', $filter)); - // Build table of mlid in the active trail + while ($node = db_fetch_object($result)) { + foreach ($terms as $term) { + // add nodes into the term + if ($node->tid == $term->tid) { + $term->nodes[] = $node; + } + // update an index of terms + $tree[$term->tid] = $term; + } + } - foreach (menu_set_active_trail() as $value) { - if ($value['mlid']) { - $trail[] = $value['mlid']; + // add children relationship just for terms present in the tree + foreach ($tree as $term) { + if ($term->parents[0] != 0 && isset($tree[$term->parents[0]])) { + $tree[$term->parents[0]]->children[] = $term->tid; } } - // Restore active menu trail + // build menu with hierarchy + foreach ($tree as $term) { + jquery_drawer_build_tree($tree, $term); + } - menu_set_active_menu_name($active_menu_name); + // format output + $output .= ''; - // Build the menus + // Display output + echo($output); - $output = jquery_drawer_build($menu); + // We need to exit here to avoid themeable output + exit(); +} - return $output; +function jquery_drawer_build_tree(&$tree, $term) { + if ($term->parents[0] != 0 && isset($tree[$term->parents[0]])) { + // is child + if (isset($term->children)) { + // is also parent, so go down one level + foreach($term->children as $child) { + jquery_drawer_build_tree($tree, $tree[$child]); + } + } + $tree[$term->parents[0]]->below[] = drupal_clone($term); + unset($tree[$term->tid]); + } } /** - * Build the Drawer. + * Recursively build the menu. * * @ingroup themeable */ -function jquery_drawer_build($menu) { +function jquery_drawer_menu_build($term) { - $output = ''; - $output .= '
'; - $output .= '
'; return $output; } +/** + * Build the Drawer. + * + * @TODO + * @ingroup themeable + */ +/*function jquery_drawer_show_items($term) { + + $tree = array(); + $terms = jquery_drawer_taxonomy_get_tree(JQUERY_DRAWER_VOC_ID); + $query = 'SELECT node.nid, node.title, term_node.tid FROM {node} LEFT JOIN + {term_node} ON term_node.nid = node.nid WHERE node.type = "story" + AND term_node.tid = "%d" AND node.status = "1")'; + $result = db_query(db_rewrite_sql($query), $term); + + while ($node = db_fetch_object($result)) { + foreach ($terms as $term) { + // add nodes into the term + if ($node->tid == $term->tid) { + $term->nodes[] = $node; + } + // update an index of terms + $tree[$term->tid] = $term; + } + } + + // add children relationship + foreach ($tree as $term) { + if ($term->parents[0] != 0) { + $tree[$term->parents[0]]->children[] = $term->tid; + } + } + + // build menu with hierarchy + foreach ($tree as $term) { + jquery_drawer_build_tree($tree, $term); + } + + // format output + $output = '
  • '. t('About') .'
  • '; + $output .= '
  • '. t('Location'); + $output .= '
  • '; + + return $output; +} + /** * Recursively build the menu. * * @ingroup themeable */ -function jquery_drawer_show_items($menu) { +/*function jquery_drawer_show_items($menu) { global $_jquery_drawer_id; @@ -198,12 +342,12 @@ function jquery_drawer_show_items($menu) { $output .= ''; return $output; -} +}*/ /** * Check whether a menu has at least one unhidden submenu. */ -function jquery_drawer_has_unhidden_submenu($menu = FALSE) { +/*function jquery_drawer_has_unhidden_submenu($menu = FALSE) { if ($menu == FALSE) { return FALSE; @@ -216,7 +360,7 @@ function jquery_drawer_has_unhidden_submenu($menu = FALSE) { } return FALSE; -} +}*/ /** * jQuery Drawer Javascript theme function. @@ -249,9 +393,49 @@ function theme_jquery_drawer_link($link) { $link['attributes']['rel'] = 'drw'; - $output = '
  • '; + $output = '
  • '; $output .= l($link['title'], $link['href'], array('attributes' => array('rel' => 'drw'))); $output .= '
  • '; return $output; } + +/** + * Version of taxonomy_get_tree() without caching. + */ +function jquery_drawer_taxonomy_get_tree($vid, $parent = 0, $depth = -1, $max_depth = NULL, $cache = FALSE) { + static $children, $parents, $terms; + + $depth++; + + // We can cache trees, so it's not CPU-intensive to call get_tree() on a term + // and its children, too. + if (!$cache && !isset($children[$vid])) { + $children[$vid] = array(); + + $result = db_query(db_rewrite_sql('SELECT t.tid, t.*, parent FROM {term_data} t INNER JOIN {term_hierarchy} h ON t.tid = h.tid WHERE t.vid = %d ORDER BY weight, name', 't', 'tid'), $vid); + while ($term = db_fetch_object($result)) { + $children[$vid][$term->parent][] = $term->tid; + $parents[$vid][$term->tid][] = $term->parent; + $terms[$vid][$term->tid] = $term; + } + } + + $max_depth = (is_null($max_depth)) ? count($children[$vid]) : $max_depth; + $tree = array(); + if ($max_depth > $depth && !empty($children[$vid][$parent])) { + foreach ($children[$vid][$parent] as $child) { + $term = drupal_clone($terms[$vid][$child]); + $term->depth = $depth; + // The "parent" attribute is not useful, as it would show one parent only. + unset($term->parent); + $term->parents = $parents[$vid][$child]; + $tree[] = $term; + if (!empty($children[$vid][$child])) { + $tree = array_merge($tree, taxonomy_get_tree($vid, $child, $depth, $max_depth)); + } + } + } + + return $tree; +} -- cgit v1.2.3