Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Dan Avramescu
11,286 PointsTargeting individual elements with same classes, but not using IDs to differentiate them
var state = "open" ;
$(".alert-container").on("click", ".alert-popup .alert-close", function(e){
e.preventDefault();
if (state !== "open")
return;
var $container = $(".alert-popup");
var $content = $(".alert-popup .content-row");
$container.css({
"right": "-270px",
"height": "40px",
"transition": "all 1s ease 0s"
});
$content.css({
"transform":"scale(.5)",
"transform-origin":"0 0",
"transition": "all 1s ease 0s"
});
state = "close";
$(e.currentTarget).addClass("hide");
$(".alert-popup .alert-open").removeClass("hide");
});
$(".alert-container").on("click", ".alert-popup .alert-open", function(e){
var state = "close";
e.preventDefault();
if (state === "open")
return;
var $container = $(".alert-popup");
var $content = $(".alert-popup .content-row");
$container.css({
"right": "0px",
"height": "80px",
"transition": "all 1s ease 0s"
});
$content.css({
"transform":"scale(1)",
"transition": "all 1s ease 0s"
});
state = "open";
$(e.currentTarget).addClass("hide");
$(".alert-popup .alert-close").removeClass("hide");
});
$(".alert-container").on("click", ".alert-popup .alert-kill", function(e){
$(".alert-popup").css("display","none");
});
Based on the code above. i have two elements , notifications like, that popup on page load. i want to be able to apply the rules above to each element, without having to use IDs (as this would mean it should require a different script for each of them and of course we don't want that.
quick glimpse to the html block:
<div class="alert-container">
<div id="alert-offer" class="alert-popup">
<a class="alert-kill" href="#">[x]</a>
<div class="pull-left close-alert">
<a class="alert-close" href="#" title="click to shrink"><div class="alert-icon">Click To Shrink</div></a>
<a class="alert-open hide" href="#" title="click to expand"><div class="alert-icon">Click To Expand</div></a>
</div>
<div class="row top-10 content-row">
CONTENT 1
</div>
</div>
<div id="alert-event" class="alert-popup">
<a class="alert-kill" href="#">[x]</a>
<div class="pull-left close-alert">
<a class="alert-close" href="#" title="click to shrink"><div class="alert-icon" >Click To Shrink</div></a>
<a class="alert-open hide" href="#" title="click to expand"><div class="alert-icon">Click To Expand</div></a>
</div>
<div class="row top-10 content-row">
CONTENT 2
</div>
</div>
</div>
I've been working on this all day and i need to get it done or i won't be able to sleep. please help
NOTE: my initial tryout was using two scripts for each ID. minimizing and maximizing each was working, however when one block was minimized and the other visible, i couldn't minimze the second one aswell. However, the kill-alert btn was working on one element even when the other element was minimised
EDIT : FUNCTIONING JS below for my fellow students
$(".alert-container").on("click", ".alert-popup .alert-close", function(e){
var state = "open" ;
e.preventDefault();
if (state !== "open")
return;
var $container = $(e.target).closest(".alert-popup");
var $content = $container.find(".content-row");
var $alert = $container.find(".alert-open");
$container.css({
"right": "-270px",
"height": "40px",
"transition": "all 1s ease 0s"
});
$content.css({
"transform":"scale(.5)",
"transform-origin":"0 0",
"transition": "all 1s ease 0s"
});
state = "close";
$(e.currentTarget).addClass("hide");
$($alert).removeClass("hide");
});
$(".alert-container").on("click", ".alert-popup .alert-open", function(e){
var state = "close" ;
e.preventDefault();
if (state === "open")
return;
var $container = $(e.target).closest(".alert-popup");
var $content = $container.find(".content-row");
var $alert = $container.find(".alert-close");
$container.css({
"right": "0px",
"height": "80px",
"transition": "all 1s ease 0s"
});
$content.css({
"transform":"scale(1)",
"transition": "all 1s ease 0s"
});
state = "open";
$(e.currentTarget).addClass("hide");
$($alert).removeClass("hide");
});
$(".alert-container").on("click", ".alert-popup .alert-kill", function(e){
var $container = $(e.target).closest(".alert-popup");
$($container).css("display","none");
});
Dan Avramescu
11,286 PointsSteven Parker , i've formatted the code and replaced images and icons loaded locally with simple text. All that is missing is including of jquery-3.2.1.min.js. What should happen at this point is to see the elements on page load, then on click on either one of them, both will shrink. clicking again will expand both.
2 Answers
Steven Parker
243,656 PointsThe revised and formatted code did the trick and exhibited the issue.
In delegated handlers, It's important to use relative tree navigation to identify specific components. By default, the jQuery selectors always find all matching elements, and the methods act on them all.
Example alternative code (old code commented):
// var $container = $(".alert-popup");
var $container = $(e.target).closest(".alert-popup");
// var $content = $(".alert-popup .content-row");
var $content = $container.find(".content-row");
By starting with the event object, and identifying the container and content with relative navigation, only the items in the same container as the link or button will be affected.
You may also need to reconsider how you make use of the variables named "state", and that one of them is global and the other is contained inside one of the handlers.
Dan Avramescu
11,286 PointsSteven Parker Thanks, that gets me a bit closer to the final result, but still not 100% correct. issues now: i can close one of the elements, but after that the second won't work at all. and this first one can only be shrinked and opened once, after that it stops working.
what i think requires more polishing: $(".alert-popup .alert-open").removeClass("hide"); $(".alert-popup .alert-close").removeClass("hide");
here i need to THIS elements' class, rather than all elements with that class. this is less important as it only shows/hides the close/open containers.
more important i think i need to define a "state" for each element rather than one set by default for all blocks. i think this is why we can't interact with each element as many times as we want (state closed/ state opened) --> cause once i click on an element and change it's state, the second element will receive the same state
can you please guide me through how i can define a general state of "open" for all elements, then when clicking one to only change that elements' state rather than all of them? thanks!
CORRECTION : i removed var state="closed" inside the second set of rules ( $(".alert-container").on("click", ".alert-popup .alert-open", function(e){ var state = "close"; ) and now i can open and close each as many times as i want, however i still cannot minimize both at the same time, just one by one. so it's definetely the state that needs to be set inside each element rather then a var state="open" for both before the onclick event.
EDIT 2 : removing var state= "open" before the set of rules and setting state="open" in the first set and state="close" in the second fixed my issue. all that is left is to target the alert-close alert-open inside each element and done! now when clicking the alert-open in one element applies the removeClass("hide") from both elements. But the issue is fixed once this is done, so @Steven thank you very much!
Dan Avramescu
11,286 PointsI've edited the code in the question to the final and fully functioning solution. again , Steven Parker , thanks a million. u are wiz!
Steven Parker
243,656 PointsSteven Parker
243,656 PointsUse the instructions for code formatting in the Markdown Cheatsheet pop-up below the "Add an Answer" area.
Or watch this video on code formatting.
Also, I wasn't able to demonstrate your basic functionality .. is there something missing from this code needed for it to work?