Does jquery ui button call affect the DOM hierarchy - javascript

I am using jquery to expand/hide a piece of content. I then changed it such that the link used to expand/hide the content is a button and that broke it. Here is the code working before I changed to a button:
<body>
<div class="content">
<a class="toggle" href="">Expand box 1</a>
<div class="contentHidden" style="display:none;">Hidden 1</div>
</div>
<div class="content">
<a class="toggle" href="">Expand box 2</a>
<div class="contentHidden" style="display:none;">Hidden 2</div>
</div>
</body>
<script type='text/javascript'>
$(function() {
$(".toggle").click(function(event) {
$(event.target).parent(".content").find(".contentHidden").toggle('slow');
event.preventDefault()
});
});
</script>
However if I change the function to the following it no longer works:
$(function() {
$(".toggle").button({ icons: { primary: 'ui-icon ui-icon-arrowthick-1-e'} });
$(".toggle").click(function(event) {
$(event.target).parent(".content").find(".contentHidden").toggle('slow');
event.preventDefault()
});
});
Its as if the call to button() changes the hierarchy and my search no longer returns the '.contentHidden' div
Regards
Des

Yes, JQuery UI button() creates a new hierarchy below the original link (adds a couple of spans). One of these spans is the new clickable item, so it goes wrong for this reason alone (the clicked element is one level deeper than before), so use closest instead of parent:
$(".toggle").button({
icons: {
primary: 'ui-icon ui-icon-arrowthick-1-e'
}
});
$(document).on('click', '.toggle', function (event) {
$(event.target).closest(".content").find(".contentHidden").toggle('slow');
event.preventDefault()
});
Working JSFiddle here: http://jsfiddle.net/HxKLy/
The other issue, of using click instead of say a deferred on is actually a red herring in this instance, but I will retain below for reference.
Binding to specific DOM elements with click, means that as soon as you change the DOM that click event has been detached. Generally you will want to use the deferred calling syntax of on instead of a click, but in this case it makes no odds.
e.g.
$(document).on('click', '.toggle', function(event)...
instead of
$(".toggle").click(function(event)
Just to prove it was not the actual issue, here is a variation of the fiddle with the click back:
http://jsfiddle.net/HxKLy/1/

Related

Show/HIde Elements on click of parent/child

I am having issues with my click events due to nested elements and the nature of what I am trying to accomplish.
When I click on the .main, the selected class is added. However when I click on .close, the selected class is removed and then added back again. Is there anyway to get around this?
The reason why I have it setup this way is because I want to maximize my clickable area (the entire element).
$('.main').off('click.a').on('click.a', function() {
$('.child2', $(this)).addClass('selected');
});
$('.close').off('click.B').on('click.B', function() {
$(this).parent().removeClass('selected')
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<div class="main">
<div>some content</div>
<div class="child2">
<span class="close">X</span>
</div>
</div>
The issue is because the .close element is a child of the .main. This means that the event fires on .close, and the class is removed. The event then propagates up the DOM to the .main element where it's caught by the other event handler and the class gets added on again.
To prevent the event from propagating up the DOM, call stopPropagation() on it from within the .close click handler:
$('.main').off('click.a').on('click.a', function() {
$(this).find('.child2').addClass('selected');
});
$('.close').off('click.B').on('click.B', function(e) {
e.stopPropagation();
$(this).parent().removeClass('selected')
});
.selected { color: #C00; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<div class="main">
<div>some content</div>
<div class="child2">
<span class="close">X</span>
</div>
</div>
As a side note, using .off('event').on('event', fn) is a code smell. You may be better off using a single delegated event handler which you can bind only once when the page loads. It would depend on your exact use case, though.
You could double check it's actually the correct item.
$('.main').off('click.a').on('click.a', function(e) {
if (!$(e.target).hasClass('.main')){ return };
$('.child2', $(this)).addClass('selected');
});
$('.close').off('click.B').on('click.B', function(e) {
if (!$(e.target).hasClass('.close')){ return };
$(this).parent().removeClass('selected')
});
I've had similar issues when I wanted an event to go off when I click the whitespace in Table Cells but not the contents itself.. if that makes any sense

jQuery, click an element inside its clickable container - how to override

I have a list o elements li that becomes my image carousel. Each element is a thumbnail, and it becomes clickable using jQuery because i needed to put the image as li background-image. This I can not change. When thumb click, it calls a lightbox to show the image passed as bg parameter.
<ul id="piclist">
<li class="box" style="background-image: url('url_1');"><i class="seq" id="1"></i></li>
<li class="box" style="background-image: url('url_2');"></li>
<li class="box" style="background-image: url('url_3');"><i class="seq" id="2"></i></li>
<li class="box" style="background-image: url('url_4');"></li>
</lu>
The piece of my jQuery code to do this is:
<script type="text/javascript">
$('.box').click(function() {
return $(this).ekkoLightbox();
});
</script>
IT WORKS! But in some special cases, the thumbnail must show a kind of button, so I used a positioned <i></i> because of the Font Awesome im using in the project.
The image bellow can illustrate what im talking about:
THE PROBLEM IS:
When the li loads an i element, it also must be clickable, and its link must override his parents link - the container.
I did a piece of code in jQuery to do this, but always when I click on the i element button, the action loads the image lightbox from the li. Its wrong. It should do another action, for example, open an URL in new window, load another modal, whatelse.
<script type="text/javascript">
$('.box').click(function() {
return $(this).ekkoLightbox();
});
$('.seq').click(function() {
console.log($(this).attr("id")); //IT WORKS!
*do other action...* //Doesn´t work, open the <li> lightbox!
});
</script>
Any Help? :)
Change the $('.seq') click to this:
$('.seq').click(function(ev) {
ev.stopPropagation();
console.log($(this).attr("id")); //IT WORKS!
*do other action...* //Doesn´t work, open the <li> lightbox!
});
This will prevent the click event from bubbling up an triggering the click even of the i's parent (the li). Notice I added the event object as an argument and I'm calling the stopPropagation (http://api.jquery.com/event.stoppropagation/) method before doing anything else.
Check if e.target is identical to this:
<script type="text/javascript">
$('.box').click(function(e) {
if( e.target !== this ) return;
return $(this).ekkoLightbox();
});
$('.seq').click(function() {
console.log($(this).attr("id")); //IT WORKS!
*do other action...*
});
</script>

jQuery - Select an element by ID not working

I'm trying to select an element and then add / remove a class. I have achieved this plenty of times with other elements, however for this one it doesn't want to work.
My html is as follows:
<div>
<a class="login-headerText" id="hypLogin" style="padding-right:5px; float:left" >Login</a>
<h4 class="login-headerText" style="font-weight:bold; padding-right:5px; float:left">/</h4>
<a class="login-headerText" id="hypCreateAccount">Create Account</a>
</div>
The div is wrapped inside another div. (id=modal)
I want to select "hypLogin" then add a class to it on click. It works if i do this in the onClick event, however it wont work in a seperate script. (The script is referenced and works as it is used for other elements)
This is my jQuery
$('#hypLogin').click(function () {
$(this).removeClass('login-headerText').addClass('login-headerText-Unselected');
});
Tried debugging it and it's not getting hit at all.
Probably something really simple.
Couple of things:
you must do it on:
$( document ).ready(function() {
});
Does these elements printed dynamically?
try to use:
$('#hypLogin').on('click', function () {
});
try to put your code on modal open event.
Here is working fiddle
try this:
$(document).ready(function () {
$('#hypLogin').click(function () {
$(this).removeClass('login-headerText').addClass('login-headerText-Unselected');
});
});

Trouble with Javascript show when element is outside of the trigger

I am trying to show a div on click on an anchor, the issue is the anchor is inside an element and the div that needs to be shown is outside of this element. There are multiple divs of the same class on the page so I only want to show the associated one.
The markup is:
<div class="wrapper">
<div class="trigger">
Change
</div>
<div class="content">
<p>Content to be shown when Change is clicked</p>
</div>
</div>
Is that what you want to do? (fiddle)
// dom ready
$(function() {
$('a.change').on('click', function() {
// wrapper div
$(this).parent()
.next() // .content div
.show();
return false; // prevent the link to be followed
});
});
With jQuery you can do it like this:
$('a.change').click(function(e) {
e.preventDefault();
$(this).parent().next().toggle();
});
jsFiddle example
is this what you mean?
$(".content").hide();
$("a.change").click(function(){
$(".content",$(this).closest(".wrapper")).show();
});
Live demo :​
http://jsfiddle.net/dfkge/
Got to the parent and get the correct div e.g.
$('a.change').click(function(event){
event.preventDefault();
$(this).parents('.wrapper').children('.content').show()
}
This way you don't have to worry how deeply embedded anchor is, or where is content (before, after) in relation to anchor
Added a jsFiddle, showing divs with different structures, working with same code
http://jsfiddle.net/NWqcq/11/

How can I make entire DIV clickable AND open child links in separate DIV?

I asked a precursor to this question here:
Click link in DIV and show PHP/HTML in separate DIV
Then, after I removed the first script shown below, I was able to get the second script to work. I revised my question, but it appears to have gone silent. So I have a slightly modified question.
What is the conflict between the 2 scripts below and how can I modify them to work in tandem? Basically I want to be able to click anywhere in the DIV (".side_items") and have the child anchor links open in a separate DIV ("#main_content")
Javascript:
<script type="text/javascript">
$(document).ready(function(){
$(".side_items").click(function(){
window.location=$(this).find("a").attr("href");
return false;
})
});
</script>
<script type="text/javascript">
$(document).ready(function(){
$(".side_items a").click(function(e){
e.preventDefault();
$("#main_content").load($(this).attr("href"));
});
});
</script>
HTML: (slightly simplified)
<div id="main_content">
</div>
<div id="right_side">
<div class="side_items">
<a href="content.html">
<img src="images/examplethumb.png" /><br />
Content</a>
</div>
</div>
Both scripts work independently to achieve their individual desired result.
This will do it:
$(document).ready(function(){
$(".side_items").click(function(){
$("#main_content").load($(this).find("a").attr("href"));
return false;
})
});
Breaking it down:
$(".side_items").click(fn);
Find all the elements with a class of side_items and assign a click event handler (fn) to them. Each time one of these elements is clicked, fn is executed with the context of the element. In the discarded code you were using the selector .side_items a, which meant the click handler was only bound to the links inside the div, not the div itself.
$(this).find("a").attr("href")
Find all the links that are contained within the current element (this), and get the value of the href attribute from the first element found. In the discarded code the context (this) was a link. Since our handler is now bound to the containing div, the context is also the div. To get the link you have to find it.
$("#main_content").load(href);
Find the element with an id of main_content and load the content found at href into it. In the discarded code you were setting location.href, which causes the page to navigate away.
I think your issue is that you're trying to assign the $().ready(..) handler twice.
Try combing scripts like this
<script type="text/javascript">
var change_location = function(){
$(".side_items").click(function(){
window.location=$(this).find("a").attr("href");
return false;
});
}
var load_location = function(){
$(".side_items a").click(function(e){
e.preventDefault();
$("#main_content").load($(this).attr("href"));
});
}
$().ready(function(){
change_location();
load_function();
});
</script>
Hope that helps

Categories