How to make div clickable? - javascript

I want to make this div click-able and want to use same href of inside <a> and want to keep link in inside <a> also (so if JS is disabled then link will be accessible).
<div id="example">
<p> some text </p>
<img src="example.jpg />
<a href="http://stackoverflow.com"> link </link>
</div>
I mean i need like this.
<div id="example" href="http://stackoverflow.com">
<p> some text </p>
<img src="example.jpg />
<a href="http://stackoverflow.com"> link </link>
</div>

Something like this should do
$('#example').click(function() {
window.location.href = $('a', this).attr('href');
});

I cannot reply to the above conversation yet because I am new here, but I just wanted to say that you do not need to return false from this function. What that does is prevent the default behavior of the event from happening (which, in the case of clicking a div is nothing) and prevent the event from propagating up to the next element in the DOM hierarchy.
It is unlikely that either of these are necessary for this case. Additionally, if you do need these behaviors, you can get them separately and more clearly like so:
// note that the function will be passed an event object as
// its first argument.
$('#example').click(function(event) {
event.preventDefault(); // the first effect
event.stopPropagation(); // the second
window.location.href = $('a', this).attr('href');
});
Again, I don't think either approach is necessary in this case, but it is important to understand how they work, because you will need one or both of them frequently.

<html>
<body>
<div onclick="window.location.href = this.getElementsByTagName('a')[0].href;">
<p>some text</p>
link
</div>
</body>
</html>

The above answers are all accepted by me. And generally u can make the same or even more great
effect to "div" than "a" by css. And you can add js function to show the css changes when a event happened like Click. Maybe like this: DIV.onclick = function(){ change the target dom object css here }。 then when the event occurs, you will see the effect. and if you want to change href to another one. write js like location.href="http://www.target.com"; it will work for you.

Related

each loop should only run once when button is clicked

I want to hide a div when a button is clicked and then show the next div with the same class. I have tried using this code, but when I do this, the next div that I want shown also fades out.
$('.arrow:last-of-type').on('click', function(){
$( ".collaboration" ).each(function( index ) {
if($('.collaboration').css('display') == 'block'){
$(this).fadeOut()
$(this).next().fadeIn()
}
})
})
Is there a way to stop the each() from running when it is executed once and then run again when the click action happens?
Here's the HTML:
<div id="collaborations">
<p class="arrow"><</p>
<div class="collaboration">
<img src="./img/test.png" />
<p>Text</p>
<button>Visit</button>
</div>
<div class="collaboration">
<img src="./img/test.png" />
<p>Text</p>
<button>Visit</button>
</div>
<div class="collaboration">
<img src="./img/test.png" />
<p>Text</p>
<button>Visit</button>
</div>
<p class="arrow">></p>
</div>
</div>
Thanks
Solution
You could solve this by not iterating through the .collaborations at all.
The key thing is that you need to keep track of which one is currently being shown.
If you know that, then what your click handler can do is show the next one and hide the current one.
I would suggest doing that with a class .active on the same div as .collaboration. You can then select the next div by $('.active').next().addClass('.active'), and deselect by $('.active').removeClass('.active').
You might need to store a reference to your first element before you select the next one 👍
Example
Here's a quick example of how this might work: https://codepen.io/juancaicedo/pen/LYGgPWa
I moved around the html to group all the collaborations into a div by themselves.
Other approaches
You'll find that you have to think through some other behaviors with the solution above. For example, in my example, there is a moment when two items are on the screen, causing their container div to grow and later shrink.
For these reasons, I don't like handling presentation from within javascript (i.e. using jquery's fadeIn/fadeOut).
If you can find a way to instead using only css, I think that's preferable. Here's an example using css transitions
https://codepen.io/juancaicedo/pen/ZEQqzrR
The each method of jQuery can be stopped whenever you want by returning false inside of the callback, so you can probably fix your code by doing this:
$('.arrow:last-of-type').on('click', function(){
$( ".collaboration" ).each(function( index ) {
if($('.collaboration').css('display') == 'block'){
$(this).fadeOut()
$(this).next().fadeIn()
return false;
}
});
});

jQuery.toggle() not working on a div

On a web page we have a list of profiles. On the right hand side of the profile is some text, followed by an arrow img#arrow.
When img#arrow is clicked, we have the following jQuery we hope to run:
However, the corresponding .bottom-sec is not toggling.
jQuery('#arrow').click(function(){
var $parent = $(this).parent();
$($parent).addClass('active');
jQuery($parent +' .bottom-sec').toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="profile-right">
<h2>Bob Brown</h2>
<h3>Non-Executive Chairman</h3>
<p>Intially showing text.</p>
<div class="bottom-sec" style="display: none;">
<p>Initially hidden text.</p>
</div>
<img id="arrow" src="/wp-content/themes/wtc/images/icons/down-arrow-circle-hi.png">
</div>
Problem
The problem with your code is exactly what the comment on your question is saying, but he didn't explain anything:
You're combining two different ways of selecting elements. One is with selectors, the other is traversing. You're using them in a way which isn't possible (the $parent + ' .bottom-sec' part). The comment linked to a jQuery page about traversing which you should definitely read! It tells you a lot about how to use traversing functions, which you could use!
Solution
There are multiple solutions to this, but I'll write down the one I think is the best:
First of all, change the HTML a bit. I've removed the element style of .bottom-sec and changed the id of the image to a class, because you have multiple images with the same id on the page, which is not a recommended thing to do. Classes can occur more than once, id's cannot.
<div class="profile-right">
<h2>Bob Brown</h2>
<h3>Non-Executive Chairman</h3>
<p>Intially showing text.</p>
<div class="bottom-sec">
<p>Initially hidden text.</p>
</div>
<img class="arrow" src="/wp-content/themes/wtc/images/icons/down-arrow-circle-hi.png">
</div>
I've reduced the JavaScript to the following. Note that is just reduced to one line, where a click on the .arrow element goes searching for the closest .profile-right parent. If, for whatever reason, you decide to change the HTML and the .arrow element is no longer a child of the .profile-right, this code still works. The only thing it does is toggle an active class on the .profile-right.
jQuery(document).on('ready', function() {
jQuery('.arrow').on('click', function(){
jQuery(this).closest('.profile-right').toggleClass('active');
});
});
The document ready listener was added because of OP's comment.
With CSS, we can use the new .active class to show or hide the element.
.profile-right .bottom-sec {
display: none
}
.profile-right.active .bottom-sec {
display: block
}
Original Code Fix
If for some reason you wanted to use your original code, this is how it should be:
// Nothing wrong about this part.
// Your only worry should be that there could be
// multiple elements with the same ID, which is something really bad.
jQuery('#arrow').click(function(){
// This part is correct, no worries
var $parent = $(this).parent();
// Removed the $(...), because $parent is already a jQuery object
$parent.addClass('active');
// Changed the selector to a find function
$parent.find('.bottom-sec').toggle();
});
You could also combine all of the code inside the listener function to just one line:
jQuery('#arrow').click(function(){
$(this).parent().addClass('active').find('.bottom-sec').toggle();
});
Change your js code like below.
jQuery('#arrow').click(function(){
var $parent = $(this).parent();
$($parent).addClass('active');
jQuery($parent).find('.bottom-sec').toggle();
});
In your event listener you can catch the element (the down arrow) that triggered the event. It will be referred as this.
Then you can go through the DOM tree using .next() and .parent() to access the <div> to toggle.
Note: you may need more functions than the one I explained above.
Note 2: without code or more detailed information, we can't help you further, I will edit this answer if you add details.

Adding and removing classes not working

I've used this exact code on a different div element and it works perfectly. When I went to add the same code to another div element with a different id it registers the element has been clicked but it doesn't add or remove any of the classes.
$('#quoteClick').click(function(){
$('#cbox-1').addClass('displayCboxBackground');
$('#cbox-2').removeClass('displayCboxBackground');
$('#cbox-3').removeClass('displayCboxBackground');
$('#dbox-1').addClass('displayBlock');
$('#dbox-2').removeClass('displayBlock');
$('#dbox-3').removeClass('displayBlock');
console.log("clicked");
});
The html structure is as follows:
<div id="cbox-1">
<div id="dbox-1">
content...
</div>
</div>
<div id="cbox-2">
<div id="dbox-2">
content...
</div>
</div>
<div id="cbox-3">
<div id="dbox-3">
<div id="quoteClick">
a quote
</div>
</div>
</div>
JSFiddle: https://jsfiddle.net/m81c23cx/1/
In the fiddle you can see the content will changes when each header is clicked. When the "quoteClick" element is clicked I want it to change to the second headers content exactly how it does when the second header is clicked.
I can see in Chrome's console that when I click the div element that it highlights all the classes but it doesn't change any of them. I have the jQuery inside a document.ready() function so it should be waiting for the DOM to load and it works perfectly when I just write the lines into the console.
I'm surprised that nobody actually questioned your use of ids (instead of suggesting that you should double-check for dupes). The reason why this code is hard to debug is because it's too complicated. As a result, you'll have a hard time fixing issues similar to this in the future too.
Drop it, do it better.
I didn't even go through your fiddle. Instead, I'm going to propose that you change your approach altogether.
Update your HTML and use classes instead of ids. Something similar to this:
<div class="cbox">
<div class="dbox">
content...
</div>
</div>
<div class="cbox">
<div class="dbox">
content...
</div>
</div>
<div class="cbox">
<div class="dbox">
<div id="quoteAdvert">
a quote
</div>
</div>
</div>
Update your JavaScript and use this to get the context of the current box:
$('.cbox').click( function cboxClicked () {
// Remove the previous class from all .cbox & .dbox elements; we don't care which
$('.cbox').removeClass('displayCboxBackground')
$('.dbox').removeClass('displayBlock')
// Add a new class to the clicked .cbox & it's child .dbox
$(this).addClass('displayCboxBackground')
$(this).children('.dbox').addClass('displayBlock')
})
The beauty of this? You can have 1000 boxes, it'll still work. No need to add any extra lines of code.
Here's a fiddle showing it in action.
The example code you provided is not consistent with the jsfiddle you created.
In your fiddle, you use the jquery selector $('#quoteClick') but there is no element with that id. There is a #quoteAdvert element however. Change that and you'll see the click in the console.
The classList property returns a token list of the class attribute of the element in question. Luckily for us, it also comes with a few handy methods:
add - adds a class
remove - removes a class
toggle - toggles a class
contains - checks if a class exists
// adds class "foo" to el
el.classList.add("foo");
// removes class "bar" from el
el.classList.remove("bar");
// toggles the class "foo"
el.classList.toggle("foo");
// outputs "true" to console if el contains "foo", "false" if not
console.log( el.classList.contains("foo") );
// add multiple classes to el
el.classList.add( "foo", "bar" );

How do I get a jQuery function to work with specific elements when they have the same class names?

I have sections (divs) with text in it, but when the text is too long I made it so the text "fades" (with css) and displays a "show more" button, which shows the full text for that specific div when clicked. The problem is that it only works for the first div, and I believe it's because they all have the same class and id name. What's the best way to get around that? Here's my code:
HTML:
<div id="fade-container">
<div id="fade-content">
<p>
Long text goes here...
<div class="fade-anchor"><span class="btn-primary round-xl small btn-shadow">Show more</span></div>
</p>
</div>
</div>
Script:
<script>
$('.fade-anchor').click(function(e){
e.preventDefault();
$('#fade-content').css('max-height','none');
$('.fade-anchor').remove();
});
</script>
By the way, info is being fetched from the database in a php while loop.
When the user clicks on .fade-anchor you can use thisto get the element currently selected, you should also use classes instead of ids for multiple elements, like so:
$('.fade-anchor').click(function(e){
e.preventDefault();
$(this).parent('.fade-content').css('max-height','none');
$(this).hide(); // Maybe you should hide instead of removing, in case you want to add a toggle effect later on.
});
You can also check out this jsFiddle with the working version.
Hope it helps.
You can achieve it by e.currentTarget
$('.fade-anchor').click(function(e){
e.preventDefault();
$(e.currentTarget).css('max-height','none');
$('.fade-anchor').remove();});

Target the next element relative to another

basically, and in a very schematic way, I need to target the first element who has a specific attribute relative to the element who got the event.
<div data-path="2" class="section">
... Nope.
</div>
<div data-path="1" class="section">
<a data-path="2" class="trigger" href="#">Foo</a>
</div>
<div data-path="1" class="section--2">
... Nope.
</div>
<div data-path="2" class="section--3">
I need to target this one, but not the sections previous to the trigger.
</div>
<div data-path="2" class="section--4">
... Nope.
</div>
I can't figure how to achieve this. It seems to be pretty simple but I'm just stuck on this since two days. I try to play with .next() and .nextUntil() but it doesn't work properly.
Any help are welcome and sorry for my english.
Edit : To be clear, what I need is when a click on the .trigger, I need to target the first next section who has the same data-path attribute, but not the sections before the trigger.
You may want to use the nextAll to get to the next element which has the same property value and then use the first one out of that:
Demo: http://jsfiddle.net/mUt9H/1/
Relevant Code:
$("a").on("click", function() {
var dp = $(this).data("path");
var txt = $(this).parent().nextAll("div[data-path='" + dp + "']").first().text();
alert(txt);
});
Your trigger is an anchor, so first you need to get to its parent div and then traverse to the next elements. Hence, $(this).parent()....
Edit: (regarding your comment)
Just chain a .first() to the statement and you are good to go.
.nextAll("div[data-path='" + dp + "']").first()...
Try:
$('a.trigger').click(function () {
var target = $(this).parent().nextAll('div[data-path="'+$(this).data('path')+'"]').first();
})
jsFiddle example

Categories

Resources