getResources to build top level menu - modx-revolution

I am trying to use getResources to build the main navigation for my site. How do I tell getResources to start at the current context and look at all resources immediately under the current context?
I see I can specify the following parameters;
parents
resources
I have set parents to 0 and that doesn't work. I don't know the resource id for the context so I cannot specify it for the resources parameter.
Can't I do what I want with getResources? What am I missing?

Build navigation on http://rtfm.modx.com/display/ADDON/Wayfinder he has a parameters to work with contexts.

use &context, from the docs at rtfm.modx.com "Which Context should be searched in. Defaults to the current Context."
so your minimum getResources call would probably looks something like:
[[getResources? &parents=0 &tpl=menuTpl ]]
You don't have to specify the context, also, getResources is very server resource intensive, unless you have a specific reason not to, use wayfinder as Vasis suggested.

I know it's a bit late, but I just came up with this, tested and working on Revo 2.2.10.
The way you tell getResources to start at the current context is setting the parent to the ID of the current document.
This would go in your template:
<ul>
[[getResources? &parents=`0` &depth=`0` &limit=`0` &sortby=`menuindex` &sortdir=`ASC` &tpl=`tpl_Navigation`]]
</ul>
And then in the Chunk used as a template for getResources (tpl_Navigation):
<li>
[[+menutitle:default=`[[+pagetitle]]`]]
[[getResources? &parents=`[[+id]]` &depth=`0` &totalVar=`numChildren[[+id]]` &limit=`0` &tpl=`tpl_Navigation` &sortby=`menuindex` &sortdir=`ASC` &toPlaceholder=`children[[+id]]`]]
[[+numChildren[[+id]]:gt=`0`:then=`<ul>[[+children[[+id]]]]</ul>`:else=``]]
</li>

If you want to use getResource to generate menu from the top of current context, you need to add &depth=`0` &context=`[[*context_key]]` parameters as well.
But for simple menu generation in modx i suggest You to use Wayfinder plugin insted of getResource.

Related

How to pull out all routes for specific resource

I have strange question. I want in my helper to have array of paths that are available for specific resource.For example, if we have a model Comment I want to have an array which will have the following elements: [new_comment_path, comments_path] etc. Is this possible to do?
Edit:
I build left side menu in rails. It will work like tree menu. I don't want to use external plugins. Only thing that i must do is to have a all paths for my models.
You can do
Rails.application.routes.routes.map{|x| x.name}.reject{|x| x.blank?}
Which will get all named routes. I'm not sure if there is a way of just getting routes for one resource though

Maintain parameter info in the request path for all pages instead of the subdomain

I seek some guidedence here ... ( I'm not sure if this is the best title )
At the moment I prepend a "server name" to the url like this:
server10.example.com
This works fine, except that I need to handle all the subdomains on the IIS and I'm not sure google are happy about jumping around from sub to sub to sub, when it seems the links to the other servers.
I'm kind a hoping for a nice way to archive this wioth asp.net mvc.
Most pages are related to a "server" ... there are however a few info pages, contact, home that dont really need a valid "server" name ... but could just be "na" for not available, but the name need to be maintained, if there is already a selected server, when a user are keeps browsing the site. This needs to be as transparent as possible when I need to create the links to the diffenrent pages.
I could extend the Html Action() extensien to automatically add the selected "server" from the previusly request to the page.
In the format:
/{serverParameter}/{controller}/{action}/{parameterInfo}
And if no server is selected, just add "na" as the {server} placeholder.
I'm not sure if more information is needed, but please let me know if ...
I tired of extracting the selected server from the domain part and the other way also seems better, I just can't think of a good way to structure this ...
Updated
90% of all the pages are about a server that the user select at some point. Could be server10, server9, server20 ... just a name. I want to maintain that information across all pages, after the users has selected it or else I just want it to be f.ex: "empty".
I mostly looking for an easy way of doing this or an alternative ... atm I'm prepending the serverParamter to the url so it ends up being: "serverParameter.example.com".
I want to end up with something like
http://example.com/{server}/{controller}/{action}
instread of
http://{server}.example.com/{controller}/{action}
If I understand your question correctly, you just wish to group different collections of content together above the controller/action level. If that's the case, have you considered using ASP.NET MVC areas?
Just right-click on your project, and choose Add -> Area.... Give it a name (what you're calling "server"), and then you can add content, your own controllers, actions, etc. Under this area. You will automatically be able to access it via /AreaName/Controller/Action/etc.
I went with the already impemented routing in ASP.NET MVC.
{server}/{controller}/{action}
When creating the links it takes the set value for {server} and places the value when generating URL's, so I only need to supply controller and action in the #Html.Action helper method ... this could not have been more easy.
I'm not sure why I did not think about this. One just gotta love routing.

incorporating all views into one view

Just wondering what the shorthand would be in Rails to do this (if any):
I have views/pages/ containing 5 html.erb files and they all use the same default layout.html.erb, with one yield statement in the middle of it (the standard setup).
Now I want one view that incorporates all 5 of those erb files above contiguously, one after the other, in place of the one existing yield statement in that same layout.html.erb.
What minimal changes would I make to the layout.html.erb to accomplish this.
(Rails Newbie - like it more than Django now).
Ah,
I see what you're saying. Try this. Have your file structure such that all the views for said controller are in one folder...
#controllers_views = Dir.glob("your/controllers/views/*.erb")
#controllers_views.each { |cv| puts cv }
Seems like that would work, I'm away from my dev box or I'd test it for you.
Hope that helps.
Good luck!
You could always have a javascript that requests the sequential yields at a time interval as an ajax request. Then just your target element change to reflect the updated information.
Alternatively load all 5 into different divisions, and have them revolve visibility, like a picture gallery. CSS3 could pull this off.
http://speckyboy.com/2010/06/09/10-pure-css3-image-galleries-and-sliders/

How to click on the second link with the same text using Capybara in Rails 3?

In a view file I have:
= link_to 'View', post
= link_to 'View', comment
In a spec file (I'm using Capybara):
click_on 'View'
It clicks on the first link, but I want it to click on the second one. How can I do it?
You could try to find all entries and deal with an array:
page.all('a')[1].click
Would help to have a class or use within to scope your search ;)
There's probably a few ways but I usually scope something like this.
within(".comment") do
click_on("View")
end
There's quite possibly/probably alternatives as well. I usually do my acceptance testing from cucumber, so my steps typically look like
When I follow "View" within the comment element
Where I have a step that translates within the comment element to a scoped call to the step itself (which I think is built into the latest capybara web_steps)
The worst thing about "the second" link is that it can become the third or the first or even the twenty fifth someday. So, scoping with a within block is the best way. Example:
within(".comment") do
click_on("View")
end
But if it is difficult to specify the link with a within scope (which sometimes it really is), I guess the way to click the second link with a certain text is:
find(:xpath, "(//a[text()='View'])[2]").click
In later versions of capybara (2.0.2, for example) both click_on 'View' and click_link 'View' will raise an ambiguous match error:
Failure/Error: click_on 'View'
Capybara::Ambiguous:
Ambiguous match, found 2 elements matching link or button "View"
So this won't do even if you want to click the first link (or if any link would be ok, which is my case).
As far as I understand this is made to force people write more specific tests where particular links are clicked.
It definitely could be tricky to debug the code if you accidentally placed two or more links with identical text and try to see what is happening. It's good to rely on something that is unlikely to change and specifying a link with a within block is a nice way to do this.
There are many ways for solving this type of problems.
Do it like this
if(page.find("a")[:href] == "comment")
click_on("View")
or
page.find("a:eq(2)").click
Remember javascript indexing starts with 0 while In Capybara, indexing starts with 1. So use a:eq(2) here for second href.
For capybara 2 solution:
within(".comment") do
click_on("View")
end
would not help if you have a few .comment. So simple use: page.first(:link, "View").click
This works for me if you have several rows of identical classes and you want to find the second row. Like a previous author mentioned, capybara indexing starts at 1.
within all(".trip-row")[2] do
assert page.has_content?("content")
end
If you use capybara-ui you could define the widget, or reusable DOM reference, for each widget.
# define your widget. in this case,
# we're defining it in a role
widget :view_post, ['.post', text: 'View']
widget :view_comment, ['.comment', text: 'View']
# then click that widget in the test
role.click :view_post
role.click :view_comment

How do I make a "back" link?

I have a detail page that gets called from various places and has a nice readable url like
"www.mypage.com/product/best-product-ever".
The calling pages (list of products) have a more complex url like:
"www.mypage.com/offers/category/electronic/page/1/filter/manufacturer/sony/sort/price" and
"www.mypage.com/bestseller/this-week".
How can I make a backlink from the detailpage to the calling product list?
I cannot use javascript
I don't want to have the calling page in the URL, because it gets to long
I really want links between pages, no http-post
I cannot use Sessionstate
EDIT:
Sessionstate is ruled out, because if there are 2 Windows open, then they would share the same "Back" page information.
Like Lee said, use the referrer value:
Back
If you don't want the URL in the link because it's too long, try running some sort of simple compression algorithm over the URL, display the compressed data as unicode text and then append the compressed URL as a parameter to a redirect page, e.g:
Back
What about using the referrer header value?
Here's a crazy idea that will require a fair but of work and may not be healthy for performance (depending on your users).. but here we go:
Create a repository for caching 'ListResults' (and wire it to persist to the DB of you like.. or just leave it in memory on the server).
In short what this Repo can do is store a ListResult which will include everything to persist the state of the current view of the list any given user is looking at. This might include routes and other values.. but essentially everything that is needed to redirect back to that specific page of the filtered and sorted list.
As the ListResult item is added to the repo a small unique hash/key is generated that will be url friendly - something like this "k29shjk4" - it is added to the item along with a datetime stamp.
ListResults are only persisted from the moment a list gets off the default view (ie. no filtering, sorting and Page 1) - this will help in a small way for performance.
A ListResult item may never actually get used but all detail actionlinks on the particular list view have the ListResult.Key hash value added to the route. So yes, it might end up as a querystring but it will be short (url friendly) and if you wanna mess with routes more, you can tidy it up further.
For navigation "back" to the list, you may need a new small controller which accepts simply the ListResult.Key hash value and redirects/re-creates the state of the list view (paging, filtering and sorting included) from the lookup in the repo.
So we have met the requirements so far: no calling page in the url (in the sense that its not the whole page - just a hash lookup of it); no POSTing, no sessions, no js.
To stop the ListResult repo from getting to big (and dangerous: if you persist it to the DB), you can use a ASP.NET background service to periodically prune the 'old' routes by way of the timestamp.. and 'extend' the life of routes that are continuously being used by adding time to the stamp of a ListResult item when it's requested via the new controller. No need to persist a route indefinitely coz if a user wants a permalink to a list view, they can bookmark the long list route itself.
hope this helps somehow
Do you have a cookie?
If so, you can put it in there, or use it to create your own session state.
I think this is more like a "Back to results" then a generic "<< back" link, because you would expect the generic back link to return to the genetic list, not the heavily filtered list you described, right?
I don't know if this falls into your "no post" condition, but the only option I can see is having the Detail action be POST-only ([AcceptVerbs(HttpVerbs.Post)]) and include another parameter like string fullRoute which is converted to the 'link' on the detail page for "Back to results". Overload the Detail action missing the fullRoute param and have the overloaded action be a GET action so that the POST fullRoute value is not required (for when users are ok with the 'generic' "Back" link). This should serve both 'generic' GET requests to the Detail page and the POST request which will include the specific "Back to results" link for the filtered list.

Resources