Cleaner Way to Write This jQuery? [closed] - javascript

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 months ago.
Improve this question
I have a full-page menu that opens on a button click with two different sections. The content in #terms doesn't change, but the content in #links does, based on which button you click. The code itself works fine, but the jQuery feels incredibly bulky and I was wondering if anyone could suggest any ways to make it a bit cleaner. Also, the HTML structure has to pretty well stay as-is because its kind of finnicky with the styling.
I should also note that I'm not the most experienced with jQuery, so...
This is the code in question and the relevant HTML (the buttons at the top are in another part of the HTML, but I included them here to see how they're structured):
$("#codes-launch, #gfx-launch, #tuts-launch, #menu-close").click(function() {
$("#menu").slideToggle("slow");
$("body").toggleClass("scroll-lock");
});
$("#codes-launch").click(function() {
$("#codes").show();
$("#gfx, #tuts").hide();
});
$("#gfx-launch").click(function() {
$("#gfx").show();
$("#codes, #tuts").hide();
});
$("#tuts-launch").click(function() {
$("#tuts").show();
$("#codes, #gfx").hide();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="codes-launch">Codes</button>
<button id="gfx-launch">Graphics</button>
<button id="tuts-launch">Resources</button>
<div id="menu">
<div id="terms">SOME STUFF</div>
<div id="links">
<button id="menu-close">Close</button>
<div id="codes">Codes</div>
<div id="gfx">Graphics</div>
<div id="tuts">Resources</div>
</div>
</div>

Using a data attribute and a common selector, you can replace all the clicks into one.
$("button[data-toggles]").on("click", function(evt) {
evt.preventDefault();
$("#links > div").hide();
const selector = $(this).data('toggles');
$(selector).show();
$("#menu").slideDown("slow");
$("body").addClass("scroll-lock");
});
$("#menu-close").on("click", function() {
$("#menu").slideUp("slow");
$("body").removeClass("scroll-lock");
});
#menu {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="codes-launch" data-toggles="#codes">Codes</button>
<button id="gfx-launch" data-toggles="#gfx">Graphics</button>
<button id="tuts-launch" data-toggles="#tuts">Resources</button>
<div id="menu">
<div id="terms">SOME STUFF</div>
<div id="links">
<button id="menu-close">Close</button>
<div id="codes">Codes</div>
<div id="gfx">Graphics</div>
<div id="tuts">Resources</div>
</div>
</div>

I see your not on style, probably something there that can be addressed as a separate question - probably just some odd CSS with an easy fix.
Here I used classes and did some minor structure changes to facilitate some "grouping" - I set and clear a data value to make the code slightly less and not impact the page DOM as much as it does not toggle classes (often messes with style a bit when toggled)
Totally out of scope but I added a Show/Hide just for fun that can be clicked also and set an initial state for "Show" to be hidden on that.
I also note there is no "initial" filter/group but left that out and made a comment in the code to illustrate it being set on page load.
$("#lanchers, #menu-close").on('click', function() {
$("#menu").slideToggle("slow");
$("body").toggleClass("scroll-lock");
var h = $(".up-down").filter(":hidden");
h.show();
$(".up-down").not(h).hide();
});
// just to set up the initial state
$("#lanchers").find(".up-down").first().hide();
// we could trigger on one of these on startup to set some initial target as the "visible" one
$("#lanchers").on('click', '.launcher-thing', function() {
const $targ = $(this.dataset.target);
$(".target-thing").not($targ).each(function(event) {
this.dataset.show = "nope";
});
$targ.get(0).dataset.show = "yep";
});
.scroll-lock {
border: 1px solid lime;
}
#links {
border: solid blue 1px;
background-color: #ffeeee;
}
[data-show="yep"] {
display: block;
}
[data-show="nope"] {
display: none;
}
.up-down {
background-color: #eeffee;
padding: 0.5em;
display: inline-block;
border: solid 1px #ccffcc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="lanchers">
<button class="launcher-thing" data-target="#codes">Codes</button>
<button class="launcher-thing" data-target="#gfx">Graphics</button>
<button class="launcher-thing" data-target="#tuts">Resources</button>
<span class="toggle-thing">
<span class="up-down">Show</span>
<span class="up-down">Hide</span></span>
</div>
<div id="menu">
<div id="terms">SOME STUFF</div>
<div id="links">
<button id="menu-close">Close</button>
<div id="codes" class="target-thing">Codes</div>
<div id="gfx" class="target-thing">Graphics</div>
<div id="tuts" class="target-thing">Resources</div>
</div>
</div>

Related

Changing classes with jQuery but the element doesn't change color?

I was in the middle of self studying HTML, CSS and JavaScript when at my job, an interviewer came to me and suggested to study jQuery as it was the “standard” now days.
So I decided to do that and started to migrate my own web page project for a future game I'm going to make, to jQuery, and it is pretty easy to understand so far and made me compress 150 or so lines of javaScript into 70 (more or less).
Now I am trying to add a class to a button when clicked using jQuery,
for that I am using:
$(this).addClass("buttonActive");
In CSS, the button is:
.menu .buttonActive {
background-color: #222629;
}
When clicking the button, the buttin does change color, and that is perfect, but I wanted to make so that the color changes to the original one once I click another button, but it is not working.
For that I am using:
$("#buttonClicked").removeClass("buttonActive");
I also tried adding another class together when removing the buttonActive but it didn't work.
$("#buttonClicked").removeClass("buttonActive").addClass("buttonNotActive");
.buttonNotActive {
background-color: #10394E;
}
Try this example:
First remove buttonActive class from all buttons except the clicked one
Toggle buttonActive class for the clicked button
$(".myButton").click(function() {
$(".myButton").not($(this)).removeClass('buttonActive');
$(this).toggleClass("buttonActive");
})
.menu .buttonActive {
background-color: #222629;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="menu">
<button class="myButton">My button</button>
<button class="myButton">My button</button>
<button class="myButton">My button</button>
</div>
I didn't understand well. Like this?
$("#buttonClicked").click(function(){
$(this).addClass("buttonActive");
})
$("#change").click(function(){
$("#buttonClicked").removeClass("buttonActive");
})
.menu .buttonActive {
background-color: #222629;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="menu">
<button id="buttonClicked">Button</button>
<button id="change">Change</button>
</div>
Add a class to each of the elements that would be clicked. Use that class for the click function. When that element is clicked, remove the active class from the elements, and apply it to the element that was clicked.
In this example when you click on one of the elements its background will change to red. If you click on another element, it returns to its original color.
$( ".menu-item" ).click(function() {
$(".menu-item").removeClass("buttonActive");
$(this).addClass("buttonActive");
});
.item-1 {
background-color: green;
}
.item-2 {
background-color: orange;
}
.item-3 {
background-color: purple;
}
.menu p {
color: #fff;
}
.buttonActive {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<div class="menu">
<p class="item-1 menu-item">Item 1</p>
<p class="item-2 menu-item">Item 2</p>
<p class="item-3 menu-item">Item 3</p>
</div>
Thanks to everyone who answered.
Thanks to the ideas, I thought of selecting all buttons from my page and removing the buttonActive class
$(:button).removeClass("buttonActive");
$(this).addClass("buttonActive");

Show/Hide feature [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm trying to create a feature using either jQuery or vanilla JS. My feature should be able to show/hide content on click. The initial task is easy enough and I'm able to show my hidden div using jQuery toggle, but I would also like to be able to switch my FA icon as well as the link text from 'Show content' to 'Hide content'.
Use
.toggleClass(`.fa-check .fa-cross')
add one as the default.
Toggle text can be handled by either not using .toggle (using .show/.hide) instead or by including a span for each text and toggling those. Or by having 2 buttons and toggling those.
Example snippet (needs fa icons)
$(".toggle").click(function() {
$(this).toggleClass("collapsed expanded")
$(this).find("i").toggleClass("fa-chevron-up fa-chevron-down")
});
.wrapper { border: 1px solid #CCC; width: 200px; }
.wrapper .details { border-top: 1px solid #CCC; }
.wrapper .toggle.collapsed > div.details { display:none; }
.wrapper .toggle.expanded > .more { display:none; }
.wrapper .toggle.collapsed > .less { display:none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='wrapper'>
<div class='toggle collapsed'><i class='fa fa-chevron-up'></i>
<div class='more'>more</div><div class='less'>less</div>
<div class='details'>details</div>
</div>
</div>
You can apply the same logic for the text to the icon as well if preferred (include 2 <i class='fa...) and then use css to show/hide them based on the class on the parent.
You can also add some css transition so it's less jumpy, or you can use $(this).find(".more,.less").slideToggle() instead of just toggle to add an effect.
There are dozens of ways to do it. Below is a step-by-step tutorial.
This should work, assuming you have already included jQuery.
<img id="imgtog" onclick="toggle()" src="someimg1.png">
<div id="content" hidden="">content</div>
<script>
var tog = false;
function toggle()
{
if(tog == false)
{
$('#content').removeAttr('hidden');
$('#imgtog').attr('src', 'otherimage2.png');
tog = true;
}
else
{
$('#content').attr('hidden', '');
$('#imgtog').attr('src', 'someimg1.png');
tog = false;
}
}
</script>

Insert HTML or append Child onClick, and remove from previous clicked element

I have a set of div elements inside a container, .div-to-hide is displayed by default whilst .div-to-show is hidden.
When I click in .set, .div-to-hide should hide and .div-to-show should be visible. Next click should return the previous clicked element to its default state.
I need to display to buttons on click inside on .div-to-show.
<div class="container">
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
<div class="set">
<div class="div-to-hide">Some text</div>
<div class="div-to-show"></div>
</div>
</div>
So far I have this:
let lastClicked;
$('.container').on('click', function(e) {
if (this == lastClicked) {
lastClicked = '';
$('.div-to-hide').show();
$(this).children('.div-to-hide').hide();
} else {
lastClicked = this;
$('.div-to-hide').hide();
$(this).children('.div-to-hide').show();
$(this).children('.div-to-show').hide();
}
});
Can't get it to work properly tho.. I don't know what I am missing...
Any help is deeply appreciated!
UPDATE: got it working! Thanks everyone!
First, you are not using delegation (second parameter on the $.on() function) to define the .set element as your this inside the function.
If I understood correctly, you want to show the elements on the last one clicked and hide the rest. You don't really need to know which one you last clicked to do that
$('.container').on('click', '.set', function (e) {
// Now "this" is the clicked .set element
var $this = $(this);
// We'll get the children of .set we want to manipulate
var $div_to_hide = $this.find(".div-to-hide");
var $div_to_show = $this.find(".div-to-show");
// If it's already visible, there's no need to do anything
if ($div_to_show.is(":visible")) {
$div_to_hide.show();
$div_to_show.hide();
}
// Now we get the other .sets
var $other_sets = $this.siblings(".set");
// This second way works for more complex hierarchies. Uncomment if you need it
// var $other_sets = $this.closest(".container").find(".set").not(this);
// We reset ALL af them
$other_sets.find(".div-to-show").hide();
$other_sets.find(".div-to-hide").show();
});
Consider using class toggling instead.
$('.set').on('click', function(e) {
$('.set').removeClass('hidden-child');
$(this).addClass('hidden-child');
});
css:
.hidden-child .div-to-hide, .div-to-show {
display: none;
}
.hidden-child .div-to-show, .div-to-hide {
display: block;
}
This will make your code easier to reason about, and lets css control the display (style) rules.
Edit: changed class name for clarity; expanded explanation; corrected answer to conform to question
Try to make use of siblings() jQuery to hide and show other divs and toggle() jQuery to show and hide itself and also you will need to set click() event on .set, not in .container
$(document).on('click', '.set', function(e) {
$(this).find('.hide').toggle();
$(this).find('.show').toggle();
$(this).siblings('.set').find('.hide').show();
$(this).siblings('.set').find('.show').hide();
});
.show {
display: none;
}
.set div {
padding: 10px;
font: 13px Verdana;
font-weight: bold;
background: red;
color: #ffffff;
margin-bottom: 10px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="set">
<div class="hide">1 Hide</div>
<div class="show">1 Show</div>
</div>
<div class="set">
<div class="hide">2 Hide</div>
<div class="show">2 Show</div>
</div>
<div class="set">
<div class="hide">3 Hide</div>
<div class="show">3 Show</div>
</div>
</div>

Javascript - show a button inside of a DIV when clicked (and hide all others)

I have a list of DIVS that have buttons inside. By default, all buttons are hidden. When I click within a DIV area, the current button inside of this clicked DIV are should show (class='.db') AND all previously clicked/shown buttons should be hidden (class='.dn'). In other words, at any time there should be only one button (currently clicked) shown and all other should be hidden.
I want to use vanilla Javascript and tried this below, but it won't work. I feel there is some small error but don't know where.. Note - the DIVS and buttons don't have their own unique IDs (they only have the same CSS (.posted) classes.
PS - maybe it'd be better not to add this onClick="t();" to each DIV and use an 'addEventListener' function, but this is way too much for me ; )
CSS:
.dn {display:none}
.db {display:block}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
HTML:
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
<div class="posted" onClick="t();">
<button class="dn">Reply</button>
</div>
JAVASCRIPT:
function t()
{
var x=document.getElementsByClassName("posted"),i,y=document.getElementsByTagName("button");
for(i=0;i<x.length;i++)
{
x[i].y[0].className="dn";
};
x.y[0].className='db';//make sure the currently clicked DIV shows this button (?)
}
You might want to read more about selector, how to select class, block level etc.
some link might be helpful:
CSS selector:
https://www.w3schools.com/cssref/css_selectors.asp
jQuery selector:
https://api.jquery.com/category/selectors/
Solution - Using jQuery:
$('.posted').on('click', function() {
//find all class called posted with child called dn, then hide them all
$('.posted .dn').hide();
//find this clicked div, find a child called dn and show it
$(this).find('.dn').show();
});
.dn {
display: none
}
.db {
display: block
}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="posted">
<button class="dn">Reply1</button>
</div>
<div class="posted">
<button class="dn">Reply2</button>
</div>
<div class="posted">
<button class="dn">Reply3</button>
</div>
Solution - Pure js version:
//get list of div block with class="posted"
var divlist = Array.prototype.slice.call(document.getElementsByClassName('posted'));
//for each div
divlist.forEach(function(item) {
//add click event for this div
item.addEventListener("click", function() {
//hide all button first
divlist.forEach(function(el) {
el.getElementsByTagName('button')[0].classList.add('dn');
});
//show button of the div clicked
this.getElementsByTagName('button')[0].classList.remove('dn');
}, false);
});
.dn {
display: none
}
.db {
display: block
}
.posted {
height: 50px;
width: 100px;
background-color: green;
border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="posted">
<button class="dn">Reply1</button>
</div>
<div class="posted">
<button class="dn">Reply2</button>
</div>
<div class="posted">
<button class="dn">Reply3</button>
</div>
You can do this with with plain JavaScript using Event Bubbling, querySelector and the element classList attribute like this.
Change your HTML to look like this:
<div class="posts">
<div class="posted">
<button class="dn">Reply</button>
</div>
<div class="posted" >
<button class="dn">Reply</button>
</div>
<div class="posted" >
<button class="dn">Reply</button>
</div>
</div>
Then use JavaScript like this:
var posts = document.querySelector('.posts');
var allPosted = document.querySelectorAll('.posted');
//clicks bubble up into the posts DIV
posts.addEventListener('click', function(evt){
var divClickedIn = evt.target;
//hide all the buttons
allPosted.forEach(function(posted){
var postedBtn = posted.querySelector('button');
postedBtn.classList.remove('db');
});
// show the button in the clicked DIV
divClickedIn.querySelector('button').classList.add('db')
});
You can find a working example here: http://output.jsbin.com/saroyit
Here is very simple example using jQuery .siblings method:
$(function () {
$('.posted').click(function () {
$('button', this).show();
$(this).siblings().find('button').hide();
});
});
https://jsfiddle.net/3tg6o1q7/

JS script not working properly [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
JS code:
function showCaption() {
var captionVis = $('.grey-box-caption-text').css('display');
if(captionVis = "none") {
$('.grey-box-caption-text').width(0);
$(this).find('.grey-box-caption-text').show().animate({'width': '464px'},750);}
} else {
$(this).find('.grey-box-caption-text').animate({'width': '0'},750,
function(){$(this).hide();});
}
};
$('.caption-container').click(function() {
showCaption();
return false;
}
);
HTML code:
<div class="one-half column home-three-img">
<div class="caption-container">
<div class="grey-box-caption">
</div>
<div class="grey-box-caption-text">This is a caption test - Hopefully this works
</div>
</div>
<img src="images/3.jpg">
</div>
This won't work and I'm a JS noob. Please help.
I'm trying to get the caption section to slide out from the left to the right. When i click on the parent container nothing happens. I'm expecting the caption to shoot out and hide when I click again.
I have Jquery loaded properly and have a document.ready function that works.
Link to the WIP http://clients.pivotdesign.com/dev/annual_report_2014/index.html
A big problem is that the value of this won't be set in your "showCaption" function. Add a return false; to the end of that function:
function showCaption(){
var captionVis = $('.grey-box-caption-text').css('display');
if (captionVis == "none") {
$('.grey-box-caption-text').width(0);
$(this).find('.grey-box-caption-text').show().animate({'width': '464px'},750);
}
else {
$(this).find('.grey-box-caption-text').animate({'width': '0'},750, function(){
$(this).hide();
});
}
};
and then change the handler assignment to:
$('.caption-container').click(showCaption);
Also note that your test in that if statement was incorrect: use == or === for comparison.
I modified the CodePen from Pointy a bit and it should do the same with less code.
Why the gray box increases the height here in the SO demo, I don't know. In this CodePen it works with-out this "bug".
function showCaption() {
var $graybox = $('.grey-box-caption-text');
$graybox.animate({
width: 'toggle',
opacity: 'toggle'
}, 'slow');
};
$(function(){
$("#wrapper").on("click", showCaption);
});
.grey-box-caption {
min-height: 3em;
min-width: 20px;
background-color: #bbb;
display: inline-block;
}
.grey-box-caption-text {
display: none;
padding: 1em;
font-family: sans-serif;
white-space: nowrap;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<div class=grey-box-caption>
<div class=grey-box-caption-text>
Hello World this is some text.
</div>
</div>
</div>

Categories

Resources