JavaScript - For loop button onclick - identify which button - javascript

I'm creating 5 divisions in for loop, each division have one image and one button.
Button's action is to perform like/vote. But, the images and buttons being in for loop, i don't know which button is linked with which image id. So that i can put it into database that image have been voted.
<%
for(until resultSet has next){
%>
<img id="img" src="resultsetValue" />
<button id="btn" >VOTE</button>
<%
}
%>
In JavaScript file:
document.getElementById("btn").onclick = function(){
//WHICH IMAGE NEEDS VOTE NOW
}
Now, if you see, i gave them id's too. An id must be unique to each element, but i gave id in for loop, which makes every image and every button have same id. How can i resolve this or is it ok?
i don't want to use jQuery, i have to learn it yet.

First of all, make sure buttons don't have duplicated ids. Better to use classes in this case:
<% for(until resultSet has next) { %>
<img id="img<%= index %>" src="resultsetValue" />
<button class="btn" data-index="<%= index %>">VOTE</button>
<% } %>
Then you can do something like this using iteration index to refer currently clicked element:
var buttons = document.querySelectorAll('.btn');
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function() {
var index = this.getAttribute('data-index');
var img = document.querySelector('#img' + index);
};
}
this one will work

Related

rails selection quantity javascript get class not working index

What want to do:
I creating ec site by ROR. What I want to do is can select the quantity each items in checkout page(Specifically, make plus and minus button then select the quantity).
The variable are #items and #user_items_quantity and Im adding index number on it.
Then what I mean, getting the (div class) in Javascript which is had index number and I want to edit quantity and show it.
But impossible to get (div class with index) in js each items. I was thinking to roop "for" in js but I can't.
Can you tell me how I work out please?
_user_basket_items.html.erb
<% #items.zip(#user_items_quantity).each.with_index(1) do | (item, uiq), index | %>
 <div class="entry value-minus quantity-minus[#{index}]" id="value-minus"> </div>
 <div class="entry value score-value quantity-score[#{index}]" id="score-value"><%= uiq %></div>
 <div class="entry value-plus active quantity-plus[#{index}]" id="value-plus"> </div>
<% end %>
///
item_quantity.js
var add = document.getElementsByClassName( "quantity-plus" )["#{index}".to_i];
var remove = document.getElementsByClassName( "quantity-minus" )["#{index}".to_i];
var scoreValue = document.getElementsByClassName( "quantity-score" )["#{index}".to_i];
var int = 0;
add.addEventListener('click', function() {
int = parseInt(scoreValue.innerHTML, 10)+1;
scoreValue.innerHTML = int;
});
remove.addEventListener('click', function() {
int = parseInt(scoreValue.innerHTML, 10)-1;
scoreValue.innerHTML = int;
});
the css classes that you are generating looks like this:
<div class="entry value-minus quantity-minus[1]"
or
<div class="entry value-minus quantity-minus[2]"
but your javascript is looking for document.getElementsByClassName( "quantity-minus" ) with a mix of ruby syntax (["#{index}".to_i]) and js. Is your js template parsing ruby? You don't provide how index is initialized.
if it is, I would change the javascript as follows:
var add = document.getElementsByClassName( "quantity-minus[#{index.to_i}]" );
If your template isn't parsing ruby, you have to find another way.
As a side note, in your partial you are iterating over a list and giving static ids to the elements (id="value-minus") you should try avoid doing that

Javascript: .value is undefined (involves NodeJs also)

So In my node I do an API and send it to my index.ejs page like
app.get("/", function (req, res) {
request("http://something/API", function (error, response, body){
if(!error && response.statusCode == 200) {
var result = JSON.parse(body) //Converts it into object
console.log(result)
res.render("home.ejs", {result:result});
}
})
})
Now In my Index Page, I do something like this
<% for ( var i= 0; i<result.length; i++ ) { %>
<table text-aling="left">
<tr>
<td> <%= i+1 %> </td>
<td> <p class="c"><%=result[i]["long"]%></p> (<%= result[i]["short"] %>) </td>
<td> <%= result[i]["price"] %> </td>
followed by a script just below body and head tag to do DOM manipulation.
<script type="text/javascript">
var x = document.getElementsByClassName("c")[1].value
console.log(x);
</script>
Now, Console.log(x) says undefined (while it does display result from API call on my frontend. Is it because it is an object? or what am I missing here? How can I get the value displayed on my frontend at my console.log
Your <p> does not have a value attribute. Use innerHTML:
x = document.getElementsByClassName("c")[1].innerHTML
I think the issue you are experiencing could be due to one of a few problems:
The placement of the tag
Make sure you place the script tag at the bottom of your html to ensure the above elements have fully rendered before the script is called. If the script runs before the elements with class "crypto" have loaded, the variable 'x' will be empty.
The number of elements with the class "crypto"
While I don't see any elements with class "crypto" in your example, you are trying to set variable 'x' to the element in the array at index 1 (the second position). If you have fewer than two elements with the class "crypto", trying to select index 1 will be undefined. If you're trying to select the first element with the class "crypto", use "var x = document.getElementsByClassName("crypto")[0].value" instead.
The presence of the class "crypto"
I see you list an element with the class "c", though none with the class "crypto". If you are trying to select the element with class "c", , use "var x = document.getElementsByClassName("c")[0].value" instead.

Load Function not updating Global Variable

I'm creating a node application and having trouble updating a global variable.
Here is my code (ejs file):
<% include ../partials/header %>
<div class="page container">
<div id="campgroundsRow" class="row">
</div> <!-- row end -->
<button id="loadMore">Load More</button>
</div> <!-- Container End -->
<% include ../partials/footer %>
<script>
var numGroundsToLoad = 1;
var numGroundsLoaded = 0;
loadCampgrounds(numGroundsLoaded, numGroundsToLoad);
function loadCampgrounds(numGroundsLoaded, numGroundsToLoad) {
var grounds = <%-JSON.stringify(campgrounds) %>
for(var i=numGroundsLoaded + 1; i<numGroundsLoaded + numGroundsToLoad; i++) {
//code to add grounds[i] to campgroundsRow div
}
numGroundsLoaded += numGroundsToLoad;
}
$("#loadMore").on("click", function() {
loadCampgrounds(numGroundsLoaded, numGroundsToLoad);
});
</script>
The problem I'm having is the loadCampgrounds function is not actually updating numGroundsLoaded. So when I click the load more button (#loadMore), it thinks that I am adding ground[0].
What I want is that each time I click load more, the next ground is added. I.e, ground[0] gets added by default. Then on load more, ground[1]. Then on load more, ground[2] and so on (assume there are unlimited grounds for now).
As you can see, the problem is related to both scope and when stuff is being loaded.
Because you update the local variable. In this case, to update global variable you need to access it through window.numGroundsLoaded.

jQuery: how to append to a specific list based on a URL

I have a app that has jobs and messages. When somebody enters a message for a job, I want to append the message to the list of messages in the jobs specific show page.
Ex: If a user add a message to job 7, then I want to append that message to the <ul> with class msg_list for the url /jobs/7
The way I have it set up, all jobs share a show page, and can be accessed with the URL /jobs/:id. Where id is the specific job id.
<div class="show_messages">
<div class="row">
<div class="small-12 columns">
<% messages = #job.messages %>
<ul class="msg_list">
<% messages.each do |m| %>
<% login = m.user_id.present? ? m.user.login : m.runner.login %>
<li class="message">
<p>
<strong><%= login %></strong>: <%= m.body %><br>
<span id="sent-at">Sent on <%= m.created_at.strftime("%b %d at %l:%M%p") %></span>
</p>
</li>
<% end %>
</ul>
<% end %>
</div>
</div>
And when I try to append a message like so:
function addMessage(msg) {
var new_msg = "<li><p> NEW TEST MESSAGE </p></li>";
$('.msg_list').append(new_msg);
}
I am appending it to every jobs show, when I only want to append it to 1 specific job (Ex: job with id 7)
Can anyone help me figure out how to do this?
You can change this to include the id:
<ul class="msg_list_<%= id %>">
And then the selector looks like this:
$('.msg_list_' + id).append(new_msg);
You have to figure out how the javascript knows the id and how to get the id set when the template language builds the html.
Get the URL segment, then use .eq() to get the job you want.
var pathArray = window.location.pathname.split( '/' );
var id_from_url = pathArray[2];
$('.msg_list').eq(id_from_url).append(new_msg);
Here is a guide on getting the URL segment with javascript.
Note: .eq() is zero-based, so you may have to offset your id if it is not zero-based.
Both solutions work, but to solve it I instead checked the url and only added the msg to the list if the id's matched
function addMessage(msg) {
// var body = msg["body"];
// $('.msg_list').append(body)
var new_msg = "<li><p> NEW TEST MESSAGE </p></li>";
$('.msg_list').append(new_msg);
}
var msgChannel = pusher.subscribe('msg_channel');
msgChannel.bind('msg_added', function(msg) {
// if (msg["job_id"] == '#job.id'){
// addMessage(msg)
// }
var message_job_id = msg["job_id"];
var url = window.location.pathname;
var job_show_id = url.substring(url.lastIndexOf('/') + 1);
var show_integer = parseInt(job_show_id);
if(message_job_id == show_integer) {
addMessage(msg);
}
});
});

Selecting item dynamically in rails

i am attempting to do a dynamic select here using rails and jquery. the code is as follows
<div class = "line_items">
<%- calc = Hash[Item.all.map{|p| [p.id, p.quantity]}].to_json %>
<div class = "item"><%= f.collection_select :item_id,Item.all,:id,:title, :prompt => "Select a Item", input_html: {data:{calc: calc} %></div>
<div class ="quantity"> <%= f.text_field :quantity %></div>
/*rest of code*/
</div>
javascript for the view is as follows
jQuery(document).ready(function(){
jQuery('.item').bind('change',function() {
var selectElement = jQuery(this);
var itemSelected = jQuery('.item:selected').val();
var wrapperDivElement = selectElement.parent(".line_items");
var quantity= eval(selectElement.data("calc"))[itemSelected];
jQuery(".quantity", wrapperDivElement).val(quantity);
});
});
when i change the item i am getting the following error
eval(selectElement.data("calc"))[itemSelected] is undefined in firebug. Can anyone point out where i am going wrong? also any better way to get the quantity. i feel the method i am doing is crude. any guidance would be helpful. Thanks in advance.
jQuery(document).ready(function(){
jQuery('.item select').bind('change',function() {
var selectElement = jQuery(this);
var itemSelected = selectElement.val();
var wrapperDivElement = selectElement.parents(".line_items");
var quantity= eval(selectElement.data("calc"))[itemSelected];
jQuery(".quantity input", wrapperDivElement).val(quantity);
});
});
i guess the value of itemSelected was not getting detected, hence the error. the above redefined code should work. But i strongly urge you not to get data like this. its better to do a json call or ajax call to get the related data from the controller. and use parents instead parent in the code:)
Ik think you mixup the reference by index and the reference by ID. I'm no Javascript wizard, but you fill the hash with a list of . Then you get the 'val'-value in the change event. That contains an integer, but that is not the index.
Then you request in Javascript the item with index val, not the item with value val. Maybe javascript cannot distinguish between them because both need an Int...
it's this line:
var quantity= eval(selectElement.data("calc"))[itemSelected];

Categories