<?php
// $Id: yuimenu.module,v 1.5.2.5 2008/11/20 17:23:55 bakyildiz Exp $

/*
 * Drupal Hizmetleri (drupalhizmetleri)
 * YUI component based module
 */


/**
 * Implementation of hook_help().
 */
function yuimenu_help($section) {
  switch ($section) {
    case 'admin/settings/modules#description':
      $output = t('YUI based drop down Menu.');
      break;
    case 'admin/settings/yuimenu':
      $output = t('<p>A module to have a css/javascript based drop down and javascript based pop-up menu for site navigation.</p>', array('!link' => l('admin/build/block', 'admin/build/block')));
      break;
  }
  return $output;
}

/**
 * Settings form as implemented by hook_admin
 */
function yuimenu_admin() {
  $form['yuimenu_root'] = array(
    '#type' => 'select',
    '#title' => t('Root of Menu Tree'),
    '#description' => t('Select the root item of menu tree.'),
    '#default_value' => variable_get('yuimenu_root','1'),
    '#options' => menu_parent_options(menu_get_menus(), 0),
  );

  $form['yuimenu_type'] = array(
    '#type' => 'select',
    '#title' => t('Menu Display type'),
    '#description' => t('Select the display type of the menu.'),
    '#default_value' => variable_get('yuimenu_type','tna'),
    '#options' => array('tns' => t('Website Top  Nav With Submenus From JavaScript'),
						'tnm' => t('Website Top  Nav With Submenus Built From Markup'),
						'lns' => t('Website Left Nav With Submenus From JavaScript'))
  );

  $form['yuimenu_animate'] = array(
    '#type' => 'checkbox',
    '#title' => t('Animated Menu'),
    '#description' => t('To enable animation while opening menu check this.'),
    '#default_value' => variable_get('yuimenu_animate',0),
  );
  
  $form['yuimenu_setid'] = array(
	'#type' => 'textfield',
	'#title' => t('Menu DIV ID'),
    '#description' => t('Define your own Menu ID (optional, for CSS)'),
    '#default_value' => variable_get('yuimenu_setid', 'productsandservices')
  );
  return system_settings_form($form);
}


/**
 * Implemention of init().
 */
function yuimenu_init() {
  $yui_source = variable_get('yui_source','http://yui.yahooapis.com/2.5.0');
  // the order of script and style sheet is important. Don't change.
  yui_add_js('menu', $yui_source, '/build/yahoo-dom-event/yahoo-dom-event.js');
  if (variable_get('yuimenu_animate',0))
  {
    yui_add_js('menu', $yui_source, '/build/animation/animation-min.js');
  }
  yui_add_css('menu', $yui_source, '/build/menu/assets/skins/sam/menu.css');
  yui_add_js('menu', $yui_source, '/build/container/container_core-min.js');
  yui_add_js('menu', $yui_source, '/build/menu/menu-min.js');

  switch (variable_get('yuimenu_type','tns')) {
    case 'tns':
      $script_body_to_html_head =  get_yui_top_script();
      break;
    case 'tnm':
      $script_body_to_html_head =  get_yui_top_markup();
      break;
    case 'lns':
      $script_body_to_html_head =  get_yui_left_script();
      break;
  }
  drupal_set_html_head($script_body_to_html_head);
  //drupal_add_css(drupal_get_path('module', 'yuimenu')  .'/yuimenu.css');
}

/**
 * Implemention of hook_menu().
 */
function yuimenu_menu() {
  $items['admin/settings/yuimenu'] = array(
    'title' => t('YUI Menu Settings'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('yuimenu_admin'),
    'access arguments' => array('administer site configuration'),
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}


/**
 * Generate js code for top markup style menu.
 */
function get_yui_top_markup () {
  $scr = '	<script type="text/javascript">
			      //<![CDATA[
            //Initialize and render the menu bar when it is available in the DOM
            YAHOO.util.Event.onContentReady("'. variable_get('yuimenu_setid','productsandservices') .'", function () {
                ';
  if (variable_get('yuimenu_animate',0)) {
    $scr .= get_ani_scr();
  }
  $scr.= 'var oMenuBar = new YAHOO.widget.MenuBar("'. variable_get('yuimenu_setid','productsandservices') .'", { autosubmenudisplay: true, hidedelay: 750, lazyload: true });';
  if (variable_get('yuimenu_animate',0)) {
    $scr .='    oMenuBar.subscribe("beforeShow", onSubmenuBeforeShow);
                oMenuBar.subscribe("show", onSubmenuShow);';
  }
  $scr .='oMenuBar.render();});
          //]]>
          </script>';
  return ($scr);
}


/**
 * Generate js code for top script style menu.
 */
function get_yui_top_script () {
  $scr = '<script type="text/javascript">
            //<![CDATA[
            // Initialize and render the menu bar when it is available in the DOM
            YAHOO.util.Event.onContentReady("'. variable_get('yuimenu_setid','productsandservices') .'", function () {
            ';
  $scr.= 'var oMenuBar = new YAHOO.widget.MenuBar("'. variable_get('yuimenu_setid','productsandservices') .'", { 
                                                            autosubmenudisplay: true, 
                                                            hidedelay: 750, 
                                                            lazyload: true });
          var oSubmenuData = [
          '.
  create_menu(variable_get('yuimenu_root','navigation:0') ).'
          ];';
  if (variable_get('yuimenu_animate',0)){
    $scr .= get_ani_scr();
  }        
  $scr .= 'oMenuBar.subscribe("beforeRender", function () {
                    if (this.getRoot() == this) {';
                    
  $scr.= script_menu(variable_get('yuimenu_root','navigation:0') );
  
  $scr .='}});';
  if (variable_get('yuimenu_animate',0)){
    $scr .=' oMenuBar.subscribe("beforeShow", onSubmenuBeforeShow);
                oMenuBar.subscribe("show", onSubmenuShow);';
  }
  $scr .="\n".'oMenuBar.render();            
            });
            //]]>
            </script>';
  return ($scr);
}

/**
 * when menu has a " or ' the script is fails. So replace them.
 * @param $inStr
 *   Input string to replace. 
 */
function rep_char ($inStr) {
  $fromChar= array("\"","\\");
  $toChar  = array("'","-");
  $outStr = str_replace($fromChar, $toChar, $inStr);
  return ($outStr);
  //return t($inStr);
}

/**
 * Generate js code for top markup style menu.
 * @param $menu_id
 *   Root menu id for composing the menu. 
 */
function html_menu($menu_id = 'navigation:0') {
  switch (variable_get('yuimenu_type','tns')) {
    case 'tns' :
      $output =  get_html_menu_script($menu_id);
      break;
    case 'lns' :
      $output =  get_html_menu_script($menu_id);
      break;
    case 'tnm' :
      $output =  get_html_menu_markup($menu_id);
      break;

  }
  return $output;
}

/**
 * Generate html code for script style menu.
 * @param $menu_id
 *   Root menu id for composing the menu.  
 */
function get_html_menu_script ($menu_id) {
  $output .='
            <!-- YUI Menu div-->
            <div id="'. variable_get('yuimenu_setid','productsandservices') .'" class="'. (("tns" == variable_get('yuimenu_type','tns') || "tnm"==variable_get('yuimenu_type','tns'))? "yuimenubar yuimenubarnav":"yuimenu") .'">
              <div class="bd">
                <ul  style="text-decoration:none" class="first-of-type">';
  $menu = load_menu($menu_id);
  foreach ($menu as $menu_item) {
    $mlid = $menu_item['link']['mlid'];
    if ($menu_item['link']['hidden'] == 0) {
      $output .= '<li  class="'.(("tns" == variable_get('yuimenu_type','tns') || "tnm"==variable_get('yuimenu_type','tns'))? "yuimenubaritem":"yuimenuitem").'">'. l($menu_item['link']['title'], $menu_item['link']['href'],array('attributes' => array('class'=>(("tns" == variable_get('yuimenu_type','tns') || "tnm"==variable_get('yuimenu_type','tns'))? "yuimenubaritemlabel":"yuimenuitemlabel"))))."</li>";
    }
  }
  $output .='</ul>
          </div>
       </div>';
  return $output;
}

/**
 * Generate menu as script.
 * @param $menu_id
 *   Root menu id for composing the menu.  
 */
function script_menu($menu_id) {
  $menu = load_menu($menu_id);
  
  $i=0;
  foreach ($menu as $menu_item) {
    $mlid = $menu_item['link']['mlid'];
    if ($menu_item['link']['hidden'] == 0) {
      if ($menu_item['link']['has_children'] != 0)
      {
        $output .= 'this.getItem('. $i .').cfg.setProperty("submenu", oSubmenuData['.$i.']);'."\n";
      }
      $i++;
    }
  }

  return $output;
}

/**
 * Generate root items as markup menu.
 * @param $menu_id
 *   Root menu id for composing the menu.  
 */
function get_html_menu_markup ($menu_id) {
  $output .='
  <!-- YUI Menu div-->
	<div id="'. variable_get('yuimenu_setid','productsandservices') .'" class="yuimenubar yuimenubarnav">
      <div class="bd">
	    <ul  class="first-of-type">';
  list($menu_name, $mlid) = explode(':', $menu_id);
  $output .= compose_markap_body_tree($menu_name, $mlid);
  $output .=' </ul>
      </div>
    </div>';
  return $output;
}

/**
 * Generate tree of markup style menu.
 * @param $menu_name
 *   menu name  
 * @param $mlid
 *   menu id.  
 * @param $menu
 *   menu.    
 */
function compose_markap_body_tree($menu_name, $mlid = NULL, $menu = NULL) {
  $menu = load_menu($menu_name.':'.$mlid);
  if ($menu) {
    $output .= compose_markap_body($menu);
  }
  return $output;
}

/**
 * Generate root menu items as markup.
 * @param $menu
 *   Menu items to compose body.  
 */
function compose_markap_body($menu) {
  $output = '';  
  foreach ($menu as $menu_item) {
    $mlid = $menu_item['link']['mlid'];
    // Check to see if it is a visible menu item.
    if ($menu_item['link']['hidden'] == 0) {
      // Build class name based on menu path 
      // e.g. to give each menu item individual style.
      // Strip funny symbols.
  //BA    $clean_path = str_replace(array('http://', '<', '>', '&', '=', '?', ':'), '', $menu_item['link']['href']);
      // Convert slashes to dashes.
  //BA    $clean_path = str_replace('/', '-', $clean_path);
  //BA    $path_class = 'menu-path-'. $clean_path;
      // If it has children build a nice little tree under it.
      if (is_menu_child_of_root($menu_item['link']['plid']))
      {
        $yuiliclass = 'yuimenubaritem';
        $yuihrefclass = 'yuimenubaritemlabel';          
      }
      if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below']))) {
        // Keep passing children into the function 'til we get them all.
        $children = compose_markap_body($menu_item['below']);
        // Build the child UL.
        $output .= '<li class="'.$yuiliclass.'">'. l($menu_item['link']['title'], $menu_item['link']['href'],array('attributes' => array('class'=>$yuihrefclass)));
        $output .= '<div id="'.$menu_item['link']['title'].'" class="yuimenu">
                     <div class="bd">
                     <ul>'."\n";
        
        $output .= $children;                     
        $output .= "</ul>
                </div>
            </div></li>\n";
      }
      else {
        $output .= '<li class="'.$yuiliclass.'">'. l($menu_item['link']['title'], $menu_item['link']['href'],array('attributes' => array('class'=>$yuihrefclass))) .'</li>'."\n";
      }
    }
  }
  return $output;
}


/**
 * Check whether the current menu item is the child of the current menu item.
 * @param $plid
 *   child menu item.  
 */
function is_menu_child_of_root ($plid) {
  list($root_menu_name, $root_mlid) = explode(':', variable_get('yuimenu_root','navigation:0'));
  if ($plid == $root_mlid)
    return true;
  return false;
}

/**
 * Start to compose the menu.
 * @param $menu_id
 *   Root menu id for composing the menu.  
 */
function create_menu($menu_id) {

  $menu = load_menu($menu_id);
  $j=1;
  foreach ($menu as $menu_item) {
    if ($menu_item['link']['hidden'] == 0)
    {
      $mlid = $menu_item['link']['mlid'];
      $output .=	"\n{\n".'id: "' . rep_char($menu_item['link']['title']) . '",'."\nitemdata: [\n";
      if ($menu_item['link']['has_children'] > 0) {
        $output .= create_inner_menu($menu_item['link']['menu_name'].':'.$mlid); 
      }
      $output .=  ']}'.($j++<count($menu)?',':'');
    }
    
  }
  return $output;
}

/**
 * Load menu with the given menu id.
 * @param $menu_id
 *   Root menu id for composing the menu.  
 */
function load_menu($menu_id)
{
  list($menu_name, $mlid) = explode(':', $menu_id);
  $menu = isset($menu) ? $menu : menu_tree_all_data($menu_name);
  
  if (!empty($mlid)) {
    // Load the parent menu item.
    $item = menu_link_load($mlid);
    $title = $item['title'];
    // Narrow down the full menu to the specific sub-tree we need.
    for ($p = 1; $p < 10; $p++) {
      if ($sub_mlid = $item["p$p"]) {
        $subitem = menu_link_load($sub_mlid);
        // Menu sets these ghetto-ass keys in _menu_tree_check_access().
        $menu = $menu[(50000 + $subitem['weight']) .' '. $subitem['title'] .' '. $subitem['mlid']]['below'];
      }
    }
  }
  return $menu;
}

/**
 * Compose the submenu of the root menu item.
 * @param $menu_id
 *   Root menu id for composing the menu.  
 */
function create_inner_menu($menu_id) {
  $menu = load_menu($menu_id);
  $j=1; 
  foreach ($menu as $menu_item) {
    $mlid = $menu_item['link']['mlid'];
    if ($menu_item['link']['hidden'] == 0) {
      if ($menu_item['link']['has_children'] > 0) {
        $output .= "{ text: \"".rep_char($menu_item['link']['title'])."\",url: \"".url(rep_char($menu_item['link']['href']))."\", submenu: { id: \"".url(rep_char($menu_item['link']['title']))."\", itemdata: [\n";
        $output .= create_inner_menu($menu_item['link']['menu_name'].':'.$mlid);
        $output .= "]}}".($j++<count($menu)?',':'');
      }
      else {
          $output .= "{ text: \"".rep_char($menu_item['link']['title'])."\", url: \"".url(rep_char($menu_item['link']['href']))."\" }".($j++<count($menu)?',':'')."\n";
      }
    }
  }
  return $output;
}

/**
 * Hard coded animation script to add the html body in case of the animation option is selected. 
 */
function get_ani_scr()
{
  return
               'var ua = YAHOO.env.ua,
                    oAnim;  // Animation instance
                function onSubmenuBeforeShow(p_sType, p_sArgs) {
                    var oBody,
                        oElement,
                        oShadow,
                        oUL;
                    if (this.parent) {
                        oElement = this.element;
                        oShadow = oElement.lastChild;
                        oShadow.style.height = "0px";
                        if (oAnim && oAnim.isAnimated()) {
                            oAnim.stop();
                            oAnim = null;
                        }
                        oBody = this.body;
                        //  Check if the menu is a submenu of a submenu.
                        if (this.parent && 
                            !(this.parent instanceof YAHOO.widget.MenuBarItem)) {
                            if (ua.gecko) {
                                oBody.style.width = oBody.clientWidth + "px";
                            }
                            if (ua.ie == 7) {
                                oElement.style.width = oElement.clientWidth + "px";
                            }
                        }
                        oBody.style.overflow = "hidden";
                        oUL = oBody.getElementsByTagName("ul")[0];
                        oUL.style.marginTop = ("-" + oUL.offsetHeight + "px");
                    }
                }

               function onTween(p_sType, p_aArgs, p_oShadow) {
                    if (this.cfg.getProperty("iframe")) {
                        this.syncIframe();
                    }
                    if (p_oShadow) {
                        p_oShadow.style.height = this.element.offsetHeight + "px";
                    }
                }
                function onAnimationComplete(p_sType, p_aArgs, p_oShadow) {
                    var oBody = this.body,
                        oUL = oBody.getElementsByTagName("ul")[0];
                    if (p_oShadow) {
                        p_oShadow.style.height = this.element.offsetHeight + "px";
                    }
                    oUL.style.marginTop = "";
                    oBody.style.overflow = "";
                    //  Check if the menu is a submenu of a submenu.
                    if (this.parent && 
                        !(this.parent instanceof YAHOO.widget.MenuBarItem)) {
                        // Clear widths set by the "beforeshow" event handler
                        if (ua.gecko) {
                            oBody.style.width = "";
                        }
                        if (ua.ie == 7) {
                            this.element.style.width = "";
                        }
                    }
                }
                function onSubmenuShow(p_sType, p_sArgs) {
                    var oElement,
                        oShadow,
                        oUL;
                    if (this.parent) {
                        oElement = this.element;
                        oShadow = oElement.lastChild;
                        oUL = this.body.getElementsByTagName("ul")[0];
                        oAnim = new YAHOO.util.Anim(oUL, 
                            { marginTop: { to: 0 } },
                            .5, YAHOO.util.Easing.easeOut);
                        oAnim.onStart.subscribe(function () {
                            oShadow.style.height = "100%";
                        });
                        oAnim.animate();
                        if (YAHOO.env.ua.ie) {
                            oShadow.style.height = oElement.offsetHeight + "px";
                            oAnim.onTween.subscribe(onTween, oShadow, this);
                        }
                        oAnim.onComplete.subscribe(onAnimationComplete, oShadow, this);
                    }
                }';
}

/**
 * Implementation of hook_block().
 *
 * Displays the menu in select block
 */
function yuimenu_block($op='list', $delta=0) {
  global $user;

  if ('lns' == variable_get('yuimenu_type','tns'))
  {
    // listing of blocks, such as on the admin/block page
    if ($op == "list") {
      $block[0]["info"] = t("YUI Menu");
      return $block;
    } else if ($op == 'view') {
      // our block content
      // content variable that will be returned for display
      $block_content = '<div id="yuimenu" class="yui-b">';
      $block_content .= html_menu(variable_get('yuimenu_root','navigation:0'));
      $block_content .= '</div>';

      $block['subject'] = $user->name;
      $block['content'] = $block_content;
      return $block;
    }
  }
}

/**
 * Compose the left menu script.
 */
function get_yui_left_script () {
  $scr = '<script type="text/javascript">
            //<![CDATA[
            // Initialize and render the menu when it is available in the DOM

            YAHOO.util.Event.onContentReady("'. variable_get('yuimenu_setid','productsandservices') .'", function () {
            
            
             var oMenu = new YAHOO.widget.Menu("'. variable_get('yuimenu_setid','productsandservices') .'", { 
                                                        position: "static", 
                                                        hidedelay:  750, 
                                                        lazyload: true';

  if (variable_get('yuimenu_animate',0))
  {
    $scr .= ',effect: {effect: YAHOO.widget.ContainerEffect.FADE,duration: 0.25}';
  }
  $scr .= '});
          var oSubmenuData = [
          '.
  create_menu(variable_get('yuimenu_root','navigation:0') ).'];';
   $scr .= 'oMenu.subscribe("beforeRender", function () {
                    if (this.getRoot() == this) {';
                    
  
  $scr.= script_menu(variable_get('yuimenu_root','navigation:0') );
  
  $scr .='}});';
  $scr .="\n".'oMenu.render();
            });
            //]]>
            </script>';
  return ($scr);
}
