Place text inside an amp-img with layout="responsive" - background-image

I have an amp-img with layout="responsive" and I need to place some text inside it, or on top of it, if you prefer to say it that way. The amp-img will fill the width of the screen and the height will be determined by amp-img so that the entire image is visible and the aspect ratio is maintained.
Is there a way to do this?
I could place the image in the background, but I would lose the responsive sizing provided by amp-img. I have tried this using a background-size of cover or contain, but I the image always ended up being cropped, either on the right or the bottom.
I also tried placing the text with position:absolute, but can not get the text on top of the image. Here is one attempt, which ends up with the text below the image:
<div style="position:relative">
<amp-img src="/images/#Model.ImageUrl" layout="responsive" width="1920" height="1080" alt=""></amp-img> #* 16 x 9 *#
<div class="clearfix" style="padding-top:25%; padding-bottom:10%; position:absolute; z-index:1">
<div class="mx-auto md-col-9">
<h2 class="tx-g2 tx-center ml-1 mr-1 shadow mb-0" style="{text-transform:uppercase;}">
<amp-fit-text width="400" height="20" layout="responsive" max-font-size="75">
#Html.Raw(Model.Title)
</amp-fit-text>
</h2>
</div>
</div>
</div>
Is there a way to get the image sized correctly and also place text on top of it?
PS. Will someone create a tag for amp-fit-text.

Your <div> containing <amp-fit-text> is missing a width. See a simplier example below.
<!doctype html>
<html ⚡>
<head>
<meta charset="utf-8">
<title> Hello World</title>
<script async src="https://cdn.ampproject.org/v0.js"></script>
<script async custom-element="amp-fit-text" src="https://cdn.ampproject.org/v0/amp-fit-text-0.1.js"></script>
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style amp-custom>
</style>
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}#-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}#-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}#-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}#-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}#keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
</head>
<body>
<div style="position: relative;">
<amp-img src="https://omoiwords.com/stories-poster.jpeg-2048.jpeg"
width="1228" height="819" layout="responsive"></amp-img>
<div style="background-color: rgba(0,0,0,0.7);
color: white; width: 80%; position:absolute; top:10%; left: 10%;">
<amp-fit-text
width="200" height="50" layout="responsive">
Lorem ipsum dolor sit amet, has nisl nihil convenire et, vim at aeque inermis reprehendunt.
Lorem ipsum dolor sit amet, has nisl nihil convenire et, vim at aeque inermis reprehendunt.
</amp-fit-text>
</div>
</div>
</body>
</html>

<div style="position: relative;">
<amp-img src="https://omoiwords.com/stories-poster.jpeg-2048.jpeg"
width="1228" height="819" layout="responsive"></amp-img>
<div style="background-color: rgba(0,0,0,0.7);
color: white; width: 80%; position:absolute; top:10%; left: 10%;">
<amp-fit-text
width="200" height="50" layout="responsive">
Lorem ipsum dolor sit amet, has nisl nihil convenire et, vim at aeque inermis reprehendunt.
Lorem ipsum dolor sit amet, has nisl nihil convenire et, vim at aeque inermis reprehendunt.
</amp-fit-text>
</div>
</div>
<script async custom-element="amp-fit-text" src="https://cdn.ampproject.org/v0/amp-fit-text-0.1.js"></script>

I have found a workaround using amp-carousel with a single slide:
<amp-carousel layout="responsive" height="1080" width="1920" type="slides" style="position:relative;">
<div style="background:linear-gradient(rgba(0,0,0,0), rgba(0,0,0,0)),
url(/images/#Model.ImageUrl);
background-size:contain; background-repeat:no-repeat; width:100%; height:100%;">
<div class="clearfix" style="padding-top:25%; padding-bottom:10%;">
<div class="mx-auto md-col-9">
<h2 class="tx-g2 tx-center ml-1 mr-1 shadow mb-0" style="{text-transform:uppercase;}">
<amp-fit-text width="400" height="20" layout="responsive" max-font-size="75">
#Html.Raw(Model.Title)
</amp-fit-text>
</h2>
</div>
</div>
</div>

Related

How to render full HTML document with flutter_html package?

I'm trying to render a full HTML document in a scrollable view but I always got this error
════════ Exception caught by rendering library ═════════════════════════════════
RenderBox was not laid out: _RenderSingleChildViewport#1741c relayoutBoundary=up7 NEEDS-PAINT
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1940 pos 12: 'hasSize'
The relevant error-causing widget was
SingleChildScrollView
My code looks like this
Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(...),
Padding(
padding: EdgeInsets.all(16),
child: Html.fromDom(
document: dom.Document.html(data['generated']),
shrinkWrap: true,
)
)
],
),
)
)
The error appears only when I use Html.fromDom, it works perfectly with Html for rendering simple elements.
I've also tried with a ListView, constainted the widget, use Expanded or Flexible but nothing works and it's always the same error.
What's the right way for do this ?
Thanks you
I cannot be sure the cause is the same as you haven't given the HTML which causes the error. However, I encountered the same error and traced it to a bug in flutter_html which throws when there are nested tables in the HTML. As of today the issue is still open but v3.0.0-alpha.2 of the library has a workaround which renders text "TABLE SECTION" instead of the table. Not perfect but at least doesn't crash the rendering.
Strangely I just run your code on this example and worked like a charm, meaning that made the it's not the widgets and yes the data['generated'] or maybe somenthing inside the widgets that you occult, this is the example that I used:
var htmlData = r"""
<p id='top'><a href='#bottom'>Scroll to bottom</a></p>
<h1>Header 1</h1>
<h2>Header 2</h2>
<h3>Header 3</h3>
<h4>Header 4</h4>
<h5>Header 5</h5>
<h6>Header 6</h6>
<h3>Ruby Support:</h3>
<p>
<ruby>
漢<rt>かん</rt>
字<rt>じ</rt>
</ruby>
is Japanese Kanji.
</p>
<h3>Support for maxLines:</h3>
<h5>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vestibulum sapien feugiat lorem tempor, id porta orci elementum. Fusce sed justo id arcu egestas congue. Fusce tincidunt lacus ipsum, in imperdiet felis ultricies eu. In ullamcorper risus felis, ac maximus dui bibendum vel. Integer ligula tortor, facilisis eu mauris ut, ultrices hendrerit ex. Donec scelerisque massa consequat, eleifend mauris eu, mollis dui. Donec placerat augue tortor, et tincidunt quam tempus non. Quisque sagittis enim nisi, eu condimentum lacus egestas ac. Nam facilisis luctus ipsum, at aliquam urna fermentum a. Quisque tortor dui, faucibus in ante eget, pellentesque mattis nibh. In augue dolor, euismod vitae eleifend nec, tempus vel urna. Donec vitae augue accumsan ligula fringilla ultrices et vel ex.</h5>
<h3>Support for <code>sub</code>/<code>sup</code></h3>
Solve for <var>x<sub>n</sub></var>: log<sub>2</sub>(<var>x</var><sup>2</sup>+<var>n</var>) = 9<sup>3</sup>
<p>One of the most <span>common</span> equations in all of physics is <br /><var>E</var>=<var>m</var><var>c</var><sup>2</sup>.</p>
<h3>Inline Styles:</h3>
<p>The should be <span style='color: blue;'>BLUE style='color: blue;'</span></p>
<p>The should be <span style='color: red;'>RED style='color: red;'</span></p>
<p>The should be <span style='color: rgba(0, 0, 0, 0.10);'>BLACK with 10% alpha style='color: rgba(0, 0, 0, 0.10);</span></p>
<p>The should be <span style='color: rgb(0, 97, 0);'>GREEN style='color: rgb(0, 97, 0);</span></p>
<p>The should be <span style='background-color: red; color: rgb(0, 97, 0);'>GREEN style='color: rgb(0, 97, 0);</span></p>
<p style="text-align: center;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
<p style="text-align: right;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
<p style="text-align: justify;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
<p style="text-align: center;"><span style="color: rgba(0, 0, 0, 0.95);">blasdafjklasdlkjfkl</span></p>
<h3>Table support (with custom styling!):</h3>
<p>
<q>Famous quote...</q>
</p>
<table>
<colgroup>
<col width="50%" />
<col span="2" width="25%" />
</colgroup>
<thead>
<tr><th>One</th><th>Two</th><th>Three</th></tr>
</thead>
<tbody>
<tr>
<td rowspan='2'>Rowspan\nRowspan\nRowspan\nRowspan\nRowspan\nRowspan\nRowspan\nRowspan\nRowspan\nRowspan</td><td>Data</td><td>Data</td>
</tr>
<tr>
<td colspan="2"><img alt='Google' src='https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png' /></td>
</tr>
</tbody>
<tfoot>
<tr><td>fData</td><td>fData</td><td>fData</td></tr>
</tfoot>
</table>
<h3>Custom Element Support (inline: <bird></bird> and as block):</h3>
<flutter></flutter>
<flutter horizontal></flutter>
<h3 id='middle'>SVG support:</h3>
<svg id='svg1' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'>
<circle r="32" cx="35" cy="65" fill="#F00" opacity="0.5"/>
<circle r="32" cx="65" cy="65" fill="#0F0" opacity="0.5"/>
<circle r="32" cx="50" cy="35" fill="#00F" opacity="0.5"/>
</svg>
<h3>List support:</h3>
<ol>
<li>This</li>
<li><p>is</p></li>
<li>an</li>
<li>
ordered
<ul>
<li>With<br /><br />...</li>
<li>a</li>
<li>nested</li>
<li>unordered
<ol style="list-style-type: lower-alpha;" start="5">
<li>With a nested</li>
<li>ordered list</li>
<li>with a lower alpha list style</li>
<li>starting at letter e</li>
</ol>
</li>
<li>list</li>
</ul>
</li>
<li>list! Lorem ipsum dolor sit amet.</li>
<li><h2>Header 2</h2></li>
<h2><li>Header 2</li></h2>
</ol>
<h3>Link support:</h3>
<p>
Linking to <a href='https://github.com'>websites</a> has never been easier.
</p>
<h3>Image support:</h3>
<h3>Network png</h3>
<img alt='Google' src='https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png' />
<h3>Network svg</h3>
<img src='https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/android.svg' />
<h3>Local asset png</h3>
<img src='asset:assets/html5.png' width='100' />
<h3>Local asset svg</h3>
<img src='asset:assets/mac.svg' width='100' />
<h3>Data uri (with base64 support)</h3>
<img alt='Red dot (png)' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==' />
<img alt='Green dot (base64 svg)' src='data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB2aWV3Qm94PSIwIDAgMzAgMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxjaXJjbGUgY3g9IjE1IiBjeT0iMTAiIHI9IjEwIiBmaWxsPSJncmVlbiIvPgo8L3N2Zz4=' />
<img alt='Green dot (plain svg)' src='data:image/svg+xml,%3C?xml version="1.0" encoding="UTF-8"?%3E%3Csvg viewBox="0 0 30 20" xmlns="http://www.w3.org/2000/svg"%3E%3Ccircle cx="15" cy="10" r="10" fill="yellow"/%3E%3C/svg%3E' />
<h3>Custom source matcher (relative paths)</h3>
<img src='/wikipedia/commons/thumb/e/ef/Octicons-logo-github.svg/200px-Octicons-logo-github.svg.png' />
<h3>Custom image render (flutter.dev)</h3>
<img src='https://flutter.dev/images/flutter-mono-81x100.png' />
<h3>No image source</h3>
<img alt='No source' />
<img alt='Empty source' src='' />
<h3>Broken network image</h3>
<img alt='Broken image' src='https://www.notgoogle.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png' />
<h3>MathML Support:</h3>
<math>
<mrow>
<mi>x</mi>
<mo>=</mo>
<mfrac>
<mrow>
<mrow>
<mo>-</mo>
<mi>b</mi>
</mrow>
<mo>&PlusMinus;</mo>
<msqrt>
<mrow>
<msup>
<mi>b</mi>
<mn>2</mn>
</msup>
<mo>-</mo>
<mrow>
<mn>4</mn>
<mo>&InvisibleTimes;</mo>
<mi>a</mi>
<mo>&InvisibleTimes;</mo>
<mi>c</mi>
</mrow>
</mrow>
</msqrt>
</mrow>
<mrow>
<mn>2</mn>
<mo>&InvisibleTimes;</mo>
<mi>a</mi>
</mrow>
</mfrac>
</mrow>
</math>
<math>
<munderover >
<mo> ∫ </mo>
<mn> 0 </mn>
<mi> 5 </mi>
</munderover>
<msup>
<mi>x</mi>
<mn>2</mn>
</msup>
<mo>⋅</mo>
<mi>&dd;</mi><mi>x</mi>
<mo>=</mo>
<mo>[</mo>
<mfrac>
<mn>1</mn>
<mi>3</mi>
</mfrac>
<msup>
<mi>x</mi>
<mn>3</mn>
</msup>
<msubsup>
<mo>]</mo>
<mn>0</mn>
<mn>5</mn>
</msubsup>
<mo>=</mo>
<mfrac>
<mn>125</mn>
<mi>3</mi>
</mfrac>
<mo>-</mo>
<mn>0</mn>
<mo>=</mo>
<mfrac>
<mn>125</mn>
<mi>3</mi>
</mfrac>
</math>
<math>
<msup>
<mo>sin</mo>
<mn>2</mn>
</msup>
<mo>θ</mo>
<mo>+</mo>
<msup>
<mo>cos</mo>
<mn>2</mn>
</msup>
<mo>θ</mo>
<mo>=</mo>
<mn>1</mn>
</math>
<h3>Tex Support with the custom tex tag:</h3>
<tex>i\hbar\frac{\partial}{\partial t}\Psi(\vec x,t) = -\frac{\hbar}{2m}\nabla^2\Psi(\vec x,t)+ V(\vec x)\Psi(\vec x,t)</tex>
<p id='bottom'><a href='#top'>Scroll to top</a></p>
""";
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.all(16),
child: Html.fromDom(
document: dom.Document.html(htmlData),
shrinkWrap: true,
)
)
],
),
)
);
}
Try this version should work flutter_html: ^2.2.1
Here is an example of an HTML table:
final data =
'<figure class="table"><table style="background-color:rgb(255, 255, 255);border:2px solid rgb(0, 0, 0);"><tbody><tr><th><strong>NAME</strong></th><th>DATE</th><th>DD</th></tr><tr><th>PETER</th><th>2020</th><th>SDSD</th></tr><tr><th>SAM</th><th>2021</th><th>SSS</th></tr></tbody></table></figure>';
Then, in your Html, remember to add style with the following
"table": Style(
backgroundColor: Colors.white,
),
"tr": Style(
padding: const EdgeInsets.all(2),
border: Border.all(color: Colors.black)),
"th": Style(
padding: const EdgeInsets.all(2),
border: Border.all(color: Colors.black)),
"td": Style(
padding: const EdgeInsets.all(2),
border: Border.all(color: Colors.black)),
},
Full Example code:
Import this below in your header
import 'package:flutter_html/flutter_html.dart';
Then return this below:
Container(
child: Html(
data:
'<figure class="table"><table style="background-color:rgb(255, 255, 255);border:2px solid rgb(0, 0, 0);"><tbody><tr><th><strong>NAME</strong></th><th>DATE</th><th>DD</th></tr><tr><th>PETER</th><th>2020</th><th>SDSD</th></tr><tr><th>SAM</th><th>2021</th><th>SSS</th></tr></tbody></table></figure>',
style: {
"table": Style(
backgroundColor: Colors.white,
),
"tr": Style(
padding: const EdgeInsets.all(2),
border: Border.all(color: Colors.black)),
"th": Style(
padding: const EdgeInsets.all(2),
border: Border.all(color: Colors.black)),
"td": Style(
padding: const EdgeInsets.all(2),
border: Border.all(color: Colors.black)),
},
),
),
I had been working on this issue for a while now and came to realise that flutter_html will not be good for this issue. I have used inappwebview to render the html and get dynamic height using script.
double height = 400;
AnimatedContainer(
duration: Duration(milliseconds: 100),
height: height + (height == 0 ? 0 : 50),
child: InAppWebView(
initialData: InAppWebViewInitialData(data: html),
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
supportZoom: false,
javaScriptEnabled: true,
disableHorizontalScroll: false,
disableVerticalScroll: true,
),
),
onLoadError: (controller, url, code, message) =>
print("onLoadError: $url, $code, $message"),
onLoadHttpError:
(controller, url, statusCode, description) => print(
"onLoadHttpError: $url, $statusCode, $description"),
onConsoleMessage: (controller, consoleMessage) {
print('height: ${height}');
height = double.parse(consoleMessage.message);
setState(() {});
},
),
);
the html should be created in the following format
html = """
<html lang="en">
<meta name="viewport" content="width=device-width user-scalable=no zoom=1.1">
<style>img {max-width: 100%; height: auto}</style>
<body>
<div class="id"><div class="container" id="_flutter_target_do_not_delete">${widget.data["html"]}</div>
<script>
function outputsize() {
console.log(document.getElementById("_flutter_target_do_not_delete").offsetHeight);
window.postMessage('flutterTargetHeight', document.getElementById("_flutter_target_do_not_delete").offsetHeight);
}
new ResizeObserver(outputsize).observe(_flutter_target_do_not_delete)
outputsize()
</script>
</body>
</html>
""";
This will render your complex tables and all html content with dynamic height.

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.

remove decoration tags aem sightly

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>

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>