Execute function in this same element - javascript

I'm new here, and in Jquery ...
I am using Wordpress to create a website and I have a Jquery function for opening cards, these cards have a plus button, and clicking that button opens a description of the card ...
So far so ok, but all the cards have the same classes (on the button, and the description) and pulling it on the page I need to use them by clicking on one of the buttons it opens all the descriptions of the other cards ... can i make it open only the card description of the button i clicked?
Code:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
$(this).ready(function(){
$(".abrir-btn").click(function(){
$(".conteudo-div").show(200);
$(".abrir-btn").hide();
$(".fechar-btn").show();
$(".listing-nucleados").css("background-color", "#FFE500");
$(".listing-nucleados").css("border-color", "#fff");
});
$(".fechar-btn").click(function(){
$(".conteudo-div").hide(200);
$(".abrir-btn").show();
$(".fechar-btn").hide();
$(".listing-nucleados").css("background-color", "#fff");
$(".listing-nucleados").css("border-color", "#EBEBEB");
});
});
</script>

Assuming, the buttons as well as the .listing-lucleados are both wrapped inside a parent element (let's call it .my-parent here). You can do the following:
$(this).ready(function(){
$(".abrir-btn").click(function(){
$(this).hide();
var parent = $(this).parents('.my-parent');
parent.find(".conteudo-div").show(200);
parent.find(".fechar-btn").show();
parent.find(".listing-nucleados").css("background-color", "#FFE500").css("border-color", "#fff");
});
$(".fechar-btn").click(function(){
$(this).hide();
var parent = $(this).parents('.my-parent');
parent.find(".conteudo-div").hide(200);
parent.find(".abrir-btn").show();
parent.find(".listing-nucleados").css("background-color", "#fff").css("border-color", "#EBEBEB");
});
});
Basically, what this does is going up the DOM tree to the parent element wrapping the show/hide buttons, as well as the list to show/hide. Then, from the parent element, find its descendants (I'm not saying direct children, because I do not know that much about your HTML structure) and apply the operation only to elements of this class inside the parent element.

In the function performed after clicking the button find a common ancestor of both elements - the button and the description - using closest().
Having an ancestor, find in it elements with the class .abrir-btn, .fechar-btn or .conteudo-div.
Example HTML:
<div class="content-outer">
<!-- the order inside is not important -->
<button class="abrir-btn" >show</button>
<button class="fechar-btn" >hide</button>
<div class="conteudo-div">...</div>
</div>
$(this).ready(function(){
$(".abrir-btn").click(function( event ){
var parent = $(event.target).closest(".content-outer");
if ( !parent.length )
return;
parent.find(".conteudo-div").show(200);
parent.find(".abrir-btn").hide();
parent.find(".fechar-btn").show();
parent.find(".listing-nucleados").css("background-color", "#FFE500").css("border-color", "#fff");
});
});

Related

Onclick event not works after "show" class added to parent div

I have two screens on the page. Every screen has 5 tables, there is only one table that can be seen. I want to change the visible table with these buttons. There are 2 buttons (previous, next) for each screen.
Here is my Javascript code to buttons:
document.querySelector('.screen.show .screen-table-buttons .next').onclick = function(){
...
}
This code works when the page is loaded the first time, but when added the show class to other screens, and I want to use it, it's not working. I want to use these buttons when the screen parent has a show class.
I changed the show class, added it to other screens, reloaded the page, and then other buttons worked on the other screen, but the first buttons didn't work.
So, I just want to use all buttons when the div parent has the show class. If the parent does not have the show class, don't work, If has it, just do it.
As mentioned in the comments this is a good case for event delegation - a single listener is attached to the document (or relevant ancestor) and functions are called based on target attributes.
Here it is attached to the document and it first checks if the clicked target has an ancestor with class screen.show using closest() if it does we check the classList of the target using classList.contains() to trigger the relevant function call.
function next_fn() {
console.log('next');
}
function previous_fn() {
console.log('previous');
}
document.addEventListener('click', (event) => {
if (event.target.closest('.screen.show')){
if (event.target.classList.contains('next')) {
next_fn();
}
if (event.target.classList.contains('previous')) {
previous_fn();
}
}
});
<div class='screen'>
<h6>Screen no-show (buttons won't trigger)</h6>
<button type='button' class='next'>Next</button>
<button type='button' class='previous'>Previous</button>
</div>
<div class='screen show'>
<h6>Screen show (only these buttons work)</h6>
<button type='button' class='next'>Next</button>
<button type='button' class='previous'>Previous</button>
</div>
<div class='not-screen'>
<h6>Not-screen (buttons won't trigger)</h6>
<button type='button' class='next'>Next</button>
<button type='button' class='previous'>Previous</button>
</div>
As Teemu said in the comment, the way you're binding the click event means that you're binding the click event to the button that is already visible (i.e. the one that has the show class at the moment the line you've put in the question is hit) - it isn't designed to cater for elements that may or may not exist at some point in the page lifecycle.
You'll either need to rebind the click event each time you switch the show class, or you can bind the event regardless of the show class.
In order to rebind the event each time, you'd be better off pulling the function out into its own area - something like this:
document.querySelector('.screen.show .screen-table-buttons .next').onclick = NextClicked
function NextClicked() {
... do the normal click event stuff, and move the show class to the other screen
document.querySelector('.screen.show .screen-table-buttons .next').onclick = NextClicked
}
Alternatively, you could bind the click event once and do a check to see whether the one clicked is the right one - something along these lines:
document.querySelector('.screen .screen-table-buttons .next').onclick = function(e){
if (e.target.parentElement.parentElement.hasClass('show')){
...
}
}

jquery show/hide not working for dynamically created div

I have a checkbox which will allow the users to show/hide certain features. So I have 2 divs with separate IDs and one div is added directly to my code and the second div is dynamically added through a plugin with the CSS display:none.
$(function() {
$("#chkstatus").click(function() {
if ($(this).is(":checked")) {
$("#dv").show();
$("#Add").hide(); //dynamic div
} else {
$("#dv").hide();
$("#Add").show(); //dynamic div
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="dv" class="forgo">
<h1>Benefits</h1>
<p></p>
</div>
<!-- The below code is not visible in the page source but visible in inspect element -->
<div id="Add" class="form-group" style="display:none">
<input class="btn-block button" type="button" style="" value="Upload File">
</div>
The problem is that the show/hide is working perfectly to the #dv but nothing happens to #Add. It always stays hidden.
Can someone let me know how can make the show/hide work for the dynamically added div?
Instead of binding the event listener to the dynamically created div you should add an eventlistener on the parent (say <div id='cont'></div> ) which is ofcourse static in nature .
Say the event we are listening to is click, now whenever you click the parent you have the reference to the specific div (even if there a lot of dynamic divs like this) as a target attribute of the event. which you can find by digging the output in console log.
Why and How ??
This is because of event delegation and event bubbling i.e. the event bubbles up to the parent div and keep on bubbling up to the body in DOM tree.
So for this case, as the event is click( checkbox ) which is on some different element (no parent child relation with dynamically added div) so we can use trigger to fire our own custom event on the parent div.
$(document).ready(function () {
$("#cont").on('myEvent1',function(){
$(this).find('#dv').show();
$(this).find('#Add').hide();
});
$("#cont").on('myEvent2',function(){
console.log($(this)); // This will o/p the #cont div containing both the static and dynamic div in it.
$(this).find('#dv').hide();
$(this).find('#Add').show();
});
$("#chk").change(function () {
if ($(this).is(":checked")) {
console.log($(this)); // This will o/p the checkbox element
$("#cont").trigger('myEvent1');
}
else {
$("#cont").trigger('myEvent2');
}
});
});
You can try to mold it for your exact purpose and can also use toggle to reduce the LOC.

jQuery does not recognize PHP generated child element when clicked

I am working on a website on which I have to display buttons based on database content. Clicking these buttons should then send a request to the database and reload the content of the page appropriately.
Everything is done with Ajax and jQuery by executing PHP scripts.
I can generate the buttons, but jQuery does not trigger when they are clicked.
It seems that jQuery detects a click on the div containing the buttons but not on the buttons themselves.
I was told that it may be because the jQuery script is loaded before the page is updated with the new HTML content.
This is the div container for all the choice buttons:
<div id = "choices">
<!-- Choices button will be displayed here -->
</div>
Here's the PHP code creating the HTML for the buttons:
echo " <button class = 'choice' id = \"$id\">
$content
</button> ";
This code is loaded in the previous #choices div by this jQuery code :
$.post("php_script/getChoices.php",
function(result){
$("#choices").html(result);
});
Pretty basic, and the expected (and actual) output on the webpage is :
<div id = "choices">
<button class = 'choice' id = "1">
Yes.
</button>
<button class = 'choice' id = "2">
No.
</button>
</div>
But when I write this :
$(".choice").click(function());
It never triggers, no matter how basic the function.
However, having another event to interact with the buttons is possible.
For example, the code below does hide the buttons when the #choices div is clicked.
$("#choices").click(function(){
$(".choice").hide();
});
In order to understand the problem, I wrote this jQuery script that print the content of the element that was clicked on the console.
$("*").on('click', function(event){
event.stopPropagation();
console.log('Clicked: ' + $(this).html());
});
And when I click on a button, it always returns the whole #choices div instead of just the content of the button.
As I said, I think this is because I am trying to interact with HTML elements that were added after the jQuery script was loaded (it is written in the section of my page).
Is my assumption correct and what should I do in order to trigger an action when the button themselves are clicked ?
You can always target the document to trigger dynamically created elements:
$(document).on('click', '.choice', function (e) {
e.preventDefault(); //stop default behaviour
var id = this.id; //get element ID
$(this).hide(); //hide element
});
As mentioned you can use event delegation
$(function(){
$("#choices").on("click", "button", function(){
alert("clicked");
});
});
Or manually bind the event handler when you add the new buttons
// called each time new buttons are added
function bindOnClick(){
$("#choices").off();
$("#choices").on("click", "button", function(){
alert("clicked");
});
}
$(function(){
// called once when dom is ready
bindOnClick();
});
If you don't call off you will bind the onclick event to the same element more than once.

How to get the inside div element child and handle event in extjs4

I want to select the div with class "icon-right" and add the click event.
Html code:
<div class="msg">
<div>
<div class="sample"></div>
</div>
<div>
<div class="icon-right"></div>
</div>
</div>
I want to select the div which has class icon-right and handle click event..
Extjs code:
var message = Ext.select('div:next(div.icon-right)');
message.on('click', function () {
alert('test msg');
}, message);
But i need to change the div with class icon-right as div with icon-left when on click and now when i click the icon-left it change to div with class icon-right.. vice versa happens
Can you do:
Ext.select('.icon-right').up('div').on('click', function() {});
As per the documentation, Ext.select returns a CompositeElement or a collection of DOM elements. You should be using Ext.query which will return an HTMLElement, which you can then define the onclick event handler:
var target = Ext.query(".icon-right").pop(); // return the first div of the query
target.onclick = function(){ alert('clicked!'); }
Alternatively, if you wish to utilize Ext event listeners, you must make use of the Ext.dom.Element class, an instance of which is returned by Ext.get, which calls for an ID, DOM Node or Existing Element as per the documentation. If you were to retrieve the element via Ext.get, you could then assign a listener via Ext.dom.Element.on as you have in the provided code.
Working jsFiddle: http://jsfiddle.net/LcRWB/ (shows both examples)
This should work.
var el = Ext.Element.select("[class=icon-right]");
el.on('click', function() {
alert("hi");
});
You can see an example on jsfiddle http://jsfiddle.net/XzKKZ/

How to get top most parent Id when I click on any one of its child element?

I have the following HTML code:
<div id='parentDiv'>
<div class='firstDiv'>
<div class='firstDivChild1'></div>
<div class='firstDivChild2'>
<div class='firstDivChild2_Child1'></div>
<div class='firstDivChild2_Child2'></div>
</div>
</div>
<div class='secondDiv'>
<div class='secondDivChild1'>
<div class='secondDivChild1_child'>
<div class='secondDivChild1_child_child'></div>
</div>
</div>
</div>
</div>
Now my requirement is when I click on any div I want to get an top most parent Id (i.e. parentDiv). Presently I'm using the below script to get parent Id:
<script type='text/javascript'>
$('div').click(function(e){
var parentDivId = (e.target).parentNode.id;
alert(parentDivId );
});
</script>
but it doesn't work. Can anyone correct this code to reach my requirement?
If that parent DIV is unique across document, then you just can refer to it by ID, i.e. $('#parentDiv'), but if it's not, then you should change your HTML and add to parentDiv some class (i.e. parentDiv), and you'll be able to refer to it by this expression $(this).parents('.parentDiv:first');
$('div').click(function() {
alert($(this).parents('div').last().attr('id'));
return false;
});​
Live DEMO
then use the natural power of event bubbling. any descendant clicked will bubble up the event upwards (hence bubble) and will act as if the parent is clicked. so adding a click handler to the parent also does the same thing.
$('#parentDiv').on('click',function(){
var id = this.id
});
Try this little function :
$.fn.root = function() {
var $all = $( this[0] ).parents();
// omit "html", "body" and one index to the last item;
return $all.slice( $all.length - 3, $all.length - 2 );
};
Sample Usage :
$('input').click(function() {
alert($(this).root().prop('id'));
});​
Simple working example using your HTML here
It is still not completely obvious what you're asking for, but based on a few of your comments, here's my best guess.
Using event bubbling, you can examine all clicks in your document and you then determine where the click originated with e.target and you can then figure out whether that click originated in your div tree or elsewhere:
$(document).click(function(e) {
// determine if click was in our div tree or not
if ($(event.target).closest("#parentDiv").length) {
// click was in our parentDiv tree
} else {
// click was not in our parentDiv tree
}
});
Regardless of where the click was located, you can get the top of your div tree id="parentDiv" at any time with this with this jQuery:
$("#parentDiv")
If, you just want the top-most div that is above what is clicked, no matter where the click is in the document, you can use event bubbling like this to get that:
$(document).click(function(e) {
e.stopPropagation();
var topMostDiv = $(e.target).parents("div").last();
// do whatever you want with topMostDiv here
});

Categories

Resources