Links stop working when using jquery to hide/show divs - javascript

I've succeeded in getting divs to show/hide but now for some reason, all other links on the page stop working unless if I open them in a new tab. How can I get this fixed?
$(document).ready(function () {
$("#div9").show("slow").siblings().hide("slow");
$('a').click(function () {
event.preventDefault();
var divname = this.name;
$("#" + divname).show("slow").siblings().hide("slow");
});
$('#seeAll').click(function() {
$('#div2').show("slow")
$('#div3').show("slow")
$('#div4').show("slow")
$('#div5').show("slow")
$('#div7').show("slow")
$('#div8').show("slow")
$('#div9').hide("slow")
})
});
<a class="people-letters" href="#" name="div2">A</a> <a class="people-letters" href="#" name="div3">B</a> <a class="people-letters" href="#" name="div4">C</a> <a class="people-letters" href="#" name="div5">D</a> E F G H I J K L M N O P Q R <a class="people-letters" href="#" name="div7">S</a> T U V <a class="people-letters" href="#" name="div8">W</a> X Y Z  <a id="seeAll" class="people-letters" href="#">See All</a>
<div>
<div id="div2" style="display: none;">
div2
</div>
<div id="div3" style="display: none;">
div3
</div>
<div id="div4" style="display: none;">
div4
</div>
<div id="div5" style="display: none;">
div5
</div>
<div id="div7" style="display: none;">
div7
</div>
<div id="div8" style="display: none;">
div8
</div>
<div id="div9" style="display: none;">
div9
</div>
</div>
Sample Link

EDIT:
You have bound your click event to ALL link elements by specifying 'a' as your selector. in order to bind it only to that specific link you can use your class that you've specified for the links that hide and show the div elements.
$('a.people-letters').click(function (event) {
event.preventDefault();
var divname = this.name;
$("#" + divname).show("slow").siblings().hide("slow");
});

Related

JavaScript How to Print A Label in a DIV?

I have 4 boxes labeled a1, a2, a3, a4 as an example. And when someone clicks on 2 boxes, I want the label (a1, a2 as an example) to print on html output. I just spent over an hour and the best I can come up was printing undefined and null.
Sorry, here is my code
HTML
<div class="container">
<div class="row">
<div class="col-md-3" label="a1">
<a class="btn btn-primary" href="#" role="button">Button 01</a>
<div class="output"></div>
</div>
<div class="col-md-3" label="a2">
<a class="btn btn-primary" href="#" role="button">Button 02</a>
<div class="output"></div>
</div>
<div class="col-md-3" label="a3">
<a class="btn btn-primary" href="#" role="button">Button 03</a>
<div class="output"></div>
</div>
<div class="col-md-3" label="a4">
<a class="btn btn-primary" href="#" role="button">Button 04</a>
<div class="output"></div>
</div>
</div>
</div>
const button = document.querySelector('.btn');
button.addEventListener('click', printLabel);
function printLabel(){
const name = document.querySelector('label');
const print = document.querySelector('.output');
print.innerText = name;
}
label isn't really a standard attribute of the <div> tag. You could try id if you're just looking for a quick solution. Also, you're accessing everything in a pretty strange way.
You should change label to id. The id attribute is pretty much universal to all HTML elements (that I know of) and will allow you to uniquely identify that element.
<div class="container">
<div class="row">
<div class="col-md-3" id="a1">
<a class="btn btn-primary" href="#" role="button">Button 01</a>
<div class="output"></div>
</div>
<div class="col-md-3" id="a2">
<a class="btn btn-primary" href="#" role="button">Button 02</a>
<div class="output"></div>
</div>
<div class="col-md-3" id="a3">
<a class="btn btn-primary" href="#" role="button">Button 03</a>
<div class="output"></div>
</div>
<div class="col-md-3" id="a4">
<a class="btn btn-primary" href="#" role="button">Button 04</a>
<div class="output"></div>
</div>
</div>
</div>
Add a unique id to all of the div elements that are meant to be your "output". This will allow your code to direct the "output" to the right element.
<div class="container">
<div class="row">
<div class="col-md-3" id="a1">
<a class="btn btn-primary" href="#" role="button">Button 01</a>
<div class="output" id="a1-output"></div>
</div>
<div class="col-md-3" id="a2">
<a class="btn btn-primary" href="#" role="button">Button 02</a>
<div class="output" id="a2-output"></div>
</div>
<div class="col-md-3" id="a3">
<a class="btn btn-primary" href="#" role="button">Button 03</a>
<div class="output" id="a3-output"></div>
</div>
<div class="col-md-3" id="a4">
<a class="btn btn-primary" href="#" role="button">Button 04</a>
<div class="output" id="a4-output"></div>
</div>
</div>
</div>
Finally, a couple of changes to your JavaScript. The first change you'll see is that I changed document.querySelector('.btn') to document.querySelectorAll('.btn'). The difference between these methods is that the first one selects ONLY the first element it finds that matches the selector, but the second one selects all elements that match the selector and creates an array.
Next, we loop through that array to add an event listener for each element.
After that, we add a parameter e (for event) to the printLabel() function because addEventListener() passes an event object in the callback function (printLabel). This object gives information about the target element related to the event.
Next, we get the target element of the event and that's your button. Then we get the parentElement of your button because your id or "label" is on the parent element. Then, you can get the name from the id of the parent element.
As a note, remember that id attributes CANNOT have spaces or . or # or really most special characters besides _.
Finally, we need to select your "output" element, and we'll use the id to do that.
document.querySelector('#' + name + '-output'); will get the element that has an id with the given name + -output. For example, if you click button a1 this will get the element with the id of a1-output. The # signifies that you're searching for an id.
Now that we stored this element in a variable print, we can place the text in it using the innerHTML property.
const button = document.querySelectorAll('.btn');
for(var i=0; i < button.length; i++) {
button[i].addEventListener('click', printLabel);
}
function printLabel(e) {
var target = e.target;
var parent = target.parentElement;
const name = parent.id;
const print = document.querySelector('#' + name + '-output');
print.innerHTML = name;
}
I created a JSFiddle to help you.
If you have any questions, please let me know.
<script>
function printDiv(divName){
var printContents = document.getElementById(divName).innerHTML;
var originalContents = document.body.innerHTML;
document.body.innerHTML = printContents;
window.print();
document.body.innerHTML = originalContents;
}
</script>
<h1> do not print this </h1>
<div id='printMe'>
Print this only
</div>
<button onclick="printDiv('printMe')">Print only the above div</button>
We can use event bubbling and data attributes to our advantage here. Replace your label attribute which is non-standard with a data attribute. Also, don't use a if it is not a navigation element, use button instead.
//Get the divs
let divs = document.querySelectorAll("[data-label]")
for(var i = 0; i < divs.length; i++){
//Add the event listener to the DIVs, yes the divs
divs[i].addEventListener("click", function(event){
//Did a button fire the event?
if(event.target.tagName === "BUTTON"){
//update the output div in the clicked div
this.querySelector(".output").innerText = this.dataset.label;
}
});
}
<div class="container">
<div class="row">
<div class="col-md-3" data-label="a1">
<button class="btn btn-primary" role="button">Button 01</button>
<div class="output"></div>
</div>
<div class="col-md-3" data-label="a2">
<button class="btn btn-primary"role="button">Button 02</button>
<div class="output"></div>
</div>
<div class="col-md-3" data-label="a3">
<button class="btn btn-primary" role="button">Button 03</button>
<div class="output"></div>
</div>
<div class="col-md-3" data-label="a4">
<button class="btn btn-primary" role="button">Button 04</button>
<div class="output"></div>
</div>
</div>
</div>
just change your script part to the following to make it work without changing HTML
<script>
//getting all buttons
var buttons = document.getElementsByClassName("btn");
//adding event listner to all buttons
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener("click", printLabel, false);
}
function printLabel() {
const outputDiv = this.parentElement.querySelector(".output"); // this will select only closet div with given class
outputDiv.innerText = this.parentElement.getAttribute("label");
}
</script>

jQuery - Loop through nested elements

I have multiple div elements having same class name (listing_class). What I need is to get href value of each anchor tag in all div elements respectively.
var length = $(".listing_class").length;
for (var i = 0; i < length; i++) {
$(".listing_class").each(function() {
console.log($(this).children('a').attr('href'));
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="listing_class " style="display: none;">
All Listings
For Sale (0)
For Rent (0)
</div>
<div class="listing_class " style="display: none;">
a
b
c
</div>
<div class="listing_class " style="display: none;">
a
b
c
</div>
<div class="listing_class " style="display: none;">
VV
CC
AQ
</div>
<div class="listing_class " style="display: none;">
VV
CC
AQ
</div>
Problem is, it returns anchor values of first div only and doesn't loop further.
Thanks in advance.
Basically a better solution would be to find all the a elements under .list_class class is if you find with the following jQuery selector $('.listing_class a') all the a tags. Then this can be used to iterate through all the necessary items and get the href attribute of each elements.
Maybe you can try the following:
$('.listing_class a').each(function(lc) {
console.log($(this).attr('href'));
});
<div class="listing_class " style="display: none;">
All Listings
For Sale (0)
For Rent (0)
</div>
<div class="listing_class " style="display: none;">
a
b
c
</div>
<div class="listing_class " style="display: none;">
a
b
c
</div>
<div class="listing_class " style="display: none;">
<a href="?section=WW&status=p" > VV</a>
<a href="?section=WW&status=p" > CC</a>
<a href="?section=WW&status=p" > AQ</a>
</div>
<div class="listing_class " style="display: none;">
VV
CC
AQ
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous"></script>
I hope this helps!

elements with the same class name in javascript

Im new to javascript because I skipped it and jumped to jquery and now Im writing a javascript code but I'm having trouble. I have multiple elements with the same class name and below each element is an a-tag. i want to hide/show the element upon clicking the button below it. How can i do this in javascript? (no jquery please).
HTML
<div>
<div class="content">content 1</div>
<a class="show-more" onclick="toggleText();" href="javascript:void(0);">Show more</a>
</div>
<div>
<div class="content">content 2</div>
<a class="show-more" onclick="toggleText();" href="javascript:void(0);">Show more</a>
</div>
<div>
<div class="content">content 3</div>
<a class="show-more" onclick="toggleText();" href="javascript:void(0);">Show more</a>
</div>
CSS
.content {
display: none;
}
Javascript
var status = "less";
function toggleText1() {
if (status == "less") {
document.getElementsByClassName("content")[0].style.display = 'block';
document.getElementsByClassName("show-more")[0].innerText = "See Less";
status1 = "more";
} else if (status1 == "more") {
document.getElementsByClassName("content")[0].style.display = 'none';
document.getElementsByClassName("show-more")[0].innerText = "See More";
status1 = "less";
}
}
in my original code i named my content as content1,content2 and my a-tag as show-more1,show-more2 then my functions as toggleText1,toggleText2 and so on. It works but i find it inefficient. Can you guys guide me to the right path?
Here's one of methods how to solve it. Catch all the links, then use Array#forEach to iterate over them and bind click event to every element. Then find the div element in the parent node and toggle it's class from hidden to visible.
ES6 solution.
var elems = document.getElementsByClassName("show-more");
Array.from(elems).forEach(v => v.addEventListener('click', function() {
this.parentElement.getElementsByClassName('content')[0].classList.toggle('hidden');
}));
.hidden {
display: none;
}
<div>
<div class="content">content 1</div>
<a class="show-more" href="javascript:void(0);">Show more</a>
</div>
<div>
<div class="content">content 2</div>
<a class="show-more" href="javascript:void(0);">Show more</a>
</div>
<div>
<div class="content">content 3</div>
<a class="show-more" href="javascript:void(0);">Show more</a>
</div>
ES5 solution.
var elems = document.getElementsByClassName("show-more");
for (var i = 0; i < elems.length; i++){
elems[i].addEventListener('click', function(){
this.parentElement.getElementsByClassName('content')[0].classList.toggle('hidden');
})
}
.hidden {
display: none;
}
<div>
<div class="content">content 1</div>
<a class="show-more" href="javascript:void(0);">Show more</a>
</div>
<div>
<div class="content">content 2</div>
<a class="show-more" href="javascript:void(0);">Show more</a>
</div>
<div>
<div class="content">content 3</div>
<a class="show-more" href="javascript:void(0);">Show more</a>
</div>
First, you can pass the element in the onclick by using the this as the argument/parameter to know the source of the on click. Then you get the parent and get the correct content div and use the style element and to do some logic on what to display or hide.
And according to your post, you should also make your content divs hidden by default.
function toggleText(aTag) {
var content = aTag.parentNode.getElementsByClassName("content")[0];
if(content.style.display == null || content.style.display == "none")
{
content.style.display = 'block';
aTag.innerText = "See Less";
}
else
{
content.style.display = 'none';
aTag.innerText = "See More";
}
}
<div>
<div class="content" style="display:none;">content 1</div>
<a class="show-more" onclick="toggleText(this);" href="javascript:void(0)">Show more</a>
</div>
<div>
<div class="content" style="display:none;">content 2</div>
<a class="show-more" onclick="toggleText(this);" href="javascript:void(0)">Show more</a>
</div>
<div>
<div class="content" style="display:none;">content 3</div>
<a class="show-more" onclick="toggleText(this)" href="javascript:void(0)">Show more</a>
</div>
also is it just me, or that just smells like a homework?
var hidePrev = function(event){
element = event.target;
element.previousSibling.previousSibling.classList.toggle('hidden');
};
.hidden {
display: none;
}
<div>
<div class="content">content 1</div>
<a class="show-more" onclick='hidePrev(event);'
href="javascript:void(0);">Show more</a>
</div>
<div>
<div class="content">content 2</div>
<a class="show-more" onclick='hidePrev(event);'
href="javascript:void(0);">Show more</a>
</div>
<div>
<div class="content">content 3</div>
<a class="show-more" onclick='hidePrev(event);'
href="javascript:void(0);">Show more</a>
</div>
You can also use a delegated event listener, which is an event listener assigned to a common ancestor element.
Check to see if the element is the type of element we are looking for (this check will probably change based on the actual content of the page), then select the previous element sibling and change the display property and text based on the current values.
This example uses a fat arrow function (introduced in the ECMAScript 2015 language specification), but a normal function expression would suffice if supporting old browsers is required.
document.addEventListener('click', event => {
const element = event.target
if(event.target.classList.contains("toggle")) {
const previous = event.target.previousElementSibling
const text = element.textContent
element.textContent = element.dataset.toggleText || "Show less"
element.dataset.toggleText = text
previous.classList.toggle('hidden')
}
})
.hidden {
display: none;
}
<div>
<div class="content hidden">content 1</div>
<a class="toggle" href="#">Show more</a>
</div>
<div>
<div class="content hidden">content 2</div>
<a class="toggle" href="#">Show more</a>
</div>
<div>
<div class="content hidden">content 3</div>
<a class="toggle" href="#">Show more</a>
</div>
Crazy, CSS Only Answer - for fun and educational purposes only
This does have some practical application, you could pre-open one of your content areas by adding a hash to the url. E.g http://yourdomain/page#Content2
.content .show-less {
display: block;
}
.content {
display: none;
}
#content-container .content:target {
display: block;
}
#content-container .content:target~.show-more {
display: none;
}
<div id="content-container">
<div>
<div class="content" id="Content1">content 1 Show Less</div>
<a class="show-more" href="#Content1">Show more</a>
</div>
<div>
<div class="content" id="Content2">content 2 Show Less</div>
<a class="show-more" href="#Content2">Show more</a>
</div>
<div>
<div class="content" id="Content3">content 3 Show Less</div>
<a class="show-more" href="#Content3">Show more</a>
</div>
</div>
More Reading:
Sibling Selector
Target Pseudo Class

Count hidden elements regardless of parent visibility

I need to count hidden elements regardless of parent visibility.
I have this code:
<div id="parent-1">
<div class="item" style="display: none;"></div>
<div class="item" style="display: none;"></div>
<div class="item"></div>
<div class="item" style="display: none;"></div>
</div>
<script>
var hidden_items = $('#parent-1').find('.item:hidden').length;
console.log (hidden_items);
</script>
In this example I get 3 items, so is correct.
But with this code:
<div id="parent-2" style="display: none;">
<div class="item" style="display: none;">
<div class="item" style="display: none;">
<div class="item">
<div class="item" style="display: none;">
</div>
<script>
var hidden_items = $('#parent-2').find('.item:hidden').length;
console.log (hidden_items);
</script>
I get 4 elements! because parent is a hidden element, but I need to get 3.
Any ideas?
You can use filter function to filter out elements that have display property set as none:
var hidden_items = $('#parent-2 .item').filter(function(){
return $(this).css('display') == "none"
}).length;
Working Snippet:
$(function(){
var hidden_items = $('#parent-2 .item').filter(function(){
return $(this).css('display') == "none"
}).length;
alert (hidden_items);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent-2" style="display: none;">
<div class="item" style="display: none;">
<div class="item" style="display: none;">
<div class="item">
<div class="item" style="display: none;">
</div>
That is because, When a parent element is hidden the children elements of it will also be hidden. That is the natural behavior. If you still want to get the elements regardless of its parent display property then use .filter with its callBack function.
var hidden_items = $('#parent-2 .item').filter(function(){
return this.style.display == "none"
}).length;
DEMO

jquery moving up/down in loop

I am trying to move the elements in the div up/down. Once its moved the item.position has to be swapped with the previous one. Below is the code. Can someone please suggest how to pass the newly assigned position and associated data seq into an array so they can passed to controller and inserted to database
<c:forEach var="item" items="${entry.value }" >
<ul>
<li> <div class="rows">
<a id='${item.position}' data-seq='${attr.id}' class="noDownloadFormat" href="/files/${item.value}" target="_blank"><c:out value="${item.title}" /></a>
<div style="float:right;margin-top:-15px;">
<input type="button" class="btn" value="UP" />
</div>
</div>
</li>
<ul>
</c:forEach>
Jquery:
$(document).ready(function () {
$(".btn1").click(function(){
var $current = $(this).closest('li')
var currentval =$(this).closest('li').children().find("a").prop("id");
var prevVal=$current.prev('li').children().find("a").prop("id");
var $previous = $current.prev('li');
if($previous.length !== 0){
$current.insertBefore($previous);
$(this).closest('li').children().find("a").prop("id",prevVal);
$current.prev('li').children().find("a").prop("id")==currentval ;
}
return false;
});
});
thanks
I modified the jquery and now I am able move up and down but not able to swap the position
I done just up button...
Tweak it online.
<html>
<body>
<ul>
<li>
<div class="rows">
<a id='position1' data-seq='id1' class="noDownloadFormat" href="#" target="_blank">title1</a>
<div style="float:right;margin-top:-15px;">
<input type="button" class="btn" value="UP 1">
</div>
</div>
</li>
<li>
<div class="rows">
<a id='position2' data-seq='id2' class="noDownloadFormat" href="#" target="_blank">title2</a>
<div style="float:right;margin-top:-15px;">
<input type="button" class="btn" value="UP 2">
</div>
</div>
</li>
<li>
<div class="rows">
<a id='position3' data-seq='id3' class="noDownloadFormat" href="#" target="_blank">title3</a>
<div style="float:right;margin-top:-15px;">
<input type="button" class="btn" value="UP 3">
</div>
</div>
</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
var handler = function (e) {
$li = $(e.target).parent().parent().parent();
// Avoid delete element if it's at top of list.
if ($li.prev().size() !== 0) {
// Move element.
$li.prev().before($li.remove());
// Bind click handler to new button.
$('.btn', $($li)).click(handler);
}
};
$('.btn').on('click', handler);
</script>
</body>
</html>

Categories

Resources