Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID

Using an app to generate the top navigation

edited August 2013 in Apps

How would I go about generating my top menu and dropdowns from an app? I'm pretty sure I've seen it discussed here but couldn't find it via googling site:elefantcms.com or the site's own search.

I want the top menu to be categories and the dropdowns to be subcategories, with some subcategories having sub-subcategories.

The site owner will be able to add and remove categories, subcategories, and sub-subcategories.

Comments

  • It would be pretty similar to my reply here:

    http://www.elefantcms.com/forum/discussion/961/bootstrap-navbar#Item_2

    Usually I create an app with the site's name and place any custom handlers in there. For example, apps/sitename/handlers/dropmenu.php would be a duplicate of apps/navigation/handlers/dropmenu.php that contains the customizations I need for my site.

    From there, it's just a matter of adding a conf/embed.php to the new app to list my custom handlers that should be exposed through the Dynamic Objects menu, then I can easily embed them anywhere I need to.

    Let me know if that makes sense. You may need a different dropmenu script on the client-side too, the one used by default probably won't work well for multiple levels of sub-menus.

  • Thanks. I'll try it and let you know.

  • Just to be contrary I did ./elefant build-app sitename twice and my console erupted in html and css, starting with <link rel='stylesheet' href='/apps/admin/css/debugger.css' /><h1>ErrorException: mkdir(): File exists</h1>

    It might be good in apps/cli/handlers/build-app.php and apps/cli/handlers/crud-app.php to make sure apps/sitename doesn't already exist.

    I ought to submit a pull request instead of telling you this...

  • A pull request would be awesome! :)

  • OK, it's on my list.

    Back to navigation -- would it make sense for my app to generate its own navigation.json file and for my handler to use that file for the tree?

  • Re-reading your initial post, if you're not using regular pages to generate the navigation structure, you could look at the Tree class that Navigation inherits from. Let me know if that's closer to what you need.

  • Yes, thanks, that looks like exactly what I need.

  • OK, this is probably obvious, but how do I tell my navigation handler to use my generated .json file?

  • You probably want to subclass it similarly to how Navigation does it:

    https://gist.github.com/jbroadway/6357687

  • I'm looking at the navigation documentation (http://api.elefantcms.com/visor/lib/Navigation) and trying to figure out how to add an id as well as a title to a node. The documentation says

    $node = $n->node ('blog');
    // {"data":"Blog","attr":{"id":"blog","sort":0}}
    

    How does it know the data is "Blog" and the id is "blog"? What if I want "Example Page" and "example-page"?

  • In the case of the Navigation class, it overrides the add() method to fetch titles when they're not provided:

    https://github.com/jbroadway/elefant/blob/master/apps/navigation/lib/Navigation.php#L75-L85

    In the Tree class, you can either pass an object to it or a string and here would be the results:

    $mytree->add ('example-page');
    // {"data":"example-page","attr":{"id":"example-page","sort":0}}
    
    $mytree->add ((object) array (
        'data' => 'Example Page',
        'attr' => (object) array (
            'id' => 'example-page',
            'sort' => 0
        )
    ));
    // {"data":"Example Page","attr":{"id":"example-page","sort":0}}
    

    Originally the underlying format was chosen based on our use of jsTree, but the latter example could certainly be cleaned up a bit. Perhaps this would be easier:

    $mytree->add ('example-page', false, 'Example Page');
    

    Where the parameters are $id, $parent, and $title to keep with the existing parameter ordering. I think I'll play with it and see about improving it a bit.

  • I just updated Tree to support both of these forms of add() now:

    $mytree->add (array (
        'data' => 'Example Page',
        'attr' => array (
            'id' => 'example-page',
            'sort' => 0
        )
    ));
    
    $mytree->add ('example-page', false, 'Example Page');
    

    The (object) casting is no longer needed, and the title can be passed as a third parameter instead too.

  • Wow, thank you! I'm having a hard time expressing my gratitude and appreciation.

  • Glad it helps! The old method was really ugly, so this was a needed improvement :)

  • edited August 2013

    It does seem better.

    I updated from github, but I'm getting an error. I haven't switched to using my generated navigation yet; this is just with {! navigation/top !}

      ErrorException: Declaration of Navigation::add() should be compatible
      with Tree::add($obj, $parent = false, $data = false)
    
    
          Debugger::handle_error (2048, "Declaration of Navigation::add()
          should be compatible with Tree::add($obj, $parent = false, $data =
          false)",
          "/path/to/apps/navigation/lib/Navigation.php",
          59, array(3))
    
    59 /path/to/apps/navigation/lib/Navigation.php
    
    57.| *     $n->save ();
    | 58.| */
    | 59.|class Navigation extends Tree {
    | 60.|    /**
    |
    61.|     * Constructor method. Decodes the navigation tree from the specified
    |
    
    
          require_once
          ("/path/to/apps/navigation/lib/Navigation.php")
    
    79 /path/to/lib/Autoloader.php
    
    77.|        $res = glob ('apps/*/{models,lib}/' . $class . '.php', GLOB_BRACE);
    | 78.|        if (is_array ($res) && count ($res) > 0) {
    | 79.|            require_once ($res[0]);
    | 80.|            return true;
    | 81.|        }
    |
    
    
          spl_autoload_call ("Navigation")
    
    98 /path/to/apps/navigation/lib/Link.php
    
    96.|        }
    | 97.|        if (self::$nav === null) {
    | 98.|            self::$nav = new Navigation ();
    | 99.|        }
    | 100.|        return self::$nav;
    |
    
    
          Link::nav ()
    
    9 /path/to/apps/navigation/handlers/section.php
    
    7.| */
    | 8.|
    | 9.|$n = Link::nav ();
    | 10.|$section = $n->node ($data['section']);
    | 11.|
    |
    
    
          require
          ("/path/to/apps/navigation/handlers/section.php")
    
    444 /path/to/lib/Controller.php
    
    442.|        // Run the handler and get its output
    | 443.|        ob_start ();
    | 444.|        $res = require ($handler);
    | 445.|        $out = ob_get_clean ();
    | 446.|        if (is_string ($res) && strlen ($res) > 0) {
    |
    
    
          Controller->handle ("apps/navigation/handlers/section.php", true,
          array(1))
    
    335 /path/to/lib/Controller.php
    
    333.|        }
    | 334.|
    | 335.|        return $c->handle ($handler, $internal, $data);
    | 336.|    }
    | 337.|
    |
    
    
          Controller->run ("navigation/section", array(1))
    
    25 /path/to/cache/revuu.php
    
    23.|            <h1 id="title">
    | 24.|                <nav id="signin" class="clearfix">
    |
    25.|                      <?php if (! User::require_login ()) { ?><?php echo $this->controller->run ('navigation/section', array ('section' => 'lighting')); ?><?php } else { ?><?php echo $this->controller->run ('navigation/section', array ('section' => 'surfaces')); ?><?php } ?>
    
    | 26.|                </nav>
    |
    27.|                <a href="/"><img src="/files/design/revuu.png" alt="<?php echo Template::sanitize (conf('General', 'site_name'), 'UTF-8'); ?>" width="162" height="115"></a>
    
    |
    
    
          require ("/path/to/cache/revuu.php")
    
    298 /path/to/lib/Template.php
    
    296.|        
    | 297.|        ob_start ();
    | 298.|        require ($cache);
    | 299.|        return ob_get_clean ();
    | 300.|    }
    |
    
    
          Template->render ("revuu", Page)
    
    146 /path/to/lib/Page.php
    
    144.|            return ($res) ? $res : $out;
    | 145.|        }
    | 146.|        $out = $tpl->render ($this->layout, $this);
    |
    147.|        $res = $controller->hook ('page/render', array ('html' => $out));
    | 148.|        return ($res) ? $res : $out;
    |
    
    
          Page->render (Template, Controller)
    
    158 /path/to/index.php
    
    156.| * compression if conf[General][compress_output] is true.
    | 157.| */
    | 158.|$out = $page->render ($tpl, $controller);
    |
    159.|if (extension_loaded ('zlib') && conf ('General', 'compress_output')) {
    | 160.|    $zlib_oc = ini_get ('zlib.output_compression');
    |
    
    
        Error Context
    
    |$class = "Navigation"; |
    
    |$orig = "Navigation"; |
    
    |$res = array (
        "apps/navigation/lib/Navigation.php"
    ); |
    
  • Thanks for catching that. Just pushed a fix to Github for that too.

  • Awesome.

Sign In or Register to comment.