remove decoration tags aem sightly - aem

How can I remove the decoration tags only in preview/publish mode in AEM sightly?
I have seen the question and answer: AEM/CQ: Conditional CSS class on decoration tag
This removes the decoration but stops me from editing the components because it removes the decoration in edit and design mode as well. What is the condition required so that it will only remove the decoration tags in preview/publish?
I have also seen that it is possible to add the following code into the activate method of my java-use class:
if (!getWcmMode().isEdit() && !getWcmMode().isDesign()) {
IncludeOptions.getOptions(getRequest(), true).setDecorationTagName("");
}
This removes all but one of the decoration tags see example below:
HTML in wcmmode=disabled without the above code in the activate method:
<ul class="timeline">
<div class="section timelineTag">
<div class="section timelineTag">
<div class="section timelineTag">
<li class="clear"></li>
</ul>
HTML in wcmmode=disabled with the above code in the activate method:
<ul class="timeline">
<div class="section timelineTag">
<li class="event" href="#">
<li class="event" href="#">
<li class="clear"></li>
</ul>
How can I remove the first decoration DIV tag in the ul as it does not disappear when I add the specified code to the activate method?
As requested here is a detailed look at the component in question (updated 07/05/2015):
Java Class
public class TimelineClass extends WCMUse {
#Override
public void activate() throws Exception {
//Remove default wrapping performed by AEM for the preview mode
if (!getWcmMode().isEdit() && !getWcmMode().isDesign()) {
IncludeOptions.getOptions(getRequest(), true).setDecorationTagName("");
}
}
}
HTML code:
- There are two components involved in this. First of all the container component that includes the ul tag
- Then the tag component which is dragged and dropped from the sidekick into the container to create, in publish, the lists shown above.
Container code:
<div class="az-timeline row">
<section class="small-12 columns">
<section class="wrapper">
<ul class="timeline">
<!-- /* The parsys where all of the timeline tags will be dropped */ -->
<div data-sly-resource="${'par-wrapper' # resourceType='foundation/components/parsys'}" data-sly-unwrap></div>
<li class="clear"></li>
</ul>
</section>
</section>
Tag component which is dragged and dropped into the container parsys above:
<li data-sly-use.timelineTag="TimelineClass" class="event" href="#">
<img style="width: 165px;" data-sly-test="${properties.outerImage}" alt="placeholder" src="${properties.outerImage}"/>
<article>
<h5>${properties.heading || 'Timeline heading'}</h5>
<h4>${properties.subheading || 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sunt labore molestias perspiciatis reiciendis.'}</h4>
<p>${properties.text || 'Sed molestie, mauris sit amet egestas malesuada, felis magna commodo urna, vel consequat lorem enim ac diam. Aenean eget ex vitae enim cursus facilisis ac feugiat nisl. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.'}</p>
<img style="height: 130px;" data-sly-test="${properties.innerImage}" alt="" src="${properties.innerImage}" />
<a data-sly-test="${properties.link}" class="az-sbButton" href="${properties.link}">${properties.linkText || 'More'}<span class="owi-az-linkIcon internal"></span></a>
</article>
</li>
Several of the tag components are dragged and dropped into the parsys in the container and the result in wcmmode=disabled is the second ul shown above with the first item in the list surrounded by a div tag

I haven't worked with the Sightly stuff yet, but I have had success removing the extra divs by assigning the property "cq:noDecoration" (Boolean set to true) on the component in the JCR. Try that and see if it helps.

if i understand you correctly and you want div.section.timelineTag to be here only in edit mode, then the code would be
<ul>
<div data-sly-test="${wcmmode.edit}" class="section timelineTag">

Use data-sly-unwrap. See this post and the referenced doc from adobe
http://www.aemmastery.com/2015/04/24/remove-div-tags-sightly/
"data-sly-unwrap: Removes the host element from the generated markup while retaining its content."
Another option, set cq:htmlTag to "":
http://dev.day.com/cemblog/en/experiencedelivers/2013/04/modify_the_auto-generateddivs.html

As Rampant suggested but make the timeline ul part of the component and try setting cq:htmlTag to a "ul" and give it a class timeline: and you can still edit the component and it does not mess with the display. http://dev.day.com/cemblog/en/experiencedelivers/2013/04/modify_the_auto-generateddivs.html

Possible workaround for the issue when you need conditional remove of the decoration tags in Sightly on example of edit / preview mode:
Create two child components for your component ("parent-component") - "edit-view" and "preview-view".
For "edit-view" component set cq:noDecoration="{Boolean}false"
For "preview-view" component set cq:noDecoration="{Boolean}true"
In parent-component.html add conditional rendering like:
<sly data-sly-test="${isEditMode}">
<sly data-sly-resource="${'editViewResourceName' # resourceType='yourapp/components/parent-component/edit-view'}"></sly>
</sly>
<sly data-sly-test="${isPreviewMode}">
<sly data-sly-resource="${'editViewResourceName' # resourceType='yourapp/components/parent-component/preview-view'}"></sly>
</sly>
Tips:
Add dialog only for "edit-view" component.
For "preview-view" component you can keep only .content.xml and preview-view.html
To avoid code duplication there is possibility to include "edit-view" into "preview-view" using construction like
<sly data-sly-resource="${currentNode.path # resourceType='yourapp/components/parent-component/edit-view'}"></sly>

Related

How to recursively search the DOM and return first element that has a specified class

For example - return the 1st element that has class = "title".
The result in this case should be div3.1
Should only use vanilla JS.
<body>
<div class="container">
<div class="abc"> div1</div>
<div class="abc"> div2
<div class="abc">div2.1
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo, ipsum?</p>
</div>
<div class="abc">div2.2</div>
<div class="abc">div2.3</div>
</div>
<div class="abc"> div3
<div class="title">div3.1</div>
<div class="title">div3.2
<img src="" alt="">
</div>
</div>
</body>
I don't know about recursively, but querySelector() does just that. It will find the first element that matches the given parameter. The parameter is a CSS selector, so:
id: #abc
class: .abc
attribute: [abc]
tag: div
There's the old school way as well using getElementsByClassName():
var abc = document.getElementsByClassName('abc')[0];
The getElementsByClassName() returns a HTMLCollection/NodeList of all elements with a given className, using the bracket notation ([0]) suffix insures that it only returns the first element of the NodeList.
Demo
var title1 = document.querySelector('.title');
var title2 = document.getElementsByClassName('title')[0];
console.log(title1.textContent);
console.log(title2.textContent);
<body>
<div class="container">
<div class="abc"> div1</div>
<div class="abc"> div2
<div class="abc">div2.1
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo, ipsum?</p>
</div>
<div class="abc">div2.2</div>
<div class="abc">div2.3</div>
</div>
<div class="abc"> div3
<div class="title">div3.1</div>
<div class="title">div3.2
<img src="" alt="">
</div>
</div>
</div>
</body>
I'm afraid you provided too little details in your question. If you want to find element with specified class, you can use document.querySelector method.
You can't "recursively" search whole DOM (starting from certain node I'm assuming?), but you can search specific DOM "branch" (element and its parents, up to document body). You can use function like:
function findElementWithClass(sourceElement, className){
var element = sourceElement; //selected DOM node
while(element !== document.body){
if(element.classList.contains(className)){
break;
}
element = element.parentNode;
}
return element;
}
After while loop you can make additional check if element you wanted has been found - if not, you can return false or do whatever you like.
JS Fiddle link: https://jsfiddle.net/8o9jzt8h/

AEM HTL looping using data-sly-repeat

<footer id="footer">
<div class="container">
<div class="row double">
<div class="6u">
<div class="row collapse-at-2">
<div data-sly-repeat="${properties.colNum}" data-sly-unwrap>
<div class="6u">
<h3>Accumsan</h3>
<ul class="alt">
<li>Nascetur nunc varius</li>
<li>Vis faucibus sed tempor</li>
<li>Massa amet lobortis vel</li>
<li>Nascetur nunc varius</li>
</ul>
</div>
</div>
</div>
</div>
<div class="6u">
<h2>Aliquam Interdum</h2>
<p>Blandit nunc tempor lobortis nunc non. Mi accumsan. Justo aliquet massa adipiscing cubilia eu accumsan id. Arcu accumsan faucibus vis ultricies adipiscing ornare ut. Mi accumsan justo aliquet.</p>
<ul class="icons">
<li><span class="label">Twitter</span></li>
<li><span class="label">Facebook</span></li>
<li><span class="label">Instagram</span></li>
<li><span class="label">LinkedIn</span></li>
<li><span class="label">Pinterest</span></li>
</ul>
</div>
</div>
<ul class="copyright">
<li>© Untitled. All rights reserved.</li>
</ul>
</div>
</footer>
I am trying to use data-sly-repeat to loop and I have verified that the value of colNum is 2 but still the loop is running only once. In other words, it doesn't loop through irrespective of the value. I also hardcoded the value 3 but it still won't run the loop more than once. Not sure what I am doing wrong here.
Thanks in advance
In sightly you can only iterate over a collection using sly-repeat or sly-list.So instead here instead using the ColNum directly you will have to make a simple collection .
Refer: https://docs.adobe.com/docs/en/htl/docs/block-statements.html
It seems you have misunderstood how data-sly-repeat is intended to be used. You can read their documentation to get clarification.
Two things:
data-sly-repeat repeats the whole element that is marked, while data-sly-list only repeats the content of the element. In your case it seems list is more appropriate.. You can eliminate the actual div that you are currently unwrapping.
Rather than passing in a number of times to repeat the HTML you pass in a list of things to iterate over. The html is rendered for each item in the list, with the ${item} variable being used to hold the current item.
So, you'll have to write some Java of JS code to turn your colNum into a list of that size.
For example, using the JS Use API. (see this question for ways to create empty iterable arrays)
"use strict";
use(function () {
let n = properties.get("colNum", 0);
return {
columns: [...Array(100)] // empty, iterable, array of size n
};
});
And calling it from the HTL. Notice I removed the extraneous div and am using data-sly-list to loop over the n length array of empty elements
<div class="row collapse-at-2"
data-sly-use.config="<JS-file-name>"
data-sly-list="${config.columns}">
<div class="6u">
<h3>Accumsan</h3>
<ul class="alt">
<li>Nascetur nunc varius</li>
<li>Vis faucibus sed tempor</li>
<li>Massa amet lobortis vel</li>
<li>Nascetur nunc varius</li>
</ul>
</div>
</div>
data-sly-repeat needs an iterable object. You can provide a dummy array with the needed number of elements or, even better, an array with usefull things, such as column names or data.

How auto active Getuikit accordion

I want solve my problem with Getuikit.
Accordion plugin is working. But I want make active (clicked) specific accordion on page load.
How can I do this ?
edit: getuikit v2
<div class="uk-accordion" data-uk-accordion="{collapse: false}">
<h3 class="uk-accordion-title">Accordion 1</h3>
<div class="uk-accordion-content">
<!-- Content -->
</div>
<h3 class="uk-accordion-title">Accordion 2</h3>
<div class="uk-accordion-content">
<!-- Content -->
</div>
<h3 class="uk-accordion-title">Accordion 3</h3>
<div class="uk-accordion-content">
<!-- Content -->
</div>
<h3 class="uk-accordion-title">Accordion 4</h3>
<div class="uk-accordion-content">
<!-- Content -->
</div>
</div>
Example: How make "Accordion 3 & Accordion 4" active ?
I've found the answer on SO. Here someone opens all accordions on page, so I've tweaked the code little bit for you. You can choose, which accordion you want to open on init.
UIkit.on('afterready.uk.dom', function() {
var accordion = UIkit.accordion(UIkit.$('#myAccordion'), {collapse:false, showfirst: false});
//choose which number of accordion interest you, here we choose 1 and 3, index starts from 0
accordion.find('[data-wrapper]').each(function (index) {
if (index==0 || index==2)
accordion.toggleItem(UIkit.$(this), true, false); // animated true and collapse false
});
});
Here's working pen for you.
If I am not wrong, You are looking to keep by default first accordion. right? If yes you don't need to do any extra code for this. As Uikit as the solution itself.
You just have to put uk-open with first , take a look at below code and codepen.
<ul uk-accordion>
<li class="uk-open">
<a class="uk-accordion-title" href="#">Item 1</a>
<div class="uk-accordion-content">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
</li>
<li>
<a class="uk-accordion-title" href="#">Item 2</a>
<div class="uk-accordion-content">
<p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor reprehenderit.</p>
</div>
</li>
<li>
<a class="uk-accordion-title" href="#">Item 3</a>
<div class="uk-accordion-content">
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat proident.</p>
</div>
</li>
Look at CodePen too : Codepen

Get WRAPPER functionality from Template::Toolkit in Text::Xslate

I've used Template::Toolkit for my last few Catalyst projects and have a set up that I like using that allows a clean separation of my templates. Now I'm hoping to use Text::Xslate, but I'm having trouble figuring out if I can do my same setup or not. Below is what I have for Template::Toolkit usually.
__PACKAGE__->config({
...
WRAPPER => 'site/wrapper',
...
});
wrapper
[% content WRAPPER site/html + site/layout %]
html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>[% template.title or site.title %]</title>
<style type="text/css">
</style>
</head>
<body>
[% content %]
</body>
</html>
layout
<div id="header">[% PROCESS site/header %]</div>
<div id="content">
[% content %]
</div>
<div id="footer">[% PROCESS site/footer %]</div>`
And then header and footer have their own content. I like this solution because everything is cleanly separated and I'm not breaking up any div tags around the content by having to put the opening tag in header and the closing in the footer. It looks like with the TTerse syntax there is some wrapper functionality, but I'm not sure if that allows me to recreate what I normally do. I also found this answer that says you can use wrapper in theory, but doesn't really give any examples.
The directive WRAPPER works slightly differently in TTerse then in TT2. This basic syntax works:
[% WRAPPER "include/layout.tt" WITH
title = "Lipsum" %]
Magna in et vel: feugait erat augue, ut accumsan wisi hendrerit,
eu amet laoreet duis. Duis ex nonummy te lorem blandit et velit
tation erat amet elit dignissim.
[% END %]
And is include/layout.tt,
# [% title %]
[% content %]
----
Commodo quis magna feugiat ullamcorper, exerci tation ut.
BLOCK are not supported in TTerse though.
The documentation of TTerse is actually good enough and includes many workable examples: https://metacpan.org/pod/Text::Xslate::Syntax::TTerse#Functions-and-filters

tumblr customization - Show post details in modal

I've been modifying my tumblr page to show posts inside a modal.
I have added the modal but when I click on a post, the post details do not show up inside the modal.
I used a free theme that has the masonry grid applied and the blog shows a grid of posts.
Currently I have the modal outside {block:Posts}.
If I have the modal inside {block:Posts} I get 10 modals opening all on top of each other. Although post details do show inside the modal. (10 is the number of posts on current page).
If I have the modal inside {block:Photo} I get all the modals showing up inside the masonry grid.
Current state of my tumblr:
http://cnocle.tumblr.com/
What I want to acheive:
http://fifth-avenue-theme.tumblr.com/
Any help, suggestions, directions would be great!
Please let me know if I should post the code. It's long and I'm not sure if I should post it or not.
Code Below is the top section of the
thank you
<body>
<script type="text/javascript" src="http://static.tumblr.com/ek9ly4s/Yfzmx9hib/jquery.ms.js"></script>
<link href="http://static.tumblr.com/ek9ly4s/0WMmx9ghw/homemade-ii.css" rel="stylesheet">
<div id="header">
<div class="xnav">
{block:ifshowblogtitle} <img src="http://static.tumblr.com/ksc6s4f/dWtnk041m/cnocle-logo.png"/> // {/block:ifshowblogtitle}
{block:ifshowdescription}
{block:Description}<p>{Description}</p> //{/block:Description} {/block:ifshowdescription}
Home /
{block:AskEnabled}{text:Ask Title} /{/block:AskEnabled}
{block:ifLinkOneTitle}
{text:Link One Title} / {/block:ifLinkOneTitle}
{block:ifLinkTwoTitle}
{text:Link Two Title} / {/block:ifLinkTwoTitle}
{block:ifLinkThreeTitle}
{text:Link Three Title} / {/block:ifLinkThreeTitle}
{block:ifLinkFourTitle}
{text:Link Four Title} / {/block:ifLinkFourTitle}
{block:ifLinkFiveTitle}
{text:Link Five Title} / {/block:ifLinkFiveTitle}
{block:HasPages}{block:Pages}{Label} / {/block:Pages} {/block:HasPages}
{block:iftextonlineusercounter}
{text:text online user counter} /
{/block:iftextonlineusercounter}
Archive /
Theme
</div><div class="spacer"> </div></div>
<div id="content">
{block:Posts}
<div class = "autopagerize_page_element" >
<div class="entry">
{block:Photo}
{block:IndexPage}
<div class="photo">
<img src="{PhotoUrl-250}" alt="{PhotoAlt}"/>
</div>
{/block:IndexPage}
{/block:Photo}
{block:PermalinkPage}
<div style="display:block;">
<img src="{PhotoUrl-500}" alt="{PhotoAlt}"/>
{block:NoteCount}{NoteCountWithLabel}
<div style="margin-top:5px;"></div>{/block:NoteCount}
{block:HasTags} · {block:Tags} #{Tag}
<div style="margin-top:5px;"></div>{/block:Tags}{/block:hasTags}
{block:Caption}{Caption}{/block:Caption}{/block:PermalinkPage}
{block:PostNotes}
<div style="width:500px;height:250px;overflow-y:scroll;overflow-x:hidden;margin-left:-5px;">{PostNotes}</div>
{/block:PostNotes}
</div>
</div>
{/block:Posts}
<!--
Start of Modal
-->
<div class="modal-content drop-shadow">
<div class="product-desc">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium adipisci aliquam corporis distinctio ea in incidunt ipsum molestiae molestias mollitia officiis possimus quis quod, ratione veritatis voluptate voluptatibus? A, amet.</div>
<div class="product-image"><img src="" alt="{PhotoAlt}" /></div>
</div>
<div class="modal-overlay"></div>
<!--
End of Modal
-->
<script type="text/javascript">
$(document).ready(function() {
$(".entry").click(function(){
var imgSrc = $(".photo").children("img").attr("src");
$(".product-image img").attr("src",imgSrc);
$(".modal-overlay").addClass("modal-show");
$(".modal-content").addClass("modal-content-show");
});
$(".btn-modal-close").click(function() {
$(".modal-overlay").removeClass("modal-show");
});
$(".modal-overlay").click(function() {
$(".modal-overlay").removeClass("modal-show");
$(".modal-content").removeClass("modal-content-show");
})
});
</script>
</div>