Groovy/Grails - Need to retrieve List index value - list

I need to retrieve the index position of each value in a list I have. I'm doing this so that I can display a gsp table with alternating row background colors. For example:
(list.indexVal % 2) == 1 ? 'odd' : 'even'
How can I get the index position number of each item in a Groovy list? Thanks!

According the documentation, the g:each tag in the gsp view allows the "status" variable
where grails store the iteration index in.
Example:
<tbody>
<g:each status="i" in="${itemList}" var="item">
<!-- Alternate CSS classes for the rows. -->
<tr class="${ (i % 2) == 0 ? 'a' : 'b'}">
<td>${item.id?.encodeAsHTML()}</td>
<td>${item.parentId?.encodeAsHTML()}</td>
<td>${item.type?.encodeAsHTML()}</td>
<td>${item.status?.encodeAsHTML()}</td>
</tr>
</g:each>
</tbody>

Any of g:each, eachWithIndex, or for loops can be used.
But, for this specific case, the index value is not needed. Using css pseudo-classes is recommended:
tr:nth-child(odd) { background: #f7f7f7; }
tr:nth-child(even) { background: #ffffff; }
If you still need to get the index, options are:
<g:each status="i" in="${items}" var="item">
...
</g:each>
<% items.eachWithIndex { item, i -> %>
...
<% } %>
<% for (int i = 0; i < items.size(); i++) { %>
<% def item = items[i] %>
...
<% } %>

Related

How can I scroll down to bottom of a specific div on page load in a chat conversation using Nuxt.js?

I want scroll down to the last div
<div v-for="(message, message_index) in messageArray" :key="message_index">
<div class="chatList">
</div>
</div>
I'm assuming you have a chat component where you want to scroll down to the last message on page load.
Although there are many ways to achieve this, I found this is the simplest one.
scrollIntoView() inside this.$nextTick(function () {}) gets the job done.
Bind your every div inside the loop with unique id. :id="`m-(some_unique_id)`">
<div v-for="(message, message_index) in messageArray" :key="message_index">
<div :id="`m-${message.id}`">
</div>
</div>
and get the element of the last index of messageArray. And tell the scrollIntoView to scroll down to that div.
script
<script>
mounted: {
this.getChatBoxUsersChats();
},
methods: {
getChatBoxUsersChats() {
this.$nextTick(function () {
let length = this.messageArray.length;
if (length > 0) {
let id = this.messageArray0[length - 1].id;
let element = document.getElementById("m-" + id);
element.scrollIntoView({ behavior: "smooth", block: "end" });
});
},
},
}
</script>

if statement within underscore loop

I'm trying to add this if statement in a loop in an underscore template:
<% _.each( looks, function( listItem, index ){ %>
<% if(_.contains(firstBatch, listItem.id)){ %>
<% if (index % 2 == 0) { %>
<div class="large-6 column overlay-col">
<% } else { %>
<div class=" column overlay-col">
<% } % %>
<% } %>
<% }) %>
Basically it's to detect if index is an even number, but I get this console error:
SyntaxError: missing : after property id
if (index % 2 === 0) {
what's wrong with code?
I think your syntax has a bozo on line 7:
<% } % %>
What's that extra percent?
This becomes apparent when you remove all the decoration around the function:
_.each( looks, function( listItem, index ){
if(_.contains(firstBatch, listItem.id)){
if (index % 2 == 0) {
<div class="large-6 column overlay-col">
} else {
<div class=" column overlay-col">
} %
}
})

wice_grid add row dynamically

I want to create a "details" row dynamically like below:
I'd like to be able to toggle details for every item on the grid. Can you advise how I can achieve this functionality?
I'm using rails 4 with wice_grid gem
I found out how to do this:
VIEW:
<%= grid(#items_grid) do |g|
g.after_row do |fill, number_of_columns|
content_tag(:tr, class: 'extra-row') do
content_tag(:td,
content_tag(:div) do
# without buffer only the last tag will appear
buffer = content_tag(:p,"data1: #{item.add_data1}")
buffer += content_tag(:p,"data2: #{item.add_data2}")
raw buffer
end,
colspan: number_of_columns)
end
g.column name: "ID", attribute: 'id' do |item|
item.id
end
g.column name: "Data", attribute: 'data' do |item|
item.data
end
g.column do |item|
button_tag("Details", class: "btn btn-default toggle-trigger")
end
end -%>
.JS:
$(document).on("page:load ready", function(){
$(".toggle-trigger").click(function(){
$(this).parents('tr').next('.extra-row').slideToggle("fast");
return false;
});
});
.CSS:
.extra-row {
display: none;
}

Animating circles getting clipped using D3.js with Ruby on Rails

I am trying to animate some SVG circles across the entire body element of a webpage, but they seem to be getting clipped when they reach this line, <%= yield %> in the application.html.erb of the RoR app.
The application.html.erb looks like the following,
<!DOCTYPE html>
<html>
<head>
<title>KegCop</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
<%= favicon_link_tag 'favicon.ico' %>
<%= render 'layouts/ie_shim' %>
</head>
<body>
<%= render 'layouts/nav' %>
<div id="container-fluid">
<%= render 'layouts/bubbles' %>
<%= yield %>
<%= render 'layouts/footer' %>
</div>
<%= render 'layouts/google_analytics' %>
<%= render 'layouts/beer_background' %>
<%= audio_tag("/audios/bottle-open.ogg", autoplay: true, controls: false) %>
</body>
</html>
And the D3.js script that animates the bubbles, _bubbles.html.erb
w = window.innerWidth,
h = window.innerHeight;
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h);
var circle = svg.selectAll("circle")
.data(d3.range(70).map(function(datum,interval) {
return {
x: interval*20,
y: 0,
dx: 5,
dy: -3 * (Math.random()+1),
mu: Math.random()*2
};
}))
.enter().append("svg:circle")
.attr("r", 2.5)
.attr("fill","blue")
.attr("opacity",".5");
var text = svg.append("svg:text")
.attr("x", 20)
.attr("y", 20);
var start = Date.now(),
frames = 0;
d3.timer(function()
{
// Update the FPS meter.
var now = Date.now(), duration = now - start;
text.text(~~(++frames * 1000 / duration));
if (duration >= 1000) frames = 0, start = now;
// Update the circle positions.
circle
.attr("cx", function(d) { d.x += Math.random()*3*Math.sin(Math.random()*3*d.x + Math.random()*10); if (d.x > w) d.x -= w; else if (d.x < 0) d.x += w; return d.x; })
.attr("cy", function(d) { d.y += d.dy ; if (d.y > h) d.y -= h; else if (d.y < 0) d.y += h; return d.y; })
.attr("r",function(d)
{
return (d.y < 100) ? d3.select(this).attr("r") : d.mu*500/d.y;
});
});
Update:
Below is what I would expect to see, but it is clipping off at the bottom of the form elements on the webpage I am working with.
http://jsfiddle.net/ipatch/4C8c8/8/
I ended up changing <div id="container-fluid"> to <div class="wrapper"> and changing the wrapper CSS style to position: absolute and now the "bubbles" / SVG circles are animating across the entire <body> element of the page.
The key was setting the wrapper class to a position of absolute.

Ember.js : Click on a link with an id sends a json-request and the received data can't be displayed under the overview table

I'm new to ember.js which seems to be very interesting but hard/difficult to learn cause there are so many ways to solve a programming problem.
I try to code a very simple app but don't know how...
The app show at the top in a table all customers with an id received from a json file (testin local) and on click on the id there will be a json-request to receive detailed infos to the customer.
The problem is, that I receive detailed data but can't display it in a template under the overview template...
Can some one help me...!?
Greets
Christian [from germany]
Here's some code-snippets I got till now...
APP.JS
App.Search = Ember.Object.extend();
App.Search.reopenClass({
all: function() {
// console.log('Search.reopenClass all');
return $.getJSON("json/kunden_suchen.json").then(function(response) {
var items = [];
response.Konto.forEach(function(child) {
// console.log(child);
var item = new App.item();
item.set('content', child);
item.set('nr', child.nr);
item.set('name1', child.name1);
item.set('name2', child.name2);
item.set('plz', child.anschrift.plz);
item.set('anschrift', child.anschrift);
items.push(item);
});
return items;
});
}
});
App.SearchRoute = Ember.Route.extend({
model: function() {
// console.log('SearchRoute model');
return App.Search.all();
},
events: {
details: function() {
console.log('SearchRoute detail');
return App.Details.all();
}
}
});
App.Details= Ember.Object.extend();
App.Details.reopenClass({
all: function() {
// console.log('Search.reopenClass all');
// return $.getJSON("json/kunden_suchen.json").then(function(response) {
return $.getJSON("json/customer.json").then(function(response) {
var items = [];
response.Konto.forEach(function(child) {
console.log(child);
var item = new App.item();
item.set('content', child);
item.set('nr', child.nr);
items.push(item);
});
return items;
});
}
});
index.html
<script type="text/x-handlebars" data-template-name="items">
<div style="width: 80%; margin: auto;">
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Name1</th>
<th>nr</th>
</tr>
</thead>
<tbody>
{{#each item in model}}
<tr class="info">
<td> {{ item.content.name1 }} </td>
<td> {{ item.content.id}} </td>
{{/each}}
</tbody>
</table>
</div>
</script>
Arrays in ember are augmented, e.g. it's prototype, so for your arrays to be binding aware and thus live updating your templates when the data asynchronously arrives you can't just use vanilla push(...) but pushObject(...) instead.
So try to change every occurrence of push to pushObject
...
items.pushObject(item);
...
Hope it helps.
Greets Alex [From Spain] :)