How to add "previous" and "next" button to text lightbox/modal - javascript

I am partially rendering data from an endpoint in a list using underscore, each list item has a link to "learn more...". Clicking on that link opens up a text modal/lightbox that shows the rest of the info for that particular element. I would like to add prev and next arrows to see the additional info on the items on the list, without having to close the modal and click on the next item.
I am thinking the way to approach this would be to add a class of "current" to my selected element, and remove/assign this class to each element as needed. But I am stuck thinking how to go about this... (newbie here, be kind).
HTML
<script type="text/template" id="event-template">
<div class="event row no-gutter">
<div class="col-md-12 info">
<div class="col-md-3">
<p class="day"><%= day %></p>
</div>
<div class="col-md-9">
<%= month %> at <%= time %>, <%= storename %> <br> <%= city %> <%= state %>
<a class="show-panel" data-id=<%=entry_id%> href="#_"> Learn More...</a>
</div>
<div class="lightbox-panel" id="lightbox-panel-<%=entry_id%>">
<h2><%= storename %></h2>
<p><%= month %>, <%= desc %></p>
<p align="center"><a class="close-panel" href="#_">Close window</a></p>
<div class="col-md-10" id="prev">Previous</div>
<div class="col-md-2" id="next">Next</div>
</div>
</div>
</div>
</script>
JS
// Open lightbox
$("#events-placeholder").on("click", ".show-panel", function(e) {
var entry_id = $(this).attr("data-id");
$("#lightbox-panel-"+entry_id).fadeIn(300);
$("body").css("background-color", "black");
});
//Close lightbox
$("#events-placeholder").on("click", "#close-panel", function(e) {
$(".lightbox-panel").fadeOut(300);
$("body").css("background-color", "white");
});
// Prev Info
$(".events-placeholder").on("click", "#prev", function(e) {
// ???
var current = $(this).attr("data-id");
var previous = current - 1;
$("#lightbox-panel-"+entry_id-1).fadeIn(300);
});
// Next Info
$("#events-placeholder").on("click", "#next", function(e) {
// ???
});

Related

Vanilla JS: Reveal only the next element at the same parent group

I am trying to create few tabs - with loop.
Then when you click on the tab's name which is a span, its expand(or hide) the next span, which is below it. The problem is that the function works only in the first created tab from the loop and if you click on the second/third, etc tab - the function triggers only at the first tab.
Was trying with querySelector and nextElementSibling without any success.
Using ejs template, express and vanilla javascript only.
This is the loop/tab.
<div>
<% listedProducts.forEach(function(product) { %>
<div class="col">
<span id="info" class="b-d" onclick="hideReveal()">
<%= product.name %>
</span>
<span>
<img src="<%= product.logo %>" alt="">
<p class="r-d"><%= product.supplierCompany %></p>
<p class="r-d"><%= product.dateListed %></p>
<p class="r-d"><%= product.dateApproved %></p>
<p class="r-d"><%= product.supplierName %></p>
</span>
</div>
<% }); %>
</div>
and the function
function hideReveal() {
var tab = document.getElementById("info");
if (tab.style.display === "none") {
tab.style.display = "block";
} else {
tab.style.display = "none";
}
}
Would like a little help, please. Thank you and have a nice weekend.
in your click handler, pass an event argument, e.g., function clickHandler(evt) then say var thisTab = evt.target.id. This assumes you have an id attribute on the tab(s). Then you can toggle the open/closed class of thisTab's firstElementChild

Add a css class using to "this" item in a forEach within EJS/node.js

I've been trying this for hours but I am stumped.
I have a kind of "shopping list" node.js app where you can tick off items as bought. I want the bought items to be styled green or smth. It is passing a mongoose obj to the client side along a route.
Server side:
router.get("/:id", function(req, res){
//find the list with provided ID
List.findById(req.params.id).populate("listItems").exec(function(err, foundList){
if(err){
console.log(err);
} else {
//render show template with that list
res.render("lists/show", {list: foundList});
The foundList obj basically has a structure of (not valid code, just so u can get an idea):
List {
name: String,
listItems: [{
text: String,
bought: Boolean
}]
On the client side I am using a forEach in ejs to loop through the listItems and display a html element for each item:
<% list.listItems.forEach(function(listItem){ %>
<div class="card">
<div class="card list">
..listItem name here
</div>
</div>
<% }) %>
I want to basically make it so that when an element is checked off and listItem.bought == true, the card list element is green, and when lisItem.bought == false, it's just white.
I've got it working with following code, however if one occurrence of the forEach is bought = true, all .card elements turn green. I want it so that only the element in question is effected.
<% list.listItems.forEach(function(listItem){ %>
<% if(listItem.bought === true){ %>
<script>
$(document).ready(function(){
(".card").css("background-color","green");
});
</script>
<% } else { %>
<script>
$(document).ready(function(){
(".card").css("background-color","white");
});
</script>
<% } %>
<div class="card">
<div class="card list">
....
Question: How do I target 1 occurrence of a forEach from server side data in ejs, and add a class/style to it. E.g. if there is 2 items on the list, 1 is bought and one not, one should be green and one white. Currently they both go green.
Thanks!
I don't think you need jQuery for this. You can just add the background color like this:
<% list.listItems.forEach(function (listItem) { %>
<div class="card" style="background-color: <%= listItem.bought ? 'green' : 'white' %>">
<div class="card list">
...
</div>
</div>
<% }); %>
If you want to use jQuery you probably need do add ids to the cards and use them to change the backgrounds.

Rails how to insert a partial in a div table?

I'm using Rails and I've got a table made up off div's. I want users to be able to click on a table cell and have a menu (in the form of another div row) slide out underneath it. With a second click on the cell the menu should slide back up.
There should be 2 different menu's / click actions per row. I would like to add/remove a div below the clicked action. I've tried working with a table but the div's seem to work better. I just don't really know how to render the partial correctly. my code:
js:
$(document).ready(function () {
openBuySliders = [];
openSellSliders = [];
function openSlider(parent, actionType) {
$( *some partial file* ).insertAfter( parent );
}
function closeSlider() {
// remove the slider
}
$("div[buy-stocks]").click(function() {
var parent = $(event.target).parent()
if ($.inArray(cellID, openBuySliders) == -1) {
openBuySliders.push(cellID);
openSlider(parent, "buy");
}else {
var index = openBuySliders.indexOf(cellID);
openBuySliders.splice(index, 1);
closeSlider(parent);
}
})
$("div[sell-stocks]").click(function() {
var parent = $(event.target).parent()
alert(test);
if ($.inArray(cellID, openSellSliders) == -1) {
openSellSliders.push(cellID);
openSlider(parent, "sell");
}else {
var index = openSellSliders.indexOf(cellID);
openSellSliders.splice(index, 1);
closeSlider(parent);
}
})
});
my html:
<div class="rTable">
<div class="rTableRow">
<div class="rTableHead"><strong>Company</strong></div>
<div class="rTableHead"><strong>Stocks available</strong></div>
<div class="rTableHead"><strong>Stocks owned</strong></div>
</div>
<% current_game.companies.each do |company|%>
<div class="rTableRow" row-id="<%= company.id%>">
<div class="rTableCell"> <%= company.name %> </div>
<div class="rTableCell" buy-stocks="<%= game_player_view_path%>"> <%= company.stocks.size %> </div>
<div class="rTableCell" sell-stocks="<%= game_player_view_path %>"> <%= #player.stocks.where(company_id: company.id).size %> </div>
</div>
<% end %>
</div>
my controller:
def show
respond_to do |format|
format.html
format.js { render :nothing => true }
end
end
I'm trying to render it using jquery insert after but this might not be the smartest solution. I'm really struggling with the JS in the app so any help is appreciated.
I would suggest something like this:
HTML:
<table>
<tr>
<td>
<div class='click-me'> Content </div>
<div class='menu' style='display:none'> Hidden </div>
</td>
</tr>
</table>
JS:
$(document).ready(function() {
$('.click-me').click(function(e) {
var target = $(e.target);
target.parent().find('.menu').toggle();
});
});

Open Semantic UI Calendar within a loop

I need to open Semantic-UI-Calendar within a loop but nothing works, which it should. The logic is, when I click data-id="expensecal", it should give me the id which is expense_date2 or expense_date1 but instead it give me the id of the input:
Rails View:
#---Loop----#
<div class="required field">
<label>Claim date</label>
<div class="ui calendar" data-id="expensecal" id="expense_date<%= contract.id %>">
<div class="ui input left icon">
<i class="calendar icon"></i>
<%= f.text_field :date, id: "expense_date_input", placeholder: "Expense date" %>
</div>
</div>
</div>
JavaScript:
$( "[data-id=expensecal]" ).click(function(e) {
e.preventDefault();
let id = '#' + e.target.id;
console.log(id); // Shows the field input id. Why?
$(id).calendar({
type: 'date'
});
});
I use this method to open up a semantic modal in a loop and it works ok but not sure why not with the calendar.
Initialize all the elements at page ready using a class, remove the click event
Try using the following code:
$('.ui.calendar').calendar({
type: 'date'
});
demo:https://jsbin.com/kenaqiyuqe/1/edit?html,js,output

How can I change a background image depending on what results are being displayed?

I have a table of venues and areas where each venue belongs to an area and an area has many venues.
The venues index page is displaying all the venue records as partials and I have a set of checkboxes to filter the venues shown by what area they are in.
I also have a div (map_container) which shows a map .png image of all the areas on the right of the screen.
venue index.html.erb
<div class="map_container">
</div>
<div class="filter_options_container">
<form class="form">
<fieldset class="filter_form_fieldset areas">
<% Area.all.each do |a| %>
<%= check_box_tag 'areas[]', a.id, false, :id => "area-#{a.id}" %>
<label for="area-<%= a.id %>"><p1><%= a.name %></p1></label>
<% end %>
</fieldset>
<div class="form_filter_button">
<p2><input type="submit" value="Filter"/></p2>
</div>
</form>
</div>
<div class="venue_partials_container">
<%= render :partial => 'venue', :collection => #venues %>
<div class="clearall"></div>
</div>
<div class="clearall"></div>
How would it be possible to check whether all the venues being displayed have the same area_id and if they do display a different map image in the map div? So if all venues have area_id of 1 then display map1.png or if they all have an area_id of 2 then display map2.png etc.
Thanks for any help, its much appreciated!
Sounds like you might want the background image to update dynamically when checkboxes are changed by the user? If so, the best bet is to use CSS to set a background-image URL on map_container, based on some other class:
.map_container_map1 {
background-image: url('/images/map1.png')
}
In javascript, attach the class map_container_map1 if all the checkboxes are set for area 1.
You should write a javascript function that's called on docReady, as well as whenever a checkbox is clicked. Something like this, in jQuery:
// docReady
$(function() {
updateMap();
}
$(document).delegate('checkbox[name|="areas"', 'change', function(event) {
updateMap();
});
function updateMap() {
// Loop through all the checkboxes, check their values to see if they're the same
$('checkbox[name|="areas"').each(function() {
...
});
var map = $j('.map_container');
map.removeClass('map_container_area1 map_container_area2');
if (area1)
$j('.map_container').addClass('map_container_area1');
else if (area2)
$j('.map_container').addClass('map_container_area2');
}
This should hopefully get you started.

Categories