Link simillary name classes so that when one is clicked the other is given a class - javascript

Basically, I'm asking for a way to optimize this code. I'd like to cut it down to a few lines because it does the same thing for every click bind.
$("#arch-of-triumph-button").click(function(){
$("#arch-of-triumph-info").addClass("active-info")
});
$("#romanian-athenaeum-button").click(function(){
$("#romanian-athenaeum-info").addClass("active-info")
});
$("#palace-of-parliament-button").click(function(){
$("#palace-of-parliament-info").addClass("active-info")
});
Is there a way to maybe store "arch-of-triumph", "romanian-athenaeum", "palace-of-parliament" into an array and pull them out into a click bind? I'm thinking some concatenation maybe?
$("+landmarkName+-button").click(function(){
$("+landmarkName+-info").addClass("active-info")
});
Is something like this even possible?
Thanks in advance for all your answers.
EDIT: Here's the full HTML.
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Arch of Triumph</span>
</div>
<div class="landmark-button" id="arch-of-triumph-button"></div>
</div>
</div>
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Romanian Athenaeum</span>
</div>
<div class="landmark-button" id="romanian-athenaeum-button"></div>
</div>
</div>
----------------------------------------------------------
<div class="landmarks-info-wrapper">
<div class="landmark-info" id="arch-of-triumph-info">
<div class="info-landmark section">
<span class="landmark-title">Arch of Triumph</span>
<span class="landmark-coord">44°28′1.99″N 26°4′41.06″E</span>
</div>
</div>
<div class="landmark-info" id="romanian-athenaeum-info">
<div class="info-landmark section">
<span class="landmark-title">The Romanian Athenaeum</span>
<span class="landmark-coord">44.4413°N 26.0973°E</span>
</div>
</div>

Assuming you're not able to modify your HTML markup (in which case with use of CSS classes would be cleaner), a solution to your question would be as shown below:
// Assign same click handler to all buttons
$("#arch-of-triumph-button, #romanian-athenaeum-button, #palace-of-parliament-button")
.click(function() {
// Extract id of clicked button
const id = $(this).attr("id");
// Obtain corresponding info selector from clicked button id by replacing
// last occurrence of "button" pattern with info.
const infoSelector = "#" + id.replace(/button$/gi, "info");
// Add active-info class to selected info element
$(infoSelector).addClass("active-info");
});

Because each .landmark-button looks to be in the same order as its related .landmark-info, you can put both collections into an array, and then when one is clicked, just find the element with the same index in the other array:
const buttons = [...$('.landmark-button')];
const infos = [...$('.landmark-info')];
$(".landmark-button").click(function() {
const i = buttons.indexOf(this);
$(infos[i]).addClass('active-info');
});
This does not rely on IDs at all - feel free to completely remove those from your HTML to declutter, because they don't serve any purpose now that they aren't being used as selectors.
Live snippet:
const buttons = [...$('.landmark-button')];
const infos = [...$('.landmark-info')];
$(".landmark-button").click(function() {
const i = buttons.indexOf(this);
$(infos[i]).addClass('active-info');
});
.active-info {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Arch of Triumph</span>
</div>
<div class="landmark-button" id="arch-of-triumph-button">click</div>
</div>
</div>
<div class="landmark-wrapper">
<div class="page-content landmark">
<div class="heading span-after">
<span>Romanian Athenaeum</span>
</div>
<div class="landmark-button" id="romanian-athenaeum-button">click</div>
</div>
</div>
----------------------------------------------------------
<div class="landmarks-info-wrapper">
<div class="landmark-info" id="arch-of-triumph-info">
<div class="info-landmark section">
<span class="landmark-title">Arch of Triumph</span>
<span class="landmark-coord">44°28′1.99″N 26°4′41.06″E</span>
</div>
</div>
<div class="landmark-info" id="romanian-athenaeum-info">
<div class="info-landmark section">
<span class="landmark-title">The Romanian Athenaeum</span>
<span class="landmark-coord">44.4413°N 26.0973°E</span>
</div>
</div>
Older answer, without knowing the HTML: You can extract the ID of the clicked button, slice off the button part of it, and then select it concatenated with -info:
$(".landmark-button").click(function() {
const infoSel = this.id.slice(0, this.id.length - 6) + 'info';
$(infoSel).addClass('active-info');
});
A much more elegant solution would probably be possible given the HTML, though.

Related

I can't find the container using an only child in JavaScript [duplicate]

This question already has answers here:
Getting the parent div of element
(7 answers)
Closed last month.
I have a project. I am working to find a container using an only child in JavaScript.
I want to add a class to the container of the req-address.
I want to take req in Javascript using an only child of this element. How to do it?
const search = document.querySelector('.search-form');
const addresses = document.querySelectorAll('.req-address');
search.addEventListener('keyup', function(e) {
addresses.forEach(function(address) {
if (address.innerHTML === search.value) {
address.classList.add('.search-active');
}
});
});
<div class="reqs-container">
<div class="req">
<div class="req-time">
<div class="req-time_from">13:00</div>
<span></span>
<div class="req-time_to">15:00</div>
</div>
<div class="req-restaurant">Argentina Grill</div>
<div class="req-address">Оболонь</div>
<div class="req-name">Аліна</div>
Instagram
Приєднатися
</div>
<div class="req">
<div class="req-time">
<div class="req-time_from">13:00</div>
<span></span>
<div class="req-time_to">15:00</div>
</div>
<div class="req-restaurant">Argentina Grill</div>
<div class="req-address">Хрещатик</div>
<div class="req-name">Аліна</div>
Instagram
Приєднатися
</div>
</div>
You needed to remove the dot from the class in .classList.add('.search-active')
To add to the parent div with class = req, you can use
address.closest('div.req')
Here is an alternative version which will toggle instead of just add.
Also I use input event since it handles paste too
Lastly I use includes, textContent, trim and toLowerCase to give the user a better chance to find stuff since innerHTML could have all sorts of whitespace
If you insist on the complete value in the address field must be typed to be found, change
address.textContent.toLowerCase().trim().includes(val)
to
address.textContent === val
const search = document.querySelector('.search-form');
const addresses = document.querySelectorAll('.req-address');
search.addEventListener('input', function(e) {
const val = this.value.toLowerCase();
addresses.forEach(address => address.closest('div.req').classList.toggle('search-active', address.textContent.toLowerCase().trim().includes(val)));
});
.search-active { color: green }
<input type="text" class="search-form" />
<div class="reqs-container">
<div class="req">
<div class="req-time">
<div class="req-time_from">13:00</div>
<span></span>
<div class="req-time_to">15:00</div>
</div>
<div class="req-restaurant">Argentina Grill</div>
<div class="req-address">Оболонь</div>
<div class="req-name">Аліна</div>
Instagram
Приєднатися
</div>
<div class="req">
<div class="req-time">
<div class="req-time_from">13:00</div>
<span></span>
<div class="req-time_to">15:00</div>
</div>
<div class="req-restaurant">Argentina Grill</div>
<div class="req-address">Хрещатик</div>
<div class="req-name">Аліна</div>
Instagram
Приєднатися
</div>
</div>

Add a Like + Sort Function to existing dynamic funcion

I wrote a function that dynamically creates a webpage for me based on a json database.
Now I want to add 2 functions:
If you click the like img (its got the id button) the like counter should increase on the webpage by 1. Pretty easy just a on(click) with jQuery variable++ and then .text(variable)
A sort function - based on the likes one item received, you should be able to sort it (most liked div first, 2nd, 3rd....
I can write it for each individually with individual variables when I give all the like buttons and outputs a separate id but I wanted to make it dynamic so if you add new data to json file it dynamically works with the like and sort function.
The likes are not saved anywhere for now.
Since sitting on it for 3h and google so much and so much stackoverflow I think I overloaded my brain with different stuff and now nothing seems to work ^^
function filmInsert(insert) {
$.each(film, function(i, data) { //.each statt loop
let box =
`<div class="boxwrapper">
<div class="imgbox">
<img src="${data.img}" alt="${data.titel}">
</div>
<div class="textbox">
<h3>${data.titel}</h3>
<p>${data.beschreibung}</p>
<p> <a id="button${data.id}">
<img src="img/budspencer_official.png"> Like
</a>
<span class="output${data.id}">${data.likes}</span>
</p>
</div>
</div>`;
insert.append(box);
});
}
I've added a container element for the boxwrapper items as I assume you have one and as it's better to have one instead of just adding the sorted items to the body of the HTML document.
$(document).on("click", ".textbox a", function() {
let likes = parseInt($(this).closest(".textbox").find("span").text());
$(this).closest(".textbox").find("span").text(likes + 1);
});
$("#sort").on("click", function() {
let divs = $(".boxwrapper")
let sorted = divs.sort(function(a, b) {
return $(a).find("span").text() < $(b).find("span").text() ? 1 : -1;
});
$(".container").html(sorted);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="boxwrapper">
<div class="imgbox">
<img src="example.gif" alt="Title">
</div>
<div class="textbox">
<h3>Titel</h3>
<p>Description</p>
<p> <a id="button1">
<img src="https://dummyimage.com/40x40/000/fff&text=1"> Like
</a>
<span class="output1">0</span>
</p>
</div>
</div>
<div class="boxwrapper">
<div class="imgbox">
<img src="example.gif" alt="Title">
</div>
<div class="textbox">
<h3>Titel 2</h3>
<p>Description 2</p>
<p> <a id="button2">
<img src="https://dummyimage.com/40x40/000/fff&text=2"> Like
</a>
<span class="output2">0</span>
</p>
</div>
</div>
</div>
<button id="sort">
Sort
</button>

Jquery .clone() only works once

I'm building a menu ordering app where I have to use Jquery.
I'm using the clone() method to duplicate cart items with the necessary data ejected in. It works once, and then logs and empty object with a <prototype>.
What I am cloning is a section in my HTML I am using as a template with an id to keep it hidden. I remove this on the cloned items.
The ejecting of the data I have excluded as it is working fine and the functions are in other files, but I am open to the idea of them being the cause.
HTML:
<div class="cart-item" id="cartitem-template">
<div class="left">
<div class="image"></div>
<div class="price"></div>
</div>
<div class="mid">
<div class="name">
</div>
<div class="stars">
<span></span>
</div>
<div class="underline"></div>
<div class="toggleReviews">
<span></span>
</div>
</div>
<div class="right">
<div class="remove-cart-item">✕</div>
</div>
</div>
</div>
The JS function:
buildCartItem = function(menuItem) {
const template = $("#cartitem-template")
template
.removeAttr("id")
.clone(false)
const newCartItem = template
newCartItem.insertAfter(".cart-item")
console.log(newCartItem)
//Get object and index atts from clicked menu item
//Also set that same data into the dom of the cart item
//As well as set that data to local storage
...
// Apply data to the cloned cart item template
newCartItem.find(".image").css("background-image", "url(" + data.image + ")")
setData(".price", "$"+data.price, newCartItem)
...
}
$(".menu-item").click(function() {
buildCartItem($(this))
})
I'm I using .clone() correctly? Honestly stuck
You are removing the attribute "id" from the source element even before cloning, That's why in the subsequent method invocations it could not find an element with the id "cartitem-template". So in your method buildCartItem, remove "id" after cloning.
const newCartItem = template.clone(false).removeAttr("id");
var buildCartItem = function(menuItem) {
const newCartItem = $("#cartitem-template").clone(false).removeAttr("id");
//newCartItem.find(".image").css("background-image", "url(" + data.image + ")");
//setData(".price", "$" + data.price, newCartItem);
newCartItem.insertAfter("#cartitem-template");
}
$(".menu-item").click(function() {
buildCartItem($(this))
})
#cartitem-template {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cart-item" id="cartitem-template">
<div class="left">
<div class="image">image</div>
<div class="price">price</div>
</div>
<div class="mid">
<div class="name">name
</div>
<div class="stars">
<span>0</span>
</div>
<div class="underline"></div>
<div class="toggleReviews">
<span></span>
</div>
</div>
<div class="right">
<div class="remove-cart-item">✕</div>
</div>
</div>
<button class="menu-item">Clone</button>
i had similar problem and i solved using function:
function getClone(){
return $(myCloningDiv).clone()
}

Javascript click specific to ID

I have a div setup like so:
<div class="content">
<button class="show-comments" id="content1"></button>
</div>
<div class="comments-wrapper" id="comment1"></div>
<div class="content">
<button class="show-comments" id="content2"></button>
</div>
<div class="comments-wrapper" id="comment2"></div>
I have the following code:
$('.show-comments').click(function(e){
e.preventDefault();
$('.comments-wrapper').slideToggle('slow');
});
As you would assume, the code works but on a class basis. I'd like for it to open up only the .comments-wrapper of its associated id (i.e. open slideToggle comments2 if content 2 button is clicked and so on and so on).
How would I do this?
$('.show-comments').click(function(e){
e.preventDefault();
$(this).closest(".content").next('.comments-wrapper').slideToggle('slow');
});
Note that this is dependent on the .content element being immediately followed by the .comments-wrapper.
If you have access to modify the html itself, I would suggest adding a wrapper element and then doing the following to avoid the reliance on the exact order of elements:
<div class="wrapper">
<div class="content">
<button class="show-comments" id="content1"></button>
</div>
<div class="comments-wrapper" id="comment1"></div>
</div>
<div class="wrapper">
<div class="content">
<button class="show-comments" id="content2"></button>
</div>
<div class="comments-wrapper" id="comment2"></div>
</div>
$(this).closest(".wrapper").find('.comments-wrapper').slideToggle('slow');
This way, if you add an element between the .content and the .comments-wrapper it does not break the code.
You can do this:
$(this).parent("div").next('.comments-wrapper').slideToggle('slow');
This will find the related div of class .comments-wrapper and slide toggle.
And a fiddle: http://jsfiddle.net/xCJQB/
$('.show-comments').click(function (e) {
e.preventDefault();
var num = this.id.match(/\d+$/)[0];
$("#comment" + num).slideToggle('slow');
});
Demo ---> http://jsfiddle.net/7pkyk/1/
Use this context
$(this).closest('.comments').next('.comments-wrapper').slideToggle('slow');
If it is not the immediate element then you might try this as well
$(this).closest('.comments')
.nextAll('.comments-wrapper').first().slideToggle('slow');
you can add a common class to associate a button with a div.
html:
<div class="content">
<button class="show-comments group1" id="content1"></button>
</div>
<div class="comments-wrapper group1" id="comment1">1</div>
<div class="content">
<button class="show-comments group2" id="content2"></button>
</div>
<div class="comments-wrapper group2" id="comment2">2</div>
javascript:
$('.show-comments').click(function(e){
var associate = $(this).attr('class').match(/group\d+/).pop();
var selector = '.comments-wrapper.' + associate;
e.preventDefault();
$(selector).slideToggle('slow');
});
http://jsfiddle.net/uMNfJ/

Jquery throw only one action

I have organized the page this way:
<div class="singlePost">
<div class="post"> </div>
<div class="comments" data-idPost="310"> </div>
<div class="formComment">
<textarea data-idPost="310"></textarea>
<button data-idPost="310">Insert</button>
</div>
</div>
<div class="singlePost">
<div class="post"> </div>
<div class="comments" data-idPost="304"> </div>
<div class="formComment">
<textarea data-idPost="304"></textarea>
<button data-idPost="304">Insert</button>
</div>
</div>
I used html5 data-attributes to distinguish posts and my jquery code is:
$(".formCommento button").click(function() {
idPost=$(this).attr('data-idpost');
text=$('textarea[data-idpost="'+idPost+'"]').val();
noty({text: 'I\'m going to insert '+text});
//and here i make the ajax request
return false;
});
I think this is not the way to organize this kind of stuff. I have the problem that when i click on the button i have multiple actions running together so the same comment is inserted several times. What do you suggest to do?
If you are learning to "organize" as well, I would suggest only to use once your data-, like:
<div class="singlePost" data-postId="310">
<div class="post"> </div>
<div class="comments"> </div>
<div class="formComment">
<textarea></textarea>
<button class="btn-submit">Insert</button>
</div>
</div>
<div class="singlePost" data-postId="311">
<div class="post"> </div>
<div class="comments"> </div>
<div class="formComment">
<textarea></textarea>
<button class="btn-submit">Insert</button>
</div>
</div>
then, fire it for every button:
$(".singlePost .btn-submit").click(function() {
var singlePost = $(this).closest(".singlePost"), // get singlePost block
postId = singlePost.attr("data-postId"), // read data attribute
txt = singlePost.find("textarea").val(); // get it's own textarea value
// do your magic
});
Here's a live example: http://jsbin.com/iyomaj/1/edit
try this, pass related context, by default jQuery uses document as context so it search in whole document
$(".formComment button").click(function() {
var parentdiv = $(this).closest('.formComment');
idPost=$(this).attr('data-idpost');
text=$('textarea[data-idpost="'+idPost+'"]',parentdiv ).val();
noty({text: 'I\'m going to insert '+text});
//and here i make the ajax request
return false;
});

Categories

Resources