Use component/tag contents in Marko template - marko

Say I'd like to have a component that wraps its contents (aka children):
<article>
<header>${input.heading}</header>
<section> ... contents come here ... </section>
<article>
Then use it like:
...
<my-article heading='Test'>
Lorem ipsum <s>dolor</s> sit amet
</my-article>
How do I access the contents in the template?

Or a simple solution:
<article>
<header>${input.heading}</header>
<section><include(input) /></section>
<article>
And use:
<my-article heading='Test'>
Lorem ipsum <s>dolor</s> sit amet
</my-article>

Found the solution - <include> reusable/nested content:
<article>
<header>${input.heading}</header>
<section><include(input.body) /></section>
</article>
Then use it like:
<my-article heading='Hello'>
<#body>Lorem ipsum dolor sit <u>amet</u></#body>
</my-article>

Related

Flexbox container for dynamic content

I am working on a single page template that will be used by a proprietary CMS. It is basically a header, 3 columns in majority of page, and a footer. In the middle column the CMS will inject content into it. The content can be of varying length.
I need the footer to not be fixed, so that everything resizes dynamically if the content is larger than the container's initial vh. How do I handle this?
<!doctype html>
<header>
<style type="text/css">
html, body {
margin: 0;
}
#header {
display: flex;
background: #000000;
height: 10vh;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
border-bottom: 2px solid black;
}
#header-left {
background: red;
flex-basis: 50%;
flex-shrink: 0;
}
#header-right {
background: green;
flex-basis: 50%;
flex-shrink: 0;
align-content: flex-end;
}
#content-container {
flex-direction: row;
display: flex;
background: #cccccc;
height: 80vh;
justify-content: space-between;
}
#sidebar-left {
background: purple;
flex-basis: 20%;
}
#sidebar-right {
background: yellow;
flex-basis: 15%;
}
#content {
border-left: 2px solid black;
border-right: 2px solid black;
flex-basis: 65%;
flex-grow:
}
#footer {
display: flex;
background: white;
height: 60px;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
border-top: 2px solid black;
}
#footer-left {
background: pink;
flex-basis: 50%;
}
#footer-right {
background: orange;
flex-basis: 50%;
align-content: flex-end;
}
</style>
</header>
<body>
<div id="header">
<div id="header-left">
HEADER-LEFT HERE
</div>
<div id="header-right">
HEADER-RIGHT HERE
</div>
</div>
<div id="content-container">
<div id="sidebar-left">
SIDEBAR-LEFT
</div>
<div id="content">
CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum
</div>
<div id="sidebar-right">
SIDEBAR-RIGHT
</div>
</div>
<div id="footer">
<div id="footer-left">
FOOTER-LEFT
</div>
<div id="footer-right">
FOOTER-RIGHT
</div>
</div>
</body>
</html>
just change the height: 80vh to min-height: 80vh;
<!doctype html>
<header>
<style type="text/css">
html, body {
margin: 0;
}
#header {
display: flex;
background: #000000;
height: 10vh;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
border-bottom: 2px solid black;
}
#header-left {
background: red;
flex-basis: 50%;
flex-shrink: 0;
}
#header-right {
background: green;
flex-basis: 50%;
flex-shrink: 0;
align-content: flex-end;
}
#content-container {
flex-direction: row;
display: flex;
background: #cccccc;
min-height: 80vh;
justify-content: space-between;
}
#sidebar-left {
background: purple;
flex-basis: 20%;
}
#sidebar-right {
background: yellow;
flex-basis: 15%;
}
#content {
border-left: 2px solid black;
border-right: 2px solid black;
flex-basis: 65%;
flex-grow:
}
#footer {
display: flex;
background: white;
height: 60px;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
border-top: 2px solid black;
}
#footer-left {
background: pink;
flex-basis: 50%;
}
#footer-right {
background: orange;
flex-basis: 50%;
align-content: flex-end;
}
</style>
</header>
<body>
<div id="header">
<div id="header-left">
HEADER-LEFT HERE
</div>
<div id="header-right">
HEADER-RIGHT HERE
</div>
</div>
<div id="content-container">
<div id="sidebar-left">
SIDEBAR-LEFT
</div>
<div id="content">
CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum CONTENT lorum ipsum lorum ipsum
</div>
<div id="sidebar-right">
SIDEBAR-RIGHT
</div>
</div>
<div id="footer">
<div id="footer-left">
FOOTER-LEFT
</div>
<div id="footer-right">
FOOTER-RIGHT
</div>
</div>
</body>
</html>

Grav/Twig - Implement text headlines as part of a modular page

I would like to implement a News Headline banner.
The HTML code for that headline banner is this:
<!-- hot news start -->
<div class="col-sm-16 hot-news hidden-xs">
<div class="row">
<div class="col-sm-15"> <span class="ion-ios7-timer icon-news pull-left"></span>
<ul id="js-news" class="js-hidden">
<li class="news-item">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor</li>
<li class="news-item">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium</li>
<li class="news-item">Donec quam felis, ultricies nec, pellentesque eu</li>
<li class="news-item">Nulla consequat massa quis enim. Donec pede justo, fringilla</li>
<li class="news-item"> Donec pede justo, fringilla vel, aliquet nec, vulputate eget ultricies nec, pellentesque</li>
<li class="news-item">In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo</li>
<li class="news-item">Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis </li>
</ul>
</div>
<div class="col-sm-1 shuffle text-right"><span class="ion-shuffle"></span></div>
</div>
</div>
<!-- hot news end -->
I would like to make this so it can be used in a modular page. The idea is that the user could just type something similar to this:
news:
text: Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
url: foo.com/lorem
news:
text: Sed ut perspiciatis unde omnis iste natus error sit voluptatem
url: foo.com/sedut
...
And the whole block would be rendered. I would like to know how to implement that in Grav/Twig. If someone answers please bear in mind that I am relatively new to Grav, so a verbose answer is more appreciated than a concise one.
I will begin with the simplest solution that would achieve your goal.
At first, I will treat this as a regular page, not a modular page.
In your user file, let's define a new template within your current template. Antimatter is the default one, so I'll work with this one. Create news.html.twig in user - templates - antimatter folder and paste in the following code block.
{# user/templates/antimatter/news.html.twig #}
<div class="col-sm-16 hot-news hidden-xs">
<div class="row">
<div class="col-sm-15"> <span class="ion-ios7-timer icon-news pull-left"></span>
<ul id="js-news" class="js-hidden">
{% for news in page.header.news %}
<li class="news-item">{{news.text}}</li>
{% endfor %}
</ul>
</div>
<div class="col-sm-1 shuffle text-right"><span class="ion-shuffle"></span></div>
</div>
This is a twig way how to loop through the frontmatter content which we'll create now.
All the pages in Grav are stored in user - pages folder. The name of the folder specifies among others the relative address of the page, the number is just for ordering purposes and irrelevant for now, the markdown file inside specifies which template to use.
Let's create in pages a folder called 02.news and inside a file called news.md. Therefore, it'll use news template we created earlier. Paste this into the news.md
<!-- user/pages/02.news/news.md -->
---
news:
-
text: Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
url: foo.com/lorem
-
text: Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
url: foo.com/lorem
-
text: Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
url: foo.com/lorem
---
Doing this we create a news array and each entry has text and url. Now you have access to it through page.header.news and you can retrieve it's attributes.
I'm not all too sure how would you imagine turning this into a modular design. One way that comes to mind is to have a parent page and within have modular pages for various topics such as business news or politics. Let's try that.
Start with a parent template, let's call it a newscontainer.html.twig. In it we need to specify that grav should retrieve all it's modular children and iterate over. Grav calls these children a collection of pages. We'll just want to spit out their content.
{# user/templates/antimatter/newscontainer.html.twig #}
{% for module in page.collection() %}
{{module.content}}
{% endfor %}
Now in the 02.news folder, change the markdown file name to newscontainer so it uses our new template. Now it serves as a parent container for all the news. Inside, specify that it should load into it's page.collection all it's modular children. The limit means that maximum 20 modular pages will be loaded.
<!-- user/pages/02.news/newscontainer.md -->
---
title: News
content:
items: '#self.modular'
limit: 20
---
In the templates folder, create a new one called modular and move the news.html.twig template we made earlier into it. Modular pages look for templates in this folder.
Almost there. Lastly, in 02.news folder, we can now create modular pages. You can do that by creating new folders that start with _ instead of numbers, so for example create _politics and _business. You can copy now the news.md we made earlier into each and change the content as you wish. It should display correctly if you go to whateverpage.com/news
In the end, the pages structure looks like this
pages
01.Home
default.md
02.News
newscontainer.md
_business
news.md
_politics
news.md
As additional comment to Dan's answer, here is what I finally did:
Defined a partial twig template
<!-- hot news start -->
<div class="col-sm-16 hot-news hidden-xs">
<div class="row">
<div class="col-sm-15"> <span class="ion-ios7-timer icon-news pull-left"></span>
<ul id="js-news" class="js-hidden">
{% set items = page.find('/ticker').children %}
{% for item in items %}
<li class="news-item">{{ item.title }} </li>
{% endfor %}
</ul>
</div>
<div class="col-sm-1 shuffle text-right"><span class="ion-shuffle"></span></div>
</div>
</div>
<!-- hot news end -->
Populated empty pages with just titles under /ticker folder (invisible).
The template can be used anywhere with {% include %} and the user just needs to add or delete empty pages and set up the title he wants to display as headline/news.
I found this approach was easier than any other one.

Populate templates with content without Angular

I have a fully functioning prototype of an HTML5 news card, and I need to populate 50 or so cards with unique content. I am asking for suggestions for a more efficient way to add content to each card other than copying, cutting, and pasting from the Excel spreadsheet. The spreadsheet's columns contain each card's news category, date, title, and external URL. I have also just been asked to include the image from the news article that the card links to - I cannot imagine how that could be automated. This project uses Bootstrap styling, data-category attribute on a tag in each card, and is a Laravel website; it does not include Angular, Mustache, Handlebars, or a templating pattern. Is there a way I could create a custom template for these news cards without needing to install a framework or template engine? Could I use data attributes?
Here is the HTML for one card:
<div class="col-lg-4 col-md-6">
<section class="news-box" data-category="blog">
<figure>
<img src="/material-icons/ic_recent_actors_black_24dp/web/ic_recent_actors_black_24dp_2x.png" class="img-responsive opacity-3">
<figcaption>Blog</figcaption>
</figure>
<h3 class="h6">Title of Blog Post</h3>
<figure>
<img src="images/news/pic2.jpg" class="img-responsive">
</figure>
<p>luctus et ultrices posuere cubilia Curae; quam erat volutpat. Phasellus dignissim euismod luctus.In leo mauris, blandit quismalesuada lobortis, fringilla a ipsum.</p>
</section>
</div>
So this might not be the best answer, but these are my 2 cents.
You will first have to convert your Excel sheet to csv and then to a json object. I think this can be easily achieved with online converters like this: http://www.convertcsv.com/csv-to-json.htm (haven't tried that myself, just pasted the first google result). Your json object will then look like var foo = [{...},{...},...] (see snipet)
Create your "card template" with dummy placeholders like card_title card_img. Hide it.
In your js file, iterate over all the elements in your json object and use the template you just created to replace all the placeholders. (var newItem = myTemplate.replace('blog_title',val.blog_title)...)
Append the resulting html snippet to the cards container.
$(document).ready(function(){
var template = $(".card-template").html(); //get the card template html
$.each(foo, function(idx, val){ //iterate over the json object
var newCard = template.replace('card_title',val.title).replace('card_image',val.img).replace('card_content',val.content); //make a copy of the template and replace the placeholders with the real data
$(".cards-container").append(newCard); //append the card to the container row
});
});
var foo = [
{
'title':'Gotta catch em all',
'img':'http://i.imgur.com/tmgWXUP.jpg',
'content':'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua'
},
{
'title':'Trumpers trumping Trump',
'img':'http://i.imgur.com/C7z53mE.gif',
'content':'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua'
},
{
'title':'Aint no hacker',
'img':'http://i.imgur.com/vQGnFD4.jpg',
'content':'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua'
}
]
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row cards-container">
<!-- inject cards here -->
</div>
<div class="card-template hide">
<div class="col-xs-3">
<h2>card_title</h2>
<img src="card_image" class="img-responsive">
<p>card_content</p>
</div>
</div>
You could also try to do it with vanilla js, but it's up to you.
$(document).ready(function(){
var template = $(".card-template").html(); //get the card template html
$.each(foo, function(idx, val){ //iterate over the json object
var newCard = template.replace('card_title',val.title).replace('card_image',val.img).replace('card_content',val.content); //make a copy of the template and replace the placeholders with the real data
$(".cards-container").append(newCard); //append the card to the container row
});
});
var foo = [
{
'title':'Gotta catch em all',
'img':'http://i.imgur.com/tmgWXUP.jpg',
'content':'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua'
},
{
'title':'Trumpers trumping Trump',
'img':'http://i.imgur.com/C7z53mE.gif',
'content':'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua'
},
{
'title':'Aint no hacker',
'img':'http://i.imgur.com/vQGnFD4.jpg',
'content':'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua'
}
]
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row cards-container">
<!-- inject cards here -->
</div>
<div class="card-template hide">
<div class="col-xs-3">
<h2>card_title</h2>
<img src="card_image" class="img-responsive">
<p>card_content</p>
</div>
</div>

text-overflow:ellipsis with MathJax?

Is it possible to get text-overflow:ellipsis to work with MathJax?
Here is a (non-working) example (on JSFiddle)
The HTML:
<!doctype html>
<script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<div id="test">
\[
\text{2014-01-05} \quad
\begin{cases} \text{Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum} \\
\text{Lorem ipsum} \\
\text{Lorem ipsum} \\
\end{cases}
\]
</div>
<div id="test">
Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum
</div>
And the CSS:
#test{
display: inline-block;
width: 20em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
As you can see, text-overflow:ellipsis works for the div without any MathJax content but not for the div with MathJax content. Is there any solution or workaround?
There is currently no way of making this work.
While the MathML spec provides two comparable values for overflow -- truncate and elide -- neither one is implemented in MathJax yet.
On the bright side, linebreaking is supported for display-style mathematics.
Addendum: some restrictions apply. Not all linebreaking methods are supported; in particular, linebreaking within token elements and some alignment options are not supported.

Is it possible to create a pinterest-like layout with Bootstrap only?

I am trying to the get my head around this for quite some time now:
Is it possible to create a pinterest Layout with Twitter Bootstrap only?
I know there are jQuery Plugins like Masonry, but is there no way without them?
Thanks
Found a (free) template at http://bragthemes.com/demo/pinstrap/. It's supposed to have all you are asking for. Haven't had time to check it out, though.
Edit 2016-03-15: Bootstrap 4 allows this out of the box here. It's still in alpha, but we're getting there.
Found this solution, works within bootstrap (works even without defining column sizes), doesn't require javascript -- I snapped it into a project and it works beautifully:
http://www.bootply.com/118335
Bless you #katiejones!
EDIT: This is now out of the box in boostrap 4 http://v4-alpha.getbootstrap.com/components/card/#card-columns
Sure Thing. Took me a while to work out. Hope this helps!
Apologies for the code dump but its necessary to show the grid working.
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/masonry.js"></script>
<script type="text/javascript" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/imagesLoaded.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" integrity="sha512-dTfge/zgoMYpP7QbHy4gWMEGsbsdZeCXz7irItjcC3sPUFtf0kuFbDz/ixG7ArTxmDjLXDmezHubeNikyKGVyQ==" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css" integrity="sha384-aUGj/X2zp5rLCbBxumKTCw2Z50WgIr1vs/PFN4praOTvYXWlVyh2UtNUU0KAUhAX" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js" integrity="sha512-K1qjQ+NcF2TYO/eI3M6v8EiNYZfA95pQumfvcVrTHtwQVDG+aHRqLi/ETn2uB+1JqwYqVG3LIvdm9lj6imS/pQ==" crossorigin="anonymous"></script>
</head>
<div class="container">
<div class="row masonry-container">
<div class="col-xs-6 col-sm-3 col-md-3 item">
<div class="thumbnail">
<img src="http://lorempixel.com/150/200/abstract" alt="">
<div class="caption">
<h3>Thumbnail label</h3>
<p>Lorem ipsumLorem ipsum dolosit amet, consectetur adipisicing eli dolor sit amet, consectetur adipisicing elit. </p>
</div>
</div>
</div><!--/.item -->
<div class="col-xs-6 col-sm-3 col-md-3 item">
<div class="thumbnail">
<img src="http://lorempixel.com/150/200/abstract" alt="">
<div class="caption">
<h3>Thumbnail label</h3>
<p>Lorem ipsumLorem ipdolor sit amet, consectetur adipisicing eli dolor sit amet, consectetur adipisicing elit. </p>
</div>
</div>
</div><!--/.item -->
<div class="col-xs-6 col-sm-3 col-md-3 item">
<div class="thumbnail">
<img src="http://lorempixel.com/150/200/abstract" alt="">
<div class="caption">
<h3>Thumbnail label</h3>
<p>Lorem ipsumLorem ipsum dolor sit amet, consectetur adipisicing eliLorem ipsum dolor sit amet, consectetur adipisicing eliLorem ipsum dolor sit amet, consectetur adipisicing eli dolor sit amet, consectetur adipisicing elit. </p>
</div>
</div>
</div><!--/.item -->
<div class="col-xs-6 col-sm-3 col-md-3 item">
<div class="thumbnail">
<img src="http://lorempixel.com/150/200/abstract" alt="">
<div class="caption">
<h3>Thumbnail label</h3>
<p>Lorem ipsumLorem ipsum dolor sit amet, consectetur adipisicing eliLorem ipsum dolor sit amet, consectetur adipisicing eliLorem ipsum dolor sit amet, consectetur adipisicing eli dolor sit amet, consectetur adipisicing elit. </p>
</div>
</div>
</div><!--/.item -->
<div class="col-xs-6 col-sm-3 col-md-3 item">
<div class="thumbnail">
<img src="http://lorempixel.com/150/200/abstract" alt="">
<div class="caption">
<h3>Thumbnail label</h3>
<p>Lorem ipsumLorem ipsum dolor ctetur adipisicing eli dolor sit amet, consectetur adipisicing elit. </p>
</div>
</div>
</div><!--/.item -->
<div class="col-xs-6 col-sm-3 col-md-3 item">
<div class="thumbnail">
<img src="http://lorempixel.com/150/200/abstract" alt="">
<div class="caption">
<h3>Thumbnail label</h3>
<p>Lorem ipsumLorem ipdolor sit amet, consectetur adipisicing eli dolor sit amet, consectetur adipisicing elit. </p>
</div>
</div>
</div><!--/.item -->
<div class="col-xs-6 col-sm-3 col-md-3 item">
<div class="thumbnail">
<img src="http://lorempixel.com/150/200/abstract" alt="">
<div class="caption">
<h3>Thumbnail label</h3>
<p>Lorem ipsumLorem ipsum dolor sit amet, consectetur adipisicing eliLorem ipsum dolor sit amet, consectetur adipisicing eliLorem ipsum dolor sit amet, consectetur adipisicing eli dolor sit amet, consectetur adipisicing elit. </p>
</div>
</div>
</div><!--/.item -->
<div class="col-xs-6 col-sm-3 col-md-3 item">
<div class="thumbnail">
<img src="http://lorempixel.com/150/200/abstract" alt="">
<div class="caption">
<h3>Thumbnail label</h3>
<p>Lorem ipsumLorem ipsum dolor sit amet, consectetur adipisicing eliLorem ipsum dolor sit amet, consectetur adipisicing eliLorem ipsum dolor sit amet, consectetur adipisicing eli dolor sit amet, consectetur adipisicing elit. </p>
</div>
</div>
</div><!--/.item -->
<div class="col-xs-6 col-sm-3 col-md-3 item">
<div class="thumbnail">
<img src="http://lorempixel.com/150/200/abstract" alt="">
<div class="caption">
<h3>Thumbnail label</h3>
<p>Lorem ipsumLorem ipsum dolor ctetur adipisicing eli dolor sit amet, consectetur adipisicing elit. </p>
</div>
</div>
</div><!--/.item -->
</div> <!--/.masonry-container -->
</div><!--/.tab-panel -->
<style type="text/css">
body {
padding-top: 50px;
}
.main-container {
padding: 10px 15px;
}
.p {
text-align: center;
}
</style>
<script type="text/javascript">
/* Demo Scripts for Making Twitter Bootstrap 3 Tab Play Nicely With The Masonry Library
* on SitePoint by Maria Antonietta Perna
*/
//Initialize Masonry inside Bootstrap 3 Tab component
(function( $ ) {
var $container = $('.masonry-container');
$container.imagesLoaded( function () {
$container.masonry({
columnWidth: '.item',
itemSelector: '.item'
});
});
//Reinitialize masonry inside each panel after the relative tab link is clicked -
$('a[data-toggle=tab]').each(function () {
var $this = $(this);
$this.on('shown.bs.tab', function () {
$container.imagesLoaded( function () {
$container.masonry({
columnWidth: '.item',
itemSelector: '.item'
});
});
}); //end shown
}); //end each
})(jQuery);
</script>
Yes, it is possible but with some limitations.
Principle
Each column is a div (or section depending upon the meaning of your layout)
Within each column each tile is also be a div, or img etc. depending upon your design.
Practice
To make the columns you can use the following various techniques:
float the columns
display: inline-block the columns
Use the new flexible box API (non-standard implementations are creeping into modern browsers)
Use the new grid positioning API (although I'd avoid this for now as it's not supported hardly at all)
Then place various tiles (divs) in each column. Again, depending upon your design/layout you could replace the column-divs with uls, and have a list of tiles (lis). I can't speak as to whether that is semantically correct for your design.
Limitations
Resizing the Pinterest page maintains the general position of most elements i.e. elements at the top of a column generally stays near the top, even when the number of columns is adjusted for the browser width - the pure CSS solution won't do that out of the box.
Work-Arounds
While not a perfect solution, you can use media queries to influence the position of various elements.
With some time, one could get pretty close to the Pinterest layout - that said, there's probably a good reason they chose to implement said layout with JavaScript.
I know my answer is late. but just wanted this common question to be up dated. I found out 3 latest implementations.
isotope. Found this on bootstrap website. Works well with infinite-scroll to build infinite scroll web pages too.
Salvattore. This is achived with pure CSS and JS. JS is only used to pull data.
masonry.desandro.com. This is a JS intensive implementation. but it has its own features.
Since Bootstrap 4, the .card-columns class is available.
Specifications in there documentation here. It makes a nice Pinterest-like grid. 😌
<div class="card-columns">
<div class="card" id="card1"></div>
<div class="card" id="card2"></div>
<div class="card" id="card3"></div>
<div class="card" id="card4"></div>
<div class="card" id="card..."></div>
</div>
About the number of columns, though, I had trouble adapting it to different screen sizes. I finally managed to do it with :
#media (max-width: 575.98px){
.card-columns {
column-count: 1; }
}
#media (min-width: 576px){
.card-columns {
column-count: 2; }
}
#media (min-width: 768px){
.card-columns {
column-count: 3; }
}
#media (min-width: 992px){
.card-columns {
column-count: 4; }
}
#media (min-width: 1200px){
.card-columns {
column-count: 4; }
}
There we have a stuff named: bootstrap-waterfall:
http://mystist.github.io/bootstrap-waterfall/
But in fact, this plugin does not need bootstrap as it's dependencies. It's depends on whether you want to use bootstrap as your pin's markups or just style it yourself.
<div class="card-deck">
<div class="card">
<img class="card-img-top" src="..." alt="Card image cap">
<div class="card-block">
<h4 class="card-title">Card title</h4>
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
</div>
<div class="card-footer">
<small class="text-muted">Last updated 3 mins ago</small>
</div>
</div>
<div class="card">
<img class="card-img-top" src="..." alt="Card image cap">
<div class="card-block">
<h4 class="card-title">Card title</h4>
<p class="card-text">This card has supporting text below as a natural lead-in to additional content.</p>
</div>
<div class="card-footer">
<small class="text-muted">Last updated 3 mins ago</small>
</div>
</div>
<div class="card">
<img class="card-img-top" src="..." alt="Card image cap">
<div class="card-block">
<h4 class="card-title">Card title</h4>
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.</p>
</div>
<div class="card-footer">
<small class="text-muted">Last updated 3 mins ago</small>
</div>
</div>
</div>
For everyone who dont want want to go through the hassle of cross browser compatibility, here is a PHP solution. Assuming you have your data in an array,
<?php $iColumns = 4;?>
<?php for($i=0; $i < $iColumns; ++$i):?>
<div class="span3">
<?php
$j=$i;
while( isset( $aData[$j] ) ):
$oItem = $aData[$j]
?>
<div class="thumbnail" style="margin-top:10px;">
<a href="">
<img src="" alt=""/>
</a>
<h3>title</h3>
<p>caption</p>
</div>
<?php
$j=$j+$iColumns;
endwhile;?>
</div>
<?php endfor;?>

Resources