Find if node is a child magnolia CMS - magnolia

I need to find out if a node in magnolia is a child and who is the parent. This is so that I can recreate the elements in reverse order. For example I need to find out that the first node 1 is child of quicklinks area node and the second node 1 is child of linklist area node.
--quicklinks [mgnl:area]
*--1 [mgnl:component]
*--linklist [mgnl:area]
*--1 [mgnl:component]
*--links [mgnl:area]
*--0 [mgnl:component]
What method can I use for that?

NodeUtil is indeed a good starting point, as #Ducaz035 mentions. But you'll need to write a model class for this. If you want to keep things strictly on the template level, have a look at cmsfn (Magnolia Templating Functions) and the Freemarker documentation. You can do neat things like this:
Content: ${content}<br />
Parent: ${content?parent}
Siblings (children of parent):<ul>
[#list cmsfn.children(content?parent) as child]<li>${child}</li>[/#list]
</ul>
Reversed siblings (children of parent):<ul>
[#list cmsfn.children(content?parent)?reverse as child]<li>${child}</li>[/#list]
</ul>

Have a look at info.magnolia.jcr.util.NodeUtil.
It brings a lot functionality that can be used including finding all children or fetching the parent of a given node.
Cheers,
Hope That helps,

Related

Is it possible to find out if an element comes before the second element in Capybara?

I was doing tests with Caplybara, Cucumber and WebDriver, so I looked at two elements on top of each other, so I thought.
In a simpler way, is it possible to know if an element comes before the second?
In a more complex way, is it possible to know if one element has a position on top of the other?
The structure is simple
<div id="father-parent">
<p id="children-0">Firt element</p>
<p id="children-1">Second element</p>
</div>
If what you're trying to verify is that children-0 comes right before children-1 you can use the CSS adjacent sibling selector
expect(page).to have_css('#children-0 + #children-1')
If you just want to verify that children-0 is a prior sibling of children-1 (not necessarily adjacent) you can use the general sibling selector
expect(page).to have_css('#children-0 ~ #children-1')
Depending on how the test is written, you could also use the have_sibling matcher:
first_child = find('#children-0')
expect(first_child).to have_sibling('#children-1')
To test for element positions, some drivers support the :below filter:
expect(first_child).to have_sibling('#children-1', below: first_child)
below is one of Capybara's global filters, you could also use above, left_of, and right_of.
If you can do with simple content matching, I have just added a new matcher as spec/support/matchers/appear_before_matcher.rb:
RSpec::Matchers.define :appear_before do |later_content|
match do |earlier_content|
page.body.index(earlier_content) < page.body.index(later_content)
end
end
and then used it like this:
expect('First element').to appear_before('Second element')

Internal link tracking with 'matches css selector'

I'm want to track in Google Analytics clicks into internal links on my page using events in GTM.
I'm debugging my tag in GTM Debugger and it shows me that, there's a problem with my trigger rule.
The rule is:
Click classes -> Matches CSS selector -> .cb-feature-1 .cb-l .cb-grid-entry
Here's hierarchy:
As you can see, there are three links inside div with class .cb-feature-1 .cb-l .cb-grid-entry but all of them are the same so I just want to track all of them together.
Currently your selector looks like this:
.cb-feature-1 .cb-l .cb-grid-entry
which means it is looking for three nested elements:
<div class="cb-feature-1">
<div class="cb-1">
<div class="cb-grid-entry>
... (rest of code)
However this is not what your markup looks like, you want to target a single element with three classes. For this you have to remove the whitespace between the elements of your selector:
.cb-feature-1.cb-l.cb-grid-entry
This will look for elements that have all three classes at once. Since you want to target links within those elements you need to look for an anchor tag:
.cb-feature-1.cb-l.cb-grid-entry a
Choose "Click Element" instead of "Click Classes".

Add indentation to lineage in GSP page

I am trying to list a descendancy starting from root and printing its children's children. The domain looks something like
class Node {
String nodeId
String label
Node parent
}
Note I dont have a reference to child instead i have a reference to its parent.
In the GSP page I want to list the entire lineage but I am not able to get proper indentation where each node will have an indent for its child. Basically need some kind of checking condition that if the previous node is the parent of the next node give it an indent otherwise find the parent of next node and put it there accordingly.
<concepts>
<g:each in="${nodes}" var="node">
<concept id="${node.id}" description ="${node.label}">
</concept>
</g:each>
</concepts>
Something like (ignore the text. i need a structure like this
This is related to: Recursion in GSP page
Update the _node.gsp template:
<g:if test="${nodes}">
<ul>
<g:each in="${nodes}" var="node">
<li>
${node}
<g:render template="node" model="[nodes:Node.findAllByParent(node)]" />
</li>
</g:each>
</ul>
</g:if>
And style accordingly.

How to render a hierarchy tree in HTML5/CSS?

I have not done any web development as of late. Was wondering if there is an easy way to load a data representation of a hierarchy tree such as
node parent
---------------------------------
root
Level1.Node1 root
Level1.Node2 root
Level1.Node3 root
Level2.Node1 Level1.Node1
Level2.Node2 Level1.Node2
Level2.Node3 Level1.Node2
And get it rendered like
root
--------Level1.Node1
--------------Level2.Node1
--------Level1.Node2
--------------Level2.Node2
--------------Level2.Node3
without using fancy tables?
Use styled and nested unordered lists.
<ul>
<li>Level 1
<ul>
<li>Level 2</li>
</ul>
</li>
</ul>
Practically you just want to keep on checking the Parent's Children. This is not a HTML5/CSS thing, but a JavaScript thing to check the DOM (node) roots.
Use the WebKit/Firebug tools to dump out the HTML DOM Object and see it's attributes. You can see what their properties and methods are and use them to iterate through them until you hit the bottom of each subtag.
console.log(document);
console.log(document.head);
These just return the HTML blocks.
console.log(document.body);
This returns the actual DOM object. You can see in the inspector that you actually get back tons of info to parse on.
Check [children] and [childNodes]. That's where you want to iterate your DOM structure.
[nodeName] and [nodeType] help you identify the attributes.
Printing it out you can do with placeholders var offset = ' '; and reloop them or use CSS to render <div> tags with mathematical calculated left-margins.

How can I place items in different (already existing) columns based upon a css class?

This is NOT a question about how to create columns in css - so please dont give me any css for doing that. I've just excluded it here for readability.
I have created two columns in css and I want to place items in them based upon some css class. I think this is possible but I'm not sure how.
<DIV id="col1">
<!-- I want to display everything with 'women' here -->
</DIV>
<DIV id="col2">
<!-- I want to display everything with 'men' here -->
</DIV>
<!-- this content is dynamically generated in a loop (PHP/ASP.NET)-->
<DIV id="products">
<DIV class="women">
Women's product 1
</DIV>
<DIV class="men">
Men's product 1
</DIV>
<DIV class="men">
Men's product 2
</DIV>
</DIV>
Edit: Just to be sure I don't want to duplicate the product list into col1 and col2. i want to move them. I only want once visible copy of each item.
So I have two columns - or areas on the page - whatever - doesn't matter for this.
I want to use css to take everything under .products.women and put it in column 1.
I want to use css to take everything under .products.men and put it in column 2.
How can I do this. These kinds of things are about my limit to css, but I know theres some cleverness I can use.
Currently I'm rendering into the columns in two separate for loops. I want to get away from this for two reasons :
I dont want to maintain 2 identical for loops - nor move that logic elsewhere
I want to make an 'iphone' friendly version and i figure this will make that easier.
You can't do precisely what you're asking for with CSS. But you can do .women { float: left } .men { float: right}, which may be just about as good.
This is kind of a band-aid on your fundamental problem, though, which is failure to separate your presentation logic from your control logic. Instead of having two identical for loops in your presentation logic, you should have one for loop outside of it that builds two arrays, then your presentation logic should use each the way that would actually be beneficial to it.
CSS it's a language used to describe the presentation of the (existing) content. You are
asking for programaticaly DUPLICATE or COPY some of that content.
You can either use ASP/PHP whatever languaje of choice to generate multiple copies of that content, or use javascript to copy-move-change it.
Actually javascript seems to fit your scenario.
EDIT: you have a similar previous question here: using css to duplicate html elements
Interestingly (but, at this point, completely uselessly), this is not only possible in the current draft of the CSS3 Advanced Layout Module (aka Template Layout), but the spec contains an example showing how to do exactly that (last example in section 3.4). So if you can stand to wait a fifteen years or so...

Resources