I have foreach loop:
objects.forEach(function(object) {
var button = '<tr><td>' + object.object.code + '</td><td>' +
formatDistance(1456000) + '</td></tr>';
$(button).mouseup(function(event) {
if (event.which == 1) {
runObject(object);
}
});
result += button;
});
$(mydiv).html(result);
but this can't work. I have one object listed only in each forEach cycle.
How can I correctly write onclick event for each point of loop.
You can append each item into your div inside the forEach loop:
objects.forEach(function(object) {
var button = $('<tr><td>' + object.object.code + '</td><td>' + formatDistance(1456000) + '</td></tr>');
button.mouseup(function(e) { if(e.which === 1) { runObject(object); } });
$(mydiv).append(button);
});
Try this
objects.forEach(function(object) {
var button = '<tr class="test_' + object.object.code + "'><td>' + object.object.code + '</td><td>' +
formatDistance(1456000) + '</td></tr>';
$('.test_' + object.object.code).mouseup(function(event) {
if (event.which == 1) {
runObject(object);
}
});
result += button;
});
$(mydiv).html(result);
you have to resolve syntax error
Here is one of the ways:
//Create an empty container
var $result = $();
[1,2,3,4].forEach(function(object) {
//Create TRs as jQuery objects (as opposed to strings), append whatever
var $button = $('<tr/>').append('<td>[' + object + ']: </td><td>' + ("this is " + object) + '</td>');
//Bing events, mouseup, click or whatever
$button.on("mouseup", function(e) {
//Add whatever conditions you like
if (e.which === 1) {
alert (object);
}
});
//Keep adding the TR to the container
$result = $result.add($button)
});
//Append all at once, outside the loop
$("#mydiv").empty().append($result);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mydiv"></div>
Related
Hare is my current function
var listItems = $("#list_li").children();
var count = listItems.length;
var i;
for (i = 0; i <= count; i++) {
const the_i = i;
$("#news_" + the_i + " h2").click(function () {
$('#news_' + the_i + ' article').addClass('active');
$('#news_' + the_i + ' h2').addClass('active');
$('#news_' + the_i + ' img').addClass('active');
$('#news_' + the_i).addClass('active');
If is clicked.
$('#news_1 article').removeClass('active');
$('#news_1 h2').removeClass('active');
$('#news_1 img').removeClass('active');
$('#news_1').removeClass('active');
}
});
}
My code adds up styles to it on click, it works fine, how ever, I need to make it so it would know if its clicked or not, I am using loop, because its news feed and it can get more and more, so without the struggle automatically know what to align.
I need something like this
var autoIncresingVar.i = 0;
so when it comes to the 1st one on loop, it would set it to 1 and on click check with "if" its clicked or not.
Let me try to explain Note that I know its not real code
each(i > 5) {
var newEl_"i" = 0;
on first element click
if {newEL_1 == 0) {
addClasses
newEL_i = 1;
} else if)newEl_1 == 1) {
removeClasses
newEL_i = 0;
}
}
You can use .hasClass() function for check if the current node has the 'active' class. If yes, remove it. Else, add it.
Example :
$("#news_" + the_i + " h2").click(function () {
if (!$('#news_' + the_i).hasClass('active'))
{
$('#news_' + the_i + ' article').addClass('active');
$('#news_' + the_i + ' h2').addClass('active');
$('#news_' + the_i + ' img').addClass('active');
$('#news_' + the_i).addClass('active');
}
else
{
$('#news_1 article').removeClass('active');
$('#news_1 h2').removeClass('active');
$('#news_1 img').removeClass('active');
$('#news_1').removeClass('active');
}
});
One approach would be to use .data() to set a property at an object where value is toggled between 0 and 1 at each click event
$("#news_" + the_i + " h2").data("clicked", 0)
.on("click", function() {
if (!$(this).data().clicked) {
// do stuff with `$(this).data().clicked` : `0`
} else {
// do stuff with `$(this).data().clicked` : `1`
}
// set `$(this).data().clicked` to `1` or `0`
$(this).data().clicked = !$(this).data().clicked ? 1 : 0;
})
Use below code.
for (i = 0; i <= count; i++) {
const the_i = i;
$("#news_" + the_i + " h2").click(function () {
$('#news_' + the_i + ' article').toggleClass('active');
$('#news_' + the_i + ' h2').toggleClass('active');
$('#news_' + the_i + ' img').toggleClass('active');
$('#news_' + the_i).toggleClass('active');
}
});
}
you can use the add attribute function to add an on click event to each element
http://coursesweb.net/jquery/add-change-remove-attribute-jquery
With dynamically generated HTML from JSON data I'm trying to add a class to each .status-card, in this case depending on the value of c.callStatus. This is the closest I got, but this just adds active class to all status-card. I'm guessing it's something to do with how I'm using $(this) or I'm missing something else?
$(function() {
var agents = [];
$.getJSON('js/agents.json', function(a) {
$.each(a.agents, function(b, c) {
var content =
'<div class="status-card">' +
'<div class="agent-details">' +
'<span class="agent-name">' + c.name + '</span>' +
'<span class="handling-state">' + c.callStatus + '</span>' +
'<span class="handling-time">' + c.handlingTime + '</span>' +
'</div>' +
'<div class="status-indicator"></div>' +
'</div>'
$(content).appendTo('#left');
//Add class depending on callStatus
$('.status-card').each(function() {
if (c.callStatus == 'On Call') {
$(this).removeClass('idle away').addClass('active');
} else if (c.callStatus == 'Idle') {
$(this).removeClass('active away').addClass('idle');
} else {
$(this).removeClass('active idle').addClass('away');
}
console.log(c.callStatus);
});
});
});
});
Thanks!
This is the closest I got, but this just adds active class to all status-card.
This is happening because after adding each status-card you are adding other classes to all the status cards added till now:
$.each(a.agents, function(b, c) {
....
// here you are updating the class for all the cards added till now.
$('.status-card').each(function() {
....
});
....
});
So, the active classes is added to all the other cards because that might be the callStatus in the last outer loop.
You can compute the className based on the callStatus before creating the HTML and then use that className in HTML like this:
function getClassNameByStatus (callStatus) {
switch(callStatus){
case "On Call":
return "active";
case "Idle":
return "idle";
default:
return "away";
}
}
$.each(a.agents, function(b, c) {
var className = getClassNameByStatus(c.callStatus);
var content =
'<div class="status-card' + className + '">' +
....; // rest of the HTML
$(content).appendTo('#left');
});
You're calling $('.status-card').each() for each agent in your a.agents list. so in the final iterate all .status-card elements will have the last agent.callStatus evaluated class.
I'd write something like this.
$(function() {
function createStatusCard(name,callStatus,handlingTime) {
var status_class_map = {
"On Call" : "active",
"Idle" : "idle"
};
var $content = $("<div/>").addClass("status-card").addClass(function(){
return status_class_map[callStatus] || "away";
});
$content.html('<div class="agent-details">' +
'<span class="agent-name">' + name + '</span>' +
'<span class="handling-state">' + callStatus + '</span>' +
'<span class="handling-time">' + handlingTime + '</span>' +
'</div>' +
'<div class="status-indicator"></div>');
return $content;
}
$.getJSON('agents.json', function(a) {
$.each(a.agents, function(b, c) {
$("#left").append(createStatusCard(c.name,c.callStatus,c.handlingTime));
});
});
});
it's more readable and easier to debug.
This is because you have your status-card each loop nested inside your JSON loop. Therefore every time you loop through an object from the JSON data you are setting all of the status-card element's class which have already been added to the DOM.
You could restructure to set the class as you build the elements before appending.
$.each(a.agents, function(b, c) {
var content =
'<div class="agent-details">' +
'<span class="agent-name">' + c.name + '</span>' +
'<span class="handling-state">' + c.callStatus + '</span>' +
'<span class="handling-time">' + c.handlingTime + '</span>' +
'</div>' +
'<div class="status-indicator"></div>';
var $statusCard = $("<div/>").addClass("status-card");
.append(content);
$statusCard.addClass(function(){
switch(c.callStatus){
case "On Call":
return "active";
case "Idle":
return "idle";
default:
return "away";
}
}());
$statusCard.appendTo('#left');
});
I want to create a script, which would provide possibility of making food table with nutrients counting. Lets say a daily menu.
When user clicks buttons, ingredients are adding to table. There are + and - buttons in the line of ingredient to change amount of it by 1.
html:
<div class="menuContainer">
<div class="foodListContainer">
<div class="row"></div>
</div>
<div class="buttonsContainer">
<button value="100,g.,12.6,2.6,68,355">Buckweat</button>
<button value="1,ps.,6.3,5.7,0.35,78.5">Egg</button>
<button value="1,sp.,2.8,3.2,4.7,58">Butter</button>
<button value="100,g.,12.6,2.6,68,355">Meat</button>
</div>
js:
$(document).ready(function () {
//When user click a button
$(".buttonsContainer button").click(function () {
//catching the name of food
var choosenFood = $(this).text();
//catching the value of pressed button with info
//about this food and making an array with it
var value = $(this).val();
var arr = value.split(',');
//insert div's with info from array
$($.parseHTML(
'<div class="name">' + choosenFood + '</div><button class="up">+</button><div class="value">' + arr[0] + '</div><div class="unit">' + arr[1] + '</div><button class="down">-</button><div class="protein">' + arr[2] + '</div><div class="fat">' + arr[3] + '</div><div class="carbs">' + arr[4] + '</div><div class="kkal">' + arr[5] + '</div><br>')).appendTo(".row");
//trying to change value
$('.down').click(function () {
$(this).prev().prev(".value").html(function (i, val) {
return val * 1 - 1;
});
});
$('.up').click(function () {
$(this).next(".value").html(function (i, val) {
return val * 1 + 1;
});
});
});
The problem starts when there are 2 and more rows in the table. The more rows, the more + and - buttons change value. You better look at it here: https://jsfiddle.net/ts3n35bq/
I assume, that there is some problem with scopes. Probably, the crucial mistake is to call "up" and "down" actions right from "appendTo" action, and it seems like this functions repeated themselves in every row, until the end. But when I try to remove them from there, they don't work at all.
I will appreciate any advice or help. Thanks!
This should work for you.
$(document).ready(function () {
$('body').on('click', '.down', function() {
$(this).prev().prev(".value").html(function (i, val) {
return val * 1 - 1;
});
});
$('body').on('click', '.up', function() {
$(this).next(".value").html(function (i, val) {
return val * 1 + 1;
});
});
//When user click a button
$(".buttonsContainer button").click(function () {
//catching the name of food
var choosenFood = $(this).text();
//catching the value of pressed button with info about this food and making an array with it
var value = $(this).val();
var arr = value.split(',');
//insert div's with info from array
$($.parseHTML(
'<div class="name">' + choosenFood + '</div><button class="up">+</button><div class="value">' + arr[0] + '</div><div class="unit">' + arr[1] + '</div><button class="down">-</button><div class="protein">' + arr[2] + '</div><div class="fat">' + arr[3] + '</div><div class="carbs">' + arr[4] + '</div><div class="kkal">' + arr[5] + '</div><br>')).appendTo(".row");
//trying to change value
});
});
Use unbind on click function
$('.down').unbind().click(function () {
$(this).prev().prev(".value").html(function (i, val) {
return val * 1 - 1;
});
});
$('.up').unbind().click(function () {
alert($(this).next(".value").attr('id'));
$(this).next(".value").html(function (i, val) {
return val * 1 + 1;
});
});
$(".buttonsContainer").on('click','button',function (){
//your code
});
Instead of:
$(".buttonsContainer button").click(function () {
...
});
Use:
$(document).on('click', '.buttonsContainer button', function() {
...
});
Each time you click to add a div to your table you call $('.down').click() which binds the event to all the existing buttons with the "down" class. Adding more than a single row makes it so that for a single click event you have multiple handlers attached to the preexisting buttons.
You can easily fix this without changing much of your code. Instead of appending the new row directly save it to a variable first and add the click handler to the down/up element inside it:
var rowString = '<div class="name">' + choosenFood + '</div><button class="up">+</button><div class="value">' + arr[0] + '</div><div class="unit">' + arr[1] + '</div><button class="down">-</button><div class="protein">' + arr[2] + '</div><div class="fat">' + arr[3] + '</div><div class="carbs">' + arr[4] + '</div><div class="kkal">' + arr[5] + '</div><br>';
var newRow = $($.parseHTML(rowString));
newRow.filter(".down").click( function () {
$(this).prev().prev(".value").html(function (i, val) {
return val * 1 - 1;
});
});
newRow.filter(".up").click(function () {
$(this).next(".value").html(function (i, val) {
return val * 1 + 1;
});
});
newRow.appendTo(".row");
I'm using the .each function to hide/show columns of a table. But the problem is that the code is very slow in IE. After searching on internet I saw that could be because of my .each() function and $(this).
For more information why I'm using this code, you can look at this post: Hide/show column
This is my old code:
include JQuery.min.js on page
javascript:
$(function () {
$('table th').each(function (_id, _value) {
if(_id > 2){
if($(this).find("a").text()){
$('<span class="ShowHide"><div style="width:175px; display: inline-block;">- '+$(this).find("a").text()+'</div></span>').appendTo($("#togglers")).click(function (e) {
$('table td:nth-of-type(' + parseInt(_id + 1) + '),table th:nth-of-type(' + parseInt(_id + 1) + ')').toggle();
e.preventDefault();
});
}
else{
if($(this).find("div").text()){
$('<span class="ShowHide"><div style="width:175px; display: inline-block;">- '+$(this).find("div").text()+'</div></span>').appendTo($("#togglers")).click(function (e) {
$('table td:nth-of-type(' + parseInt(_id + 1) + '),table th:nth-of-type(' + parseInt(_id + 1) + ')').toggle();
e.preventDefault();
});
}
}
}
});
});
HTML:
<div id="togglers">Show/Hide columns<br/></div>
I tried to convert my javascript with this code (Source: jQuery very slow in IE), but I think there is still a problem with my i(or _id) and _value...
$(function () {
var items = $('table th');
var $currentItem;
for (var i = 0, j = items.length; i < j; i++) {
$currentItem = $(items[i]); // in place of $(this)
function (i, _value) {
if(i > 2){
if($currentItem.find("a").text()){
$('<span class="ShowHide"><div style="width:175px; display: inline-block;">- '+$currentItem.find("a").text()+'</div></span>').appendTo($("#togglers")).click(function (e) {
$('table td:nth-of-type(' + parseInt(i + 1) + '),table th:nth-of-type(' + parseInt(i + 1) + ')').toggle();
e.preventDefault();
});
}
else{
if($currentItem.find("div").text()){
$('<span class="ShowHide"><div style="width:175px; display: inline-block;">- '+$currentItem.find("div").text()+'</div></span>').appendTo($("#togglers")).click(function (e) {
$('table td:nth-of-type(' + parseInt(i + 1) + '),table th:nth-of-type(' + parseInt(i + 1) + ')').toggle();
e.preventDefault();
});
}
}
}
}
}
});
It's possible that I need to use other code. Any suggestion is welcome! Tnx.
Performance issue has nothing to do with .each. DOM is tens of times slower than any way to iterate collection you choose.
Instead of iterating table on every toggle you can make CSS do it for you. Demo.
$(function() {
var togglers = $('#togglers'), //cache toggler ref
addToggler = function(idx, text) {
togglers.append('<span class="toggler" data-id="'
+ idx + '">' + text + '</span>');
},
table = $('#table'), //cache table ref
columns = 0;
//generate styles for 100 columns table :)
(function generateStyleSheet(len){
var styles = [], i = 0;
for(; i < len; i++) {
styles.push('.hide-' + i + ' .column-' + i + ' {display: none;}') ;
}
$('<style>' + styles.join('\n') + '</style>').appendTo(document.body);
}(100))
//bind on click once using event delegation
togglers.on('click', '.toggler', function(e){
var id = $(e.target).toggleClass('pressed').data('id');
table.toggleClass('hide-' + id);
});
//generate all togglers and count em
table.find('th').each(function(idx, header){
header = $(header);
addToggler(idx, header.text()); //make toggler
header.addClass('column-' + idx); //add class column-i
columns++;
});
//add column-i class to tds
table.find('td').each(function(idx, td) {
$(td).addClass('column-' + (idx%columns));
});
});
I have created nestled arrays, which I then append to a div. When i click the button with id "name", a movie with title is stored in an array $titelBetyg, which is later stored in another array $films. Whenever i create a new $titelBetyg, i want to remove the previous $films from my div, before replacing it with the new one. How do I do this?
Javascript
$(document).ready(function(){
var $films = [];
$('#name').keyup(function(){
$('#name').css('background-color', 'white');
});
$('#options').change(function(){
$('#options').css('background-color', 'white');
});
$("#button").click(function(){
var $titelBetyg = [];
var $titel = $('#name').val();
var $betyg = $('#options').val();
if($titel == ""){
$('#name').css('background-color', 'red');
alert("Fail");
}
else if($betyg == "0"){
$('#options').css('background-color', 'red');
alert("Fail");
}
else{
$titelBetyg.push($titel);
$titelBetyg.push($betyg);
$films.push($titelBetyg);
// here is where i need to remove it before appending the new one
$('#rightbar').append("<ul>");
for(i=0; i<$films.length; i++){
$('#rightbar').append("<li>" + $films[i][0] + " " + $films[i][1] + "</li>" + "<br>");
}
$('#rightbar').append("</ul>");
}
});
$('#stigande').click(function(a,b){
});
$('#fallande').click(function(){
});
});
Use .empty() like this (and append to the <ul> instead of something else):
var $ul = $("<ul>");
for (var i=0; i<$films.length; i++) {
$ul.append("<li>" + $films[i][0] + " " + $films[i][1] + "</li><br>");
}
$('#rightbar').empty().append($ul);
Btw, it might be easier to only append the new one instead of emptying and rebuilding the whole thing:
$('#rightbar ul').append("<li>" + $titel + " " + $betyg + "</li><br>");
To remove only the list contents (and nothing else) from the #rightbar, you could use this:
var $ul = $('#rightbar ul').empty();
if (!$ul.length) // if nonexistent…
$ul = $("<ul>").appendTo('#rightbar'); // create new one
for (var i=0; i<$films.length; i++)
$ul.append("<li>" + $films[i][0] + " " + $films[i][1] + "</li>");
document.getElementById('rightbar').innerHTML = '';
That way rightbar is totally empty.
You only require to remove the content of the container. So, use the .empty() function
$('#rightbar').empty().append("<ul>"); //It will empty the content and then append
for(i=0; i<$films.length; i++){
$('#rightbar').append("<li>" + $films[i][0] + " " + $films[i][1] + "</li>" + "<br>");
}
$('#rightbar').append("</ul>");