silverstripe function to return menu level - silverstripe

I'm trying to write a function that returns what menu levels are visible on the page...at the moment I'm using <% if %> statements in the template, ie:
<div class="<% if Menu(1) %>navA<% end_if %> <% if Menu(2) %>navB<% end_if %> <% if Menu(3) %>navC<% end_if %>">...</div>
Which, if there are 3 menu levels on a page, returns <div class="navA navB navC">
What I want is a function that returns just the lowest level menu on the current page, ie <div class="navC">
Thanks

that's perfectly possible.
just add the following to your Page_Controller class:
function LowestLevel() {
$i = 1;
while($this->getMenu($i)->count() > 0) $i++;
return 'level'.($i-1);
}
now you can call it in your template like so:
<div>lowest level: $LowestLevel</div>
$LowestLevel will print 'level1', 'level2' etc.
in case your class names have to be like 'navA', 'navB'... you need to do some matching like 'level1'->'navA', which shouldn't be too hard - come back to me if you need any help on this.

What about the following (untested):
<div class="<% if Menu(3) %>navC<% else_if Menu(2) %>navB<% else %>navA<% end_if %>">...</div>
You might want to consider using some custom code in the Controller for logic-heavy stuff, but this should get you going...

Related

Using CSS To Style Posts in Ruby on Rails

I'm trying to create a feed of posts for my bloglike application. I'm trying to arrange it so posts are grouped by month and there are 3 posts displayed per line.
This is my code for my feed partial:
<% #posts_by_month.each do |monthname, posts| %>
<%= monthname %>
<% posts.each do |post| %>
<div style="width:100%">
<div style="float:left;width:33%"><%= post.created_at %></div>
</div>
<% end %>
<% end %>
& this is the #posts_by_month in my controller:
#posts_by_month = current_user.feed.group_by { |post| post.created_at.strftime("%B") }
This currently styles it like in this screenshot:
When the code reaches a new month I want the month to be on a new line like the arrow demonstrates, rather than part of the same block like it is currently. Does anyone have any suggestions on how to do this?
You could wrap the month name in:
<div style="clear:left"><%= monthname %></div>
This will make the monthname 'clear' anything that is floated left.
You could make it easier on yourself though by using a grid system or using flexbox like this: https://codepen.io/anon/pen/JNZqaM.
You shouldn't have to use floats for this purpose

Silverstripe: Template behavior of "Up"

In Silverstripe templating, the $Up tag temporarily breaks out of the current loop/with and gives access to the parent scope. While the following template code works, I don't understand why.
$Checked is a list with objects that I loop, in itself containing a list with $Items of which I need to show the first. The object also has an Owner, which I need to access while in the scope of the first item.
I've got the following silverstripe template code:
<% loop $Checked %>
<% with $Items.First %>
<article class="checked-statement">
<span class="statement-outcome h-bg-true-$Verdict.Value">$Verdict.Name</span>
<div class="checked-statement__statement">
<a href="xxx" class="checked-statement__picture"><img
src="$Up.Up.Owner.Photo.CroppedImage(160,160).Url" alt="$Up.Up.Owner.Name.XML" class="h-full-rounded"/></a>
$Up.Up.Owner.Name zei
<h3>
$Up.Up.Title
</h3>
</div>
<a href="yyy" class="checked-statement__argument">
$Up.Up.Statement…
$Top.Icon('chevron-right')
</a>
</article>
<% end_with %>
<% end_loop %>
I would think I would need only one "Up" to get to the scope of $Checked. But I need two, which is strange, as the first Up should break out of the "with", and the second one should break out of the loop, giving me the top level scope, in which the specific item is not available...
Can anyone point me at the fault in my reasoning, or code?
At some point, I believe it was with 3.0 or 3.1, the logic behind $Up changed.
Previously <% with $Items.First %> or back in 2.x <% control $Items.First %> was just one scope level that you could break out of with $Up.
These days, each object/method call/property gets it's own scope. This means:
<% with $Foo.Bar %>Foo's ID: $Up.ID<% end_with %>
<% with $Foo.Bar %>Outside of "with" ID: $Up.Up.ID (== $Top.ID in this case)<% end_with %>
And for deeper nesting you need even more ups:
<% with $Foo.Bar.X %><% loop $Y %>$Up.Up.Up.Up.ID == $Top.ID<% end_loop %><% end_with %>

Adding Recent post in silverstripe blog

I am working with silverstripe with first time and I almost create a blog in silverstripe but now I stuck at one place where I need help you guys. If anybody have any idea about it then please help me.
I am trying to add recent posts in my blog. I am using the below code for this
public function latestBlog($num=10) {
/* return BlogEntry::get()->sort('PublishDate','desc')->limit($num); */
echo $blogPosts;
return $blogPosts = BlogPost::get()->filter('ParentID', $this->ID)->limit($num);
}
And in my ss page I am using html like this
<% loop $latestBlog %>
<li>$Title</li>
<% end_loop %>
this gives me titles of the each post but in href I want url too
If my title is "TEST POST" then I want href like "www.mydomain.com/TEST-POST";
Can Anybody have Idea about it?
You can use $Link which will return the relative url. Reference https://docs.silverstripe.org/en/3.2/developer_guides/templates/common_variables/#links
<ul>
<% loop $latestBlog %>
<li>$Title</li>
<% end_loop %>
</ul>

setLeftTitle in Silverstripe 3.1

I have just jumped up the Silverstripe bandwagon.
I have been trying to get the following effect of static text in front of a text field on the getCMSfields form:
Telephone number: +36 [__________]
where "telephone number:" is obviously the field title (which can be altered via ->setTitle() and +36 is a static prefix prepended to the left of the input field.
I have been trying with ->setLeftTitle('+36') but it does not seem to have any effect.
BTW. ->setRightTitle('something') - which I expected to append a label to the right of input field, works identically to ->setDescription().
I'm confused. So is there any way to achieve what I want?
Use the FieldGroup class
public function getCMSFields($fields) {
$fields = parent::getCMSFields($fields);
$fields->addFieldToTab('Root.Main',
FieldGroup::create(
new HeaderField('+36'),
new TextField('PhoneNumber','')
)->setTitle('Telephone number')
);
return $fields;
}
Personally I'd use two TextFields for cosmetic reasons, and enforce some validation on the TelephonePrefix.
The default template does not render the left title. To do this, you will probably need to create a custom form field template (called FormFieldLeftTitle.ss) or something, and include $LeftTitle in the appropriate spot:
<div id="$Name" class="field<% if $extraClass %> $extraClass<% end_if %>">
<% if $Title %><label class="left" for="$ID">$Title</label><% end_if %>
<div class="middleColumn">
$LeftTitle
$Field
</div>
<% if $RightTitle %><label class="right" for="$ID">$RightTitle</label><% end_if %>
<% if $Message %><span class="message $MessageType">$Message</span><% end_if %>
<% if $Description %><span class="description">$Description</span><% end_if %>
</div>
You can then call $myFormField->setTemplate('FormFieldLeftTitle') to use this template.

Silverstripe: Excluding current page from list of the parent's children

Using Silverstripe's "ChildrenOf" syntax, I've been successfully able to list all children of a page's parent. It's being used in a "see also" style list on a page.
I'd like to exclude the current page from the list but unsure how to determine which is the same as the current page, as within the control loop I'm in the parent's scope. Any ideas? Here's a pseudocode of what I'm doing:
<% control ChildrenOf(page-url) %>
<!-- Output some stuff, like the page's $Link and $Title -->
<% end_control %>
there's a built-in page control for this, so to exclude the current page from your list:
<% control ChildrenOf(page-url) %>
<% if LinkOrCurrent = current %>
<!-- exclude me -->
<% else %>
<!-- Output some stuff, like the page's $Link and $Title -->
<% end_if %>
<% end_control %>
see http://doc.silverstripe.org/sapphire/en/reference/built-in-page-controls#linkingmode-linkorcurrent-and-linkorsection
UPDATE
as you mentioned in your comment below that you'd like to use the $Pos control, you need to filter the dataobjectset before iterating over it.
add the following to your Page_Controller class:
function FilteredChildrenOf($pageUrl) {
$children = $this->ChildrenOf($pageUrl);
if($children) {
$filteredChildren = new DataObjectSet();
foreach($children as $child) {
if(!$child->isCurrent()) $filteredChildren->push($child);
}
return $filteredChildren;
}
}
then replace 'ChildrenOf' in your template by 'FilteredChildrenOf':
<% control FilteredChildrenOf(page-url) %>
//use $Pos here
<% end_control
In Silverstripe 3.1 you can use a method like this -
<% loop $Parent.Children %>
<% if $LinkingMode != current %>
<!-- Output some stuff, like the page's $Link and $Title , $Pos etc -->
<% end_if %>
<% end_loop %>
This way you can list all parent's children pages.
See https://docs.silverstripe.org/en/3.1/developer_guides/templates/common_variables/

Resources