If you go to www.lindysez.com and click on the top level navigation links, you'll notice that position presence is indicated by a slightly darker background (same as hover state). This works for each of the links EXCEPT "Tips & Techniques".
If I look under the hood, I noticed that the "current_page_item" class isn't being added to the parent of the "Tips & Techniques" menu item when you go to http://www.lindysez.com/tips
Also, curiously enough, when on the tips page, the parent of the "Blog" navigation item gets the class "current_page_parent", which is neither expected nor desired. This is harmless from a UI standpoint, but probably an indication what the underlying problem might be.
Anyone know why the "Tips & Techniques" menu item isn't getting the "current_page_item" class once selected?
Update: Directed #user2019515's comment below
Thanks for the nudge in this direction, it does seem like I could create a workaround that would fix this. Couple things however.
This treats the symptom of the problem rather than the root. I'd like to figure out how to get wp to just add the "current_page_item" class natively. Any idea what's causing this? I think it may also be related to another problem I'm having which involves "tips" not showing in the RSS feed. I posted another question about that, but haven't seen any answers...
https://stackoverflow.com/questions/15980846/custom-post-type-not-showing-up-in-wordpress-rss-feed
Even as a workaround, I'd rather try to avoid a solution that relies on hard coded "menu-item-##". My development and production servers both have different ID#'s. I know I can account for this, but I hope there's a better, scalable workaround.
The code you provided didn't work for me, not that I can find any fault in it, nor are there any errors. Seems like it should work, but just doesn't. I even tried creating a very simple version that would add a class to all the items, but this too isn't executing. Here's that code.
function add_class_to_wp_nav_menu($classes, $item)
{
$classes[] = 'classy-class';
return $classes;
}
add_filter('nav_menu_css_class', 'add_class_to_wp_nav_menu', 10, 2);
Thanks so much for your help!
The Tips page is a post archive page, it shows posts rather than a normal page that's why the blog was being highlighted. You can easily fix this issue by adding the following custom CSS to your style.css file.
.post-type-archive-tips .menu-item-23{
background:url(images/nav-hover.png) repeat-x;
}
You'll need to loop over your menu, by default the current page class is added to the blog page because in the end the custom posts.
//Change current_page_parent for custom post type
function remove_parent_classes($class)
{
// check for current page classes, return false if they exist.
return ($class == 'current_page_item' || $class == 'current_page_parent' || $class == 'current_page_ancestor' || $class == 'current-menu-item') ? FALSE : TRUE;
}
function add_class_to_wp_nav_menu($classes)
{
switch (get_post_type()) {
case 'portfolio':
// we're viewing a custom post type, so remove the 'current_page_xxx and current-menu-item' from all menu items.
$classes = array_filter($classes, "remove_parent_classes");
// add the current page class to a specific menu item (replace ###).
if (in_array('menu-item-14', $classes)) {
$classes[] = 'current_page_parent';
}
break;
case 'tips':
// we're viewing a custom post type, so remove the 'current_page_xxx and current-menu-item' from all menu items.
$classes = array_filter($classes, "remove_parent_classes");
// add the current page class to a specific menu item (replace ###).
if (in_array('menu-item-23', $classes)) {
$classes[] = 'current_page_parent';
}
break;
}
return $classes;
}
add_filter('nav_menu_css_class', 'add_class_to_wp_nav_menu');
There's just one custom post type in the function, but I'm sure you can figure out how to add more. Got any questions, feel free to leave a comment! :)
Related
I'm using apache velocity in a web application (just for experimentation and practice)
for example:
<input id="limited" type="checkbox"> <strong>Limited view</strong>
so I need a code which would be... if the checkbox above is checked then do this:
#foreach( $customer in $customerList )
#if( $velocityCount > 5 )
#break
#end
$customer.Name
#end
else then don't break it
is that kind of syntax possible?
and if yes then can you show me how?
please no rude comments, I'm just trying to learn... can anyone help?
It seems you wish to get Velocity to instantly react on someones click, right?
This wouldn't work (without further effort, that is), because the Velocity template is rendered server sided. Your Velocity code would never 'notice' the click, as it is done on the client side. At least not in the same request, but I come to that later.
Furthermore Velocity isn't able to directly access the value of the checkbox, meaning there is no such thing as limited.isChecked().
So, first thing you need is a backing (form) object, where you evaluate and keep the status of your checkbox. Should be no problem, as you managed to provide the object $customerList. The checkbox status should be represented by a boolean var, say limitedView, so that you can write:
#foreach( $customer in $customerList )
#if($velocityCount > 5 && $yourBackingObject.isLimitedView())
#break
...
(Please see Breaking out of a foreach loop in Velocity, if you face problems with the #break instruction.)
If you actually need to show the shortened list immediately, then refresh (part of) the page using JavaScript/Ajax. This new request is what you need to update your backing object and to render the template again.
Edit:
Or even simpler (but a little outside of Veloctiy and depending on JavaScript) provide both lists in two different containers in the page, like <div>, and toggle the css class on a click at the checkbox so that one on of the two is always invisible.
.vm:
<div id="listLength">
#foreach( $customer in $customerList )
#if($velocityCount > 5)
#break
...
</div>
<div id="listLengthToggler">
#foreach( $customer in $customerList )
...
</div>
.css
div#listLengthToggler,
div#listLength {
... /* general styles for classes */
display: none;
}
div#listLengthToggler {
display: block;
}
.js
$(document).ready(
function() {
$('div#listLengthToggler').click(
function() {
$('div#listLength').slideToggle('slow');
}
);
}
);
Get http://code.jquery.com/jquery-2.1.4.min.js
You add a line that says 'Click to expand!' and 'Click to collapse!', respectively inside each div and get rid of the checkbox or adapt the JavaScript so the toggling starts on a click on it.
Bit of a mystery to me this, but I have a table in libgdx where everything is being positioned in new cells vertically;
I am not using .row() anywhere.
Probably doing something stupid here but I cant see it.
Clues as to what can cause this?
(I'll post the code if needed, but its not that neat, and seeing as I think knowing anything that can cause a newline will help me, it shouldn't necessarily be needed)
edit
Tried to cut the code down to all the bits that happen when an item gets added
Code;
//function that triggers on adding
//SSSNode is a semantic reference for the items details,it just justs made into a label like object
public void addItem(SSSNode itemsnode){
Item newitem = new Item(itemsnode); //Item extends label
allItems.add(newitem);
super.add(newitem).size(60, 30).top().left().fillY().expandY();
//pack();
//super.invalidate();
//super.validate(); (tried doing pack, validate, and none...neither helped)
//update the GUI bar in case the inventory tab isnt there yet
MainExplorationView.usersGUI.setDataVisible(true);
}
The following code is in "usersGUI", which creates and handles the popup called inventory which is whats in the picture and is the table I cant get to behave.
//ensures the interface for the inventory popup is setup and visible
//also refreshes the links
public void setDataVisible(boolean visible){
if (myContents.isVisible!=true){
myContents.isVisible=visible;
refreshlinks();
setupInventory();
}
}
private void refreshlinks() {
super.clearChildren();
super.addActor(backgroundobject);
super.addActor(ME.playersInventory); //re adds the inventory panel table?
int y = 440;
ME.playersInventory.validate(); //revalidated the table (I dumped this almost everywhere in frustration)
//below is not relevant, it updates other items in a onscreen gui
for (InterfaceButton link : allLinks) {
if (link.isVisible==true){
link.setPosition(5,y);
super.addActor(link);
y=y-30;
}
}
backgroundobject.setSize(85, 200);
backgroundobject.setPosition(0,y+20);
}
//ensures inventory is setup once.
public void setupInventory() {
if (setup){
return;
}
Log.info("setupInventory");
ME.playersInventory.setPrefWidth(super.getWidth());
Log.info("width is "+super.getWidth());
ME.playersInventory.setHeight(200);
ME.playersInventory.pack();
float X = myContents.getX();
float Y = myContents.getY()-ME.playersInventory.getHeight();
Log.info("popping up inventory at:"+X+","+Y);
ME.playersInventory.setPosition(X, Y);
super.validate();
setup=true;
}
The full code is also on GitHub;
https://github.com/ThomasWrobel/MeshExplorerGDX
The whole project is a game being made to demo/test and open source distributed semantic database system. The relevant bit is the inventory and the maybe the gui that creates it.
Anyone with good knowledge of LibGDXs workings should I think not need to look any of the code though if theres other things that can tell a table to start a new row. (ie, any layout restrictions that can cause it to happen automatically? )
layout ending the current row was a side effect to make the layout logic simpler. It is now fixed.
Note HorizontalGroup is still a better fit for your use case and has the benefit that you can add/remove actors at any index.
The answer seems to be that layout() causes new rows;
http://www.badlogicgames.com/forum/viewtopic.php?f=11&t=15857&p=68533&hilit=layout#p68533
Adherently this is how its supposed to work, despite the docs not saying that.
Introduce the Problem
I would like to profoundly modify the layout of the Orchard CMS Tags list.
Here is an example page with Shape Tracing enabled.
The only alternate that it suggests for the List shape is ~/Themes/TheThemeMachine/Views/List.cshtml, because the page is rendering the default List shape. I would like to have other alternates that are specific to the page.
After reading Orchard list customization, I have been able to implement the default List.cshtml in razor. What I would like to do, though, is to add another alternate, such as ~/Themes/TheThemeMachine/Views/Parts.Tags.List.cshtml instead of implementing the default List.cshtml template.
The problem seems to be that the page is rendering the generic List shape.
In contrast, the blog post list page is rendering a Parts_Blogs_BlogPost_List shape, which means that a ~/Themes/TheThemeMachine/Views/Parts.Blogs.BlogPost.List.cshtml is available.
Search and Research
All quotes below are from the Orchard list customization blog post, which explains how to add a list item alternate (whereas I would like to add a list alternate).
What we really want is an alternate template... aptly called Shape
Alternates... [so] enable Shape Tracing... and select a post in the list...
[you will see that] we already have some possible alternates.
My example page also has some possible alternates for the List Content. Cool.
we need to somehow get into list rendering... [t]he default is defined
in code... [which] can be override by a new [cshtml] template in our
theme.
Okay. That makes sense. We can override the list rendering.
As Shape Tracing can show, we can override the list rendering for a
blog by creating a Parts.Blog.BlogPost.List.cshtml template.
This works for alog but not for the blog Tag page (example page). You see, the blog displays a **Parts_Blogs_BlogPost_List shape and suggests an appropriate alternate but the blog tags page displays the default List shape with no alternates other than List.cshtml.
Blog Page with alternates galore
Blog Tags Page with one alternate List.cshtml
So, I created a List.cshtml not a Parts.Blog.BlogPost.List.cshtml template, and save it in my theme's Views directory. (One problem here is that, once we get it working, we will b overriding the default List rendering.)
Then I add the Razor code (copy and pasted from Bertrand's post) to override the default rendering for Lists. When I refresh the site, the browser renders a blank page. It isn't working. Here's the code:
This Does NOT Work in List.cshtml
#using Orchard.DisplayManagement.Shapes;
#{
var list = Model.ContentItems;
var items = list.Items;
var count = items.Count;
var listTag = Tag(list, "ul");
listTag.AddCssClass("content-items");
listTag.AddCssClass("blog-posts");
var index = 0;
}
#listTag.StartElement
#foreach (var item in items) {
var itemTag = Tag(item, "li");
if (index == 0) {
itemTag.AddCssClass("first");
}
else if (index == count - 1) {
itemTag.AddCssClass("last");
}
#itemTag.StartElement
#Display(item)
#itemTag.EndElement
++index;
}
#listTag.EndElement
As a trouble shooting step, I replace the List.cshtml with <p>Hello world.</p>. Orchard renders the markup as expected. So, something is incompatible between the Razor code from Bertrand's blog and the Tags List.
To find out what exactly is incompatible, I try Betrand's code one line at time to see where it breaks (yup, VS would be better than WM here). At each change, I restart WebMatrix and view the results. This is the minimal code that breaks it.
The Culprit
#using Orchard.DisplayManagement.Shapes;
#{
var list = Model.ContentItems;
var items = list.Items;
}
list.Items isn't appropriate here. So I comment it out again and run the <p>Hello World</p> version again. Also, Shape Tracing reveals that on my Tags/tagname page, the Content Zone is now rendering the List twice. Is that normal?
As another step, I replace Model.ContentItems just with Model. It works. It seems that, to override the List.cshtml template, we cannot use the ContentItems property of Model. Here is the new, working code:
This Does Work in List.cshtml
#using Orchard.DisplayManagement.Shapes;
#{
//var list = Model.ContentItems;
//var items = list.Items;
var items = Model.Items;
var count = items.Count;
//var listTag = Tag(list, "ul");
var listTag = Tag(Model, "ul");
listTag.AddCssClass("content-items");
listTag.AddCssClass("blog-posts");
var index = 0;
}
#listTag.StartElement
#foreach (var item in items) {
var itemTag = Tag(item, "li");
if (index == 0) {
itemTag.AddCssClass("first");
}
else if (index == count - 1) {
itemTag.AddCssClass("last");
}
#itemTag.StartElement
#Display(item)
#itemTag.EndElement
++index;
}
#listTag.EndElement
Onward through the article.
So far so good, we have effectively taken over the rendering of the
list, but the actual HTML [will] be... identical to what we had before
[except for] the implementation.
Okay. I'm following. We want to modify the rendering not just re-implement it.
Alternates are a collection of strings that describe additional shape
names for the current shape... in the Metadata.Alternates property of any shape.
Gotcha. Now, why doesn't the Tags/tagname page show an alternate other than just List.cshtml for the rendering of the List shape?
All we need to do is add to this list [of alternates]... [and make sure] to respect the lifecycle...
Great. Maybe we can we add another alternate for the List shape on the Tags/tagname page. But, doing that is different from what Betrand is explaining. While Betrand's blog post is excellent, it is explaining how to add an alternate for an item, whereas I would like to add an alternate for the list.
The List.cshtml template is where I would add an alternate for a List Item as follows:
ShapeMetadata metadata = item.Metadata;
string alternate = metadata.Type + "_" +
metadata.DisplayType + "__" +
item.ContentItem.ContentType +
"_First";
metadata.OnDisplaying(ctx => {
metadata.Alternates.Add(alternate);
});
So that...
[t]he list of alternates from Shape Tracing now contains a new item.
Where and how, though, would I add an alternate for the List shape? Bertrand has recommended to check out the Shape Table Providers blog post for this. The quotes below are from that post.
But what if you want to change another shape template for specific
pages, for example the main Content shape on the home page?
This looks like a fit, because my example is the main List shape on the tags page. To do this we...
... handle an event that is triggered every time a shape named "Content"
[in our case "List"] is about to be displayed. [It] is implemented in a shape table provider which is where you do all shape related site-wide operations.
Great! Here is my implementation for adding another template for the main List shape.
TheThemeMachine > ListShapeProvider.cs
namespace Themes.TheThemeMachine
{
using Orchard.DisplayManagement.Descriptors;
public class ListShapeProvider : IShapeTableProvider
{
public void Discover(ShapeTableBuilder builder)
{
System.Diagnostics.Debugger.Break(); // break not hit
builder.Describe("List").OnDisplaying(displaying => {
// do stuff to the shape
displaying.ShapeMetadata.Alternates.Add("Tags__List");
});
}
}
}
The above builds and runs but does not hit the breakpoint nor add an alternate for the List shape on the /tags page. So I looked into the Orchard.Azure.MediaServices module and its CloudVideoPlayerShape which implements IShapeTableProvider. Its breakpoint does get hit. How is my code for ListShapeProvider fundamentally different than the code for the CloudVideoPlayerShape?
Also, I installed the Orchard.Themes.CustomLayoutMachine.1.0.nupkg as suggested in Bertrand's blog post. It unfortunately no longer contains an implementation of IShapeTableProvider.
I have also looked at this szmyd post, which does not explain where to put the IShapeTableProvider code.
Further, I installed the Contoso theme from the Orchard Gallery. It works and builds after adding a reference to Microsoft.CSharp. It also includes an implementation of the IShapeTableProvider. Hooray! Comparing its ContentShapeProvider with my ListShapeProvider reveals a subtle but important difference:
Contoso.csproj
<ItemGroup>
<Compile Include="Code\ContentShapeProvider.cs" />
</ItemGroup>
My implementation didn't include the .cs file in the compilation, because my theme has neither a .csproj nor a App_Code folder. So, I recreated my theme with the following code generation:
orchard.exe
feature enable Orchard.CodeGeneration
codegen theme My.FirstTheme /CreateProject:true
theme enable My.FirstTheme
feature enable Orchard.DesignerTools
When adding the ListShapeProvider.cs file, Visual Studio automatically added a ItemGroup/Compile entry for the file, which included the code in compilation. Hooray!
These two posts will help.
Shape Shifting
List Customization
Here are steps of my own minimum solution.
Download and unzip Orchard.Source.1.8.zip.
Open "\Downloads\Orchard.Source.1.8\src\Orchard.sln" in Visual Studio.
Build the solution to create orchard.exe.
Generate a new theme with orchard.exe. Use CreateProject:true because you will need a csproj to include your .cs file.
orchard.exe
setup /SiteName:SITE /AdminUsername:ME /AdminPassword:PWD /DatabaseProvider:SqlCe
feature enable Orchard.CodeGeneration
codegen theme My.FirstTheme /CreateProject:true
theme enable My.FirstTheme
In VS, add a ListShapeProvier.cs file to the root (or any folder) in your theme.
Add the following code to ListShapeProvider.cs.
namespace My.FirstTheme
{
using Orchard.DisplayManagement.Descriptors;
public class ListShapeProvider : IShapeTableProvider
{
public void Discover(ShapeTableBuilder builder)
{
System.Diagnostics.Debugger.Break();
// implementation here
}
}
}
Build the solution.
Run Orchard.Web.
Visual Studio will break at System.Diagnostics.Debugger.Break(). If it doesn't, go to the Orchard Dashboard and make My.FirstTheme the Current Theme.
Now read Shape Shifting to implement public void Discover(ShapeTableBuilder builder).
This post should give you a full response: http://weblogs.asp.net/bleroy/archive/2011/05/23/orchard-list-customization-first-item-template.aspx
Someone was able to so quickly help me with a problem I'd spent hours and hours on, that I'm hoping I'll get lucky and someone can point me in the right direction on this one, too.
I didn't see anyone else with quite my issue here - and I'm new to working with WP templates instead of plain old HTML/CSS/JS stuff.
Basically - on a site we did (www.opted.org) with a purchased WP theme - I can't get the mobile version collapsible menu to stop defaulting on page load to the last item in the Main Menu.
So instead of something that makes sense - like About ASCO, or even being able to add "Select Page" - the drop down shows "-- past issues"
I don't care how I fix it really, but the client just doesn't want that page to be the default. I tried adding an extra menu item at the end called "Select Page" with an href='#' and using CSS to hide it on screens above 480px - but I couldn't get it to work no matter how I tried to refer to it.
I feel like this should be easy - but I don't know where to set the selected LI among the many WP files.
Thanks!!
I had a look at the plugin.js file on the site www.opted.org.
On line 22, there is 'header' : false // Boolean: Show header instead of the active item
and on line 41 there is jQuery('<option/>').text('Navigation')
Try setting line 22 to true, and text('Navigation') to your 'Select Page' if you prefer that over the text 'Navigation'
Or, according to the tinynav.js page (http://tinynav.viljamis.com/), you can customize that as an option like this:
$("#nav").tinyNav({
active: 'selected', // String: Set the "active" class
header: 'Navigation', // String: Specify text for "header" and show header instead of the active item
label: '' // String: Sets the <label> text for the <select> (if not set, no label will be added)
});
In your main.js file, your calling it on line 14. You should add that header: 'Navigation', option there.
It's hard to answer this question without knowing how the theme you are using works. However, you can certainly change the selected attribute using javascript.
Here's the code you would use to set it to 'About Asco' using jQuery:
jQuery('.tinynav').val('/about-asco/')
alternatively (a little clearer, but more verbose):
jQuery('.tinynav option:first').prop('selected', true);
Is it possible to force the sitemap control to render the menu when the current action is not listed in the MVC.sitemap file?
I have a simple top nav. When the current action is in the sitemap, the call to .Menu() will render the correct <ul><li>.. data. However, if I got to a page that is not in the sitemap such as /Home/Login, then it will not render any html at all (not even a comment, just empty space). This isn't an [authorize] issue; the menu is fine when i'm in '/Home/Index'.
It seems like it should render what was requested, but just not set the IsCurrentNode and IsNodeInPath properties. Here is the call I am making
<div id="main-nav">
#Html.MvcSiteMap().Menu(0, true, true, 1)
</div>
The Mvc.sitemap file:
<mvcSiteMapNode title="Home" controller="Home" action="Index">
<mvcSiteMapNode title="Form New Human" controller="Person" action="Create"/>
<!-- there is no mvcSiteMapNode for "Home" "Login" -->
</mvcSiteMapNode>
Found the way around it. It apparently isn't a built in extension method, or at least I couldn't find one. You could call Html.MvcSitemap().Menu(Html.MvcSiteMap.Provider.RootNode,...) but I didn't want to instantiate the helper twice.
<div id="main-nav">
#{
var sm = Html.MvcSiteMap();
#sm.Menu(sm.Provider.RootNode, true, true, 2); // 2 levels (home, plus main nav)
}
</div>
Looking around in the disassembly seems to show that it works a little like this:
You really need a starting node
If you don't give it one, it tries to find one based on the current node
plus restrictions (forward searching, depth restrictions, etc)
if you want nodes from level 1, you have to know what level you are on
Since that returns null, starting node is null, which means the helper writes an empty string
There may be a combination of tricks, or an overload or two, which can be finagled into doing this, but I can't find it right now. This works for my needs (simple top menu). There has to be a simpler way to do this, something with wild cards, or route based, with a closest match thing going on. I figured menus were a fairly standard part of a web app, and this would be covered :)