How to output array via ECO in DocPad to build for example an image gallery? - docpad

I have a document with the following frontmatter:
---
layout: default
title: "A Gallery"
image:
- "image-1.jpg"
- "image-2.jpg"
- "image-3.jpg"
---
Now I want to build a list of images in my default-template like this.
<ul>
<li><img src="image-1.jpg" alt=""></li>
<li><img src="image-2.jpg" alt=""></li>
<li><img src="image-3.jpg" alt=""></li>
</ul>
I found this tutorial for javascript loops.
But how do I convert it to ECO/Coffeescript?
Something like this?
<ul>
<% gallery i + 1, for images i in #document.image[i]: %>
<li><%- #document.image[i] %></li>
<% end %>
</ul>

This is how I did it.
In your docpad.coffee file:
site:
pics:
myFirstGallery: [
{name: '/images/mypic.png' h: '180px' w: '100px'},
{name: '/images/mypic2.png' h: '180px' w: '100px'}
]
Then in your eco file:
<ul>
<% for pic in #document.site.pics.myFirstGallery: %>
<li>
<img src="#{pic.name}" width="#{pic.w}" height="#{pic.h}" />
</li>
<% end %>
</ul>
It should be something similar to that. I use Jade so I forget the exact CoffeeScript syntax. Let me know if I got something wrong. The for in syntax comes from CoffeeScript's website. I looked it up on Eco's ReadMe file.

I figured it out after seeing this code in »The Little Book on CoffeeScript« (GitHub Version).
for name, i in ["Roger the pickpocket", "Roderick the robber"]
alert "#{i} - Release #{name}"
For the sample above (see my question) you have to write this code.
<ul>
<% for image, i in #document.image: %>
<li>
<img src="<%- "#{image}" %>" />
</li>
<% end %>
</ul>
Now it works like charm.

Related

Insert dynamic class assignment to a Rails link_to tag

I am trying to add a dynamic class to a link_to in Rails 7. I have the following code, but it's not inserting the appropriate content based on the request.env["PATH_INFO"]...
<ul>
<% %w[blog headlines network].each do |nav_link| %>
<%= added_class = request.env["PATH_INFO"] == nav_link ? "nav_current" : nil %>
<li class="btn"><%= link_to "#{nav_link}".capitalize, "/#{nav_link}", id: "nav_main", class: "btn btn_nav #{added_class}" %></li>
<% end %>
</ul>
However, the resulting HTML is:
<ul>
<li class="btn"><a id="nav_main" class="btn btn_nav " href="/blog">Bog</a></li>
<li class="btn"><a id="nav_main" class="btn btn_nav " href="/headlines">Headlines</a></li>
<li class="btn"><a id="nav_main" class="btn btn_nav " href="/network">Network</a></li>
</ul>
As you can see, the added_class doesn't get inserted. Any ideas?
request.env['PATH_INFO'] contains a leading / (at least on Rails 7; and IIRC on previous versions as well)
That means that if you are visiting localhost:3000/blog, request.env['PATH_INFO'] is /blog, not blog.
The following code should fix it:
<ul>
<% %w[blog headlines network].each do |nav_link| %>
<% added_class = request.env["PATH_INFO"] == "/#{nav_link}" ? "nav_current" : nil %>
<li class="btn"><%= link_to "#{nav_link}".capitalize, "/#{nav_link}", id: "nav_main", class: "btn btn_nav #{added_class}" %></li>
<% end %>
</ul>
Ok, so the following code does what I wanted it to. It injects a custom class into the link tag so that I can track the current button and style it differently... :
<ul>
<% %w[blog headlines network].each do |nav_link| %>
<% add_class = request.env['PATH_INFO'] == "/#{nav_link}" ? "nav_current" : "" %>
<li class="btn"><%= link_to "#{nav_link}".capitalize, "/#{nav_link}", id: "nav_main", class: "btn btn_nav #{add_class}" %></li>
<% end %>
</ul>
No Javascript necessary.

How to reuse a variable obtained from a loop in a subsequent loop in ejs?

I'm currently working on a menu for an hexo.io site using data from a YAML file and EJS. My point is to generate a menu with sections and subsections directly from the data included in the YAML file.
The yaml file in _data/menu.yml
sections:
Section1:
Section2:
section1:
Activate:
url: /activate
First steps:
url: /first-steps
My ejs file
<% for (var section in site.data.menu.sections) { %>
<ul>
<li>
<%= section %>
<% for (var i in site.data.menu.section) { %>
<ul>
<li><%= i %></li>
</ul>
<% } %>
</li>
</ul>
<hr>
<% } %>
My goal is to reuse the section variable in the second loop so that I can get a menu displaying :
Section1
Activate
First steps
Section2
Until now, I couldn't find how to properly insert this variable in the loop conditions. And I do not wish to hard code section names in the second loop.
Thanks for your input.
Found a way to do it unifying everything. it could still be optimised but works for me so I post it in case others have the same issue:
YAML
sections:
section1:
title: Section 1
sub:
Activate: /activate
First steps: /first-steps
section2:
title: Section 2
EJS
<% for (var i in site.data.menu.sections) { %>
<ul>
<li>
<%= site.data.menu.sections[i].title %>
<% for (var j in site.data.menu.sections[i].sub) { %>
<ul>
<li><%= j %></li>
</ul>
<% } %>
</li>
</ul>
<hr>
<% } %>

how to convert EJS to handlebars?

is it possible to use both ejs and handlebars in the same project? or do i need to change the ejs to handlebars? This is a piece of the code that needs to be changed, can someone help me?
<ul>
<% for(var i=0; i < discussions.length; i++) { %>
<li><%= discussions[i].question %></li>
<% } %>
</ul>
{{#each discussion}}
<li><a href="/discussion/... </a></li>
{{/each}}
First of all, No. You can use only one view engine. If your project is on handlebars, then stick to handlebars. If it's on ejs, stick with ejs. And for the following code to be converted into handlebars, this will do:
{{#each discussion}}
<li><a href="/discussion/... </a></li>
{{/each}}

Distribute the returns of a loop among two sections

I've basically got these two templates:
<article>
<section>
...
</section>
<section>
...
</section>
</article>
and:
#posts.each do |post|
<h3> post.title </h3>
<p> post.body </p>
<hr />
I can replace ... in <section> with yield and have every post in this section. Now what I want to do is to alternate this every turn so that each of the two sections gets filled up equally. I'm sure there must be some relatively easy way to achieve this? I somehow can't think of one for now.
edit: don't get me wrong. the first template can (and probably should) be merged with the second.
Do this in the first section:
#posts.select.each_with_index{|_,i| i.even? }
and this in the other one:
#posts.select.each_with_index{|_,i| i.odd? }
If you don't mind that the elements are not alternating between the columns but go top to bottom, you can do:
<article>
<% #posts.in_groups(2, false) do |grouped_posts| %>
<section>
<% grouped_posts.each do |post| %>
<h3> post.title </h3>
<p> post.body </p>
<hr />
<% end %>
</section>
<% end %>
</article>
Outside of Rails you can either pull in the necessary bits for in_groups from the active support gem
require 'active_support/core_ext/array/grouping'
or you can use this alternative approach which works very similarly:
#posts.each_slice((#posts.size/2.0).ceil).to_a
The only difference is:
#posts = []
#posts.in_groups(2, false) #=> [[], []]
#posts.each_slice((#posts.size/2.0).ceil).to_a #=> []

Ruby on Rails 3 : Playing with views

I am sorry for my bad english. I just try to description my question. :)
I have an application layout that have a yield for display post in body. I have another yield :footerpost3 for display title of recent post on the footer.
When I in localhost:3000, the yield :footerpost3 display a recent of title correctly. but when i am click a post link, which is the url is localhost:3000/posts/3, the yield :footerpost3 display nothing.
Here is my code:
app/views/layout/application.html.erb
<!-- begin footer comment widget -->
<div class="footer_list widget_recent_comments">
<div class="title"><h5>Artikel Terkini</h5></div>
<%= yield :footerpost3 %>
</div>
<!-- end footer comment widget -->
app/views/store/index.html.erb
<% content_for :footerpost3 do %>
<% #postsMain.each do |dopostAll| %>
<div class="entry">
<ul>
<li class="recentcomments"><%= link_to dopostAll.title, dopostAll %></li>
</ul>
</div>
<% end %>
<% end %>
i hope my question is easy to understand.. :)
Looks like your root url is stores#index .
You must be initializing #postsMain in the stores#index action and generating the content_for footerpost3 in stores/index.html.erb.
When you click on a post, you will be taken to posts#show page. So you have to initialize #postsMain even in posts#show action and generate the content for footerpost3 even in posts/show.html.erb
The answer is there in your question. You are defining the "content for" footerpost3 in that block, which exists in index.html.erb. When you're on /posts/3, index.html.erb is not rendered, but rather show.html.erb is.
To solve this, you'd need to add the content in the show.html.erb template as well.
You could solve this in multiple ways. Using nested layouts would be one. For example, you might create a posts layout at app/views/layout/posts.html.erb, like so:
<% content_for :footerpost3 do %>
<% #postsMain.each do |dopostAll| %>
<div class="entry">
<ul>
<li class="recentcomments"><%= link_to dopostAll.title, dopostAll %></li>
</ul>
</div>
<% end %>
<% end %>
<%= render :file => 'layouts/application' %>
In this way, all the views of your PostsController would use this layout, which simply adds your footer content, then renders the application_layout.

Resources