joer80 Posted February 26, 2015 Share Posted February 26, 2015 I have a template called redirectPage.php and it only has one line of code. $session->redirect($page->redirectTo_URL); How would I go about telling this to open the link in a new window instead of the current one? (In my navigation if I want to link to a different address than itself, I set the page to this template and paste in the url into the redirectTo_URL field. I also want to add a checkbox for if it is a new window or not. To get my top level nav links, I search for this: $pages->find('parent=1, sort=sort') Thanks! Link to comment Share on other sites More sharing options...
apeisa Posted February 26, 2015 Share Posted February 26, 2015 You have to do the redirect with javascript (which is run in browser) instead of PHP which is run on server. Link to comment Share on other sites More sharing options...
joer80 Posted February 26, 2015 Author Share Posted February 26, 2015 It sounds like adding the javascript to pop open a new window to this template wouldnt work, because you will still have this page open also, which would be blank. Sounds like I just need to do it with a blank target before I get to this page/template? Link to comment Share on other sites More sharing options...
renobird Posted February 26, 2015 Share Posted February 26, 2015 What are you using to generate the navigation? custom code, or MarkupSimpleNavigation? Link to comment Share on other sites More sharing options...
joer80 Posted February 26, 2015 Author Share Posted February 26, 2015 Custom code that uses the bootstrap format. One query finds top level links by getting the children of the homepage $TopLevelNavLinks = $pages->find('parent=1, sort=sort'); And then I do a second query to loop through each of those $SecondLevelNavLinks = $pages->find("parent=$TopLevelNavLink->id, sort=sort"); Link to comment Share on other sites More sharing options...
renobird Posted February 26, 2015 Share Posted February 26, 2015 Add the new window checkbox to your template. If "new_window" = 1 add "target=blank" to your <a> tag on output. 1 Link to comment Share on other sites More sharing options...
joer80 Posted February 26, 2015 Author Share Posted February 26, 2015 Yeah, I will have to add it to all of my templates that can be in the nav though I think, as well as a url box to all templates. In the past, I just had one template that was a redirect template. I think this is my best option though... Just not as neat and clean. Link to comment Share on other sites More sharing options...
renobird Posted February 26, 2015 Share Posted February 26, 2015 I'm not sure I follow. If you have a "redirect" template with 2 fields: URL, New Window Each page that is just a redirect would use that template. So then you can change the output based on template and the value of the checkbox. Link to comment Share on other sites More sharing options...
joer80 Posted February 26, 2015 Author Share Posted February 26, 2015 Got you! Not sure why I was thinking all pages would need new window functionality. I am really only concerned with websites that link off my url. That should work! Thanks! Link to comment Share on other sites More sharing options...
renobird Posted February 26, 2015 Share Posted February 26, 2015 Written in browser, but something like: foreach ($TopLevelNavLinks as $p){ $url = $p->url; $title = $p->title; $attr = ''; if ($p->template == "redirect"){ $url = $p->redirect //redirect is the name of the URL field if($p->new_window == 1){ $attr = "target=blank"; } } echo "<li><a href='$url' $attr>$title</a></li>"; 2 Link to comment Share on other sites More sharing options...
renobird Posted February 26, 2015 Share Posted February 26, 2015 You should really check if the redirect field is empty, and if it is, then skip that page. Link to comment Share on other sites More sharing options...
renobird Posted February 26, 2015 Share Posted February 26, 2015 Here's a more complete answer. Tested and works as expected. function navList($items, $level = 1){ $max_levels = 2; $level == 1 ? $class = "parent" : $class = "child"; $out = ''; if ($level <= $max_levels){ $out = "<ul class='$class'>"; foreach ($items as $item){ $out .= navItem($item, $level); } $out .= "</ul>"; } $level++; // increment level each time this function is called. return $out; } function navItem($item, $level){ $url = $item->url; $attr = ''; if ($item->template == "redirect"){ if (trim($item->redirect) == "") return; // skip because the field is blank. $url = $item->redirect; if($item->new_window == 1){ $attr = "target=_blank"; } } $out = "<li><a href='$url' $attr>$item->title</a>"; if ($item->numChildren > 0){ $out .= navList($item->children(), $level + 1); // get recursive } $out .= "</li>"; return $out; } echo navList($p); No need to do anything other than get the top level nav items and set the $max_levels if different than 2. You can of course probably do all of this as easy/easier with MarkupSimpleNavigation, but it's not necessary if all you need is this. 4 Link to comment Share on other sites More sharing options...
renobird Posted February 26, 2015 Share Posted February 26, 2015 I changed the "solved" answer on this post, because I think the code above is a lot more universal. Link to comment Share on other sites More sharing options...
joer80 Posted February 26, 2015 Author Share Posted February 26, 2015 The reason why I do not do the $item->children method, is if someone has a database of products under a page tied to the navigation, it makes it a lot slower and uses more memory. Especially if there are thousands of products. ie. A layout using Home -> Inventory -> All Inventory -> Item1 would not be good. I noticed a huge speed boost when I went to 2 queries. (Bootstrap only supports 2 levels, so no need to go deeper.) Link to comment Share on other sites More sharing options...
joer80 Posted February 26, 2015 Author Share Posted February 26, 2015 This is what I am using right now to make bootstrap menus with active link colors and drop downs before I add the above new window redirect code: <?php $LogoImage = 'logo.png'; $NavColor = 'navbar-default'; //navbar-default or navbar-inverse //Make the menu //echo the starting code echo '<nav class="navbar ' . $NavColor . ' navbar-fixed-top" role="navigation"> <div class="container"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse-1"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="' . $config->urls->root . '"><img src="' . $config->urls->templates . 'images/' . $LogoImage . '" class="Logo" alt="' . $LocationPage->title . ' Logo" /></a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="navbar-collapse-1">'; echo '<div id="AboveNav"><i class="fa fa-phone"></i> ' . $LocationPage->Location_PhoneNumber_Switchboard . ' <i class="fa fa-flag"></i> ' . $LocationPage->Location_AddressStreet . ' ' . $LocationPage->Location_City . ', ' . $LocationPage->Location_StateAbrv . '</div><!-- -->'; echo '<ul class="nav navbar-nav navbar-right">'; //Make the top level links $TopLevelNavLinks = $pages->find('parent=1, sort=sort'); //add home link echo '<li><a href="/">Home</a></li>'; //could use $config->urls->root //Build Top Level Links foreach($TopLevelNavLinks as $TopLevelNavLink){ //Look up this top level link to build a drop down if it needs it $SecondLevelNavLinks = $pages->find("parent=$TopLevelNavLink->id, sort=sort"); $SecondLevelTotal = $SecondLevelNavLinks->getTotal(); //If I am on this page, add the active class if($page->id == $TopLevelNavLink->id){ $classTag = ' active'; } else { $classTag = ''; } //if there is atleast one sublink, put me in a dropdown if($SecondLevelTotal > 0){ //Dont make link take user to page. Instead, open a dropdown menu. echo '<li class="dropdown' . $classTag . '">'; echo '<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">' . $TopLevelNavLink->title . ' <span class="caret"></span></a>'; echo '<ul class="dropdown-menu" role="menu">'; //loop through the second level foreach($SecondLevelNavLinks as $SecondLevelNavLink){ //If I am on this page, add the active class if($page->id == $SecondLevelNavLink->id){ $classTag2ndlevel = ' class="active" '; } else { $classTag2ndlevel = ''; } echo '<li' . $classTag2ndlevel . '><a href="' . $SecondLevelNavLink->url . '">' . $SecondLevelNavLink->title . '</a></li>'; } echo '</ul>'; } else { //Make link take user to page echo '<li class="nodropdown' . $classTag . '"><a href="' . $TopLevelNavLink->url . '">' . $TopLevelNavLink->title . '</a></li>'; } } //end of built top level nav links //echo the ending code echo '</ul></div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav>'; ?> 1 Link to comment Share on other sites More sharing options...
renobird Posted February 26, 2015 Share Posted February 26, 2015 You can restrict it to one level, or you can also do $item->children($selector) to filter out certain template types. If you use markup cache for your menus, then it won't matter, the slowdown will be minor for the one view that retriggers the cache. That said, whatever works for you. I like to keep these things as dry as possible. Link to comment Share on other sites More sharing options...
joer80 Posted February 26, 2015 Author Share Posted February 26, 2015 Nice.. Can I tell it to only go 2 levels since that is all bootstrap supports? 1 Link to comment Share on other sites More sharing options...
renobird Posted February 26, 2015 Share Posted February 26, 2015 OK, I tested the code above and it works as expected. Link to comment Share on other sites More sharing options...
joer80 Posted February 26, 2015 Author Share Posted February 26, 2015 That is a handy addition! I would be curious if I did it this way, if it would still have the delay or not? Does it still pull all 2k pages and populate it into the $item var and this just doesn't loop through it anymore? I used to be about 3-5 seconds extra on all page loads but I can test it. But like you said, caching helps for most of the time.. Link to comment Share on other sites More sharing options...
renobird Posted February 26, 2015 Share Posted February 26, 2015 I just quickly built a menu using: $navItems = $pages->get("/")->children("template!=syllabi"); That creates a 2 level menu with 15 parents, and about 65 children. Without any markupCache total time: 0.6733 With MarkupCache total time: 0.0018 I tested them like so: $t = Debug::timer(); echo navList($p); echo Debug::timer($t); $t = Debug::timer(); $cache = $modules->get("MarkupCache"); if(!$data = $cache->get("menu-test")) { $data = navList($p); $cache->save($data); } echo $data; echo Debug::timer($t); 2 Link to comment Share on other sites More sharing options...
joer80 Posted February 26, 2015 Author Share Posted February 26, 2015 Very handy! Thanks for taking your time to look into all of this. I havn't even had the chance to add the checkbox logic and you have all of the sample code. I will use that timer code to start timing things on future snippets. 1 Link to comment Share on other sites More sharing options...
renobird Posted February 26, 2015 Share Posted February 26, 2015 MarkupCache clears at a default interval of an hour, but you can specify less time if you want. $cache->get("menu-test",120); // 2 minutes No worries, I suspect it will be useful to someone else as well, so I figured I'd leave a solid example here. 2 Link to comment Share on other sites More sharing options...
renobird Posted February 26, 2015 Share Posted February 26, 2015 I needed a break from a project I was stumped on, so here's a version that creates a bootstrap menu (at least the best I can tell, since I don't use bootstrap, I just went by your sample code). I stripped out a few of the things to make it more general, but you could easily use it to create your menu. Renders lightning fast here. <?php function navList($items, $level = 1){ $max_levels = 2; $level == 1 ? $attrs = 'class="nav navbar-nav navbar-right"' : $attrs = 'class="dropdown-menu" role="menu"'; $out = ''; if ($level <= $max_levels){ $out = "<ul $attrs'>"; foreach ($items as $item){ $out .= navItem($item, $level); } $out .= "</ul>"; } $level++; // increment level each time this function is called. return $out; } function navItem($item, $level){ $url = $item->url; $attrs = ''; $itemClass = 'nodropdown'; if ($item->template == "redirect"){ if (trim($item->redirect) == "") return; // skip because the field is blank. $url = $item->redirect; if($item->new_window == 1){ $attr = "target=_blank "; } } if ($item->numChildren()){ $itemClass = 'dropdown'; $attrs = 'class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false" '; } $out = "<li class='$itemClass'><a href='$url' $attrs>$item->title</a>"; if ($item->numChildren > 0){ $out .= navList($item->children(), $level + 1); // get recursive } $out .= "</li>"; return $out; } ?> <nav class="navbar navbar-fixed-top" role="navigation"> <div class="container"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse-1"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="<?=$config->urls->root;?>"><img src="" class="Logo" alt="Logo" /></a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="navbar-collapse-1"> <?php $cache = $modules->get("MarkupCache"); if(!$data = $cache->get("main-nav")) { $data = navList($pages->get("/")->children()); $cache->save($data); } echo $data; ?> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> 1 Link to comment Share on other sites More sharing options...
joer80 Posted February 26, 2015 Author Share Posted February 26, 2015 Nice! Link to comment Share on other sites More sharing options...
renobird Posted February 26, 2015 Share Posted February 26, 2015 The caveat here is that new pages won't be immediately added to the menu because of the markupCache. It's just cleared at the interval, not via page save. I haven't ever looked into it, but it might be possible to clear the markupCache from a hook. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now