Jquery click - thinks its the parent element, not the child - javascript

When I click on a child element inside a div (the 'butMedWhite ' class) - the jquery thinks that I am clicking on the parent element ('.alternative') - even when I dump 'this' inside the console it says i have clicked on the class 'alternative' (see code below) - not the 'butMedWhite ' class - does anyone have any ideas why?
Here is the html:
<div class="alternative _activeCategory">
<div class="alternative_inner"></div>
<div class="expandable" style="display: block;">
<div class=" criteriaContainer">
<a class="butMedWhite altCreator">add rule</a>
</div>
</div>
</div>
and here is the jquery:
$('.altExpander').on('click', '.alternative', function(e) {
console.log(this);
if(!$(this).hasClass('_activeCategory')){
expandCategory($(this));
}else{
closeCategory();
}
});
Thanks for any help!

jQuery provides as context to your callback the element on which you bound the event handler, just like the native DOM functions.
If you want the clicked element instead, don't use this but e.target :
$('.altExpander').on('click', '.alternative', function(e) {
var clicked = $(e.target);
console.log(clicked);
if(!clicked.hasClass('_activeCategory')){
expandCategory(clicked);
}else{
closeCategory();
}
});

That's because your selector is ".alternative" in this line:
$('.altExpander').on('click', '.alternative', function(e)
If you want this to be the anchor tag, you need to use
$('.altExpander').on('click', '.alternative a', function(e)

Related

jQuery display property not changing but other properties are

I'm trying to make a text editable on clicking it. Below is the code I'm trying. When the title is clicked it shows an input box and button to save it.
<div class="block">
<div class="title">Title</div>
<div class="title-edit">
<input type="text" name="title" value="Title">
<button>Save</button>
</div>
</div>
I have changed other properties like color or changing the text of the elements and its working, but it is not applying the display property or .show()/.hide() function on the title or edit elements.
Below is my jQuery
$(function(){
$('.block').on('click', editTitle);
$('.title-edit button').on('click', saveTitle);
});
function saveTitle(){
var parent = $(this).closest('.block');
var title = $('.title', parent);
var edit = $('.title-edit', parent);
$(title).show();
$(edit).hide();
}
function editTitle(){
$('.title-edit', this).show();
$('.title', this).hide();
}
Here's the jsfiddle
https://jsfiddle.net/ywezpag7/
I've added
$(title).html('abcd');
to the end to show that other properties/functions are working, but just not the display.
For checking the html change on title element you will have to check the source through developer tools cause the title element is hidden.
Where am I going wrong?
Your problem is in the function saveTitle. The first line must stop the event propagation otherwise after this function the editTitle function is called.
The snippet:
$(function(){
$('.block').on('click', editTitle);
$('.title-edit button').on('click', saveTitle);
});
function saveTitle(e){
// this line
e.stopPropagation();
var parent = $(this).closest('.block');
var title = $('.title', parent);
var edit = $('.title-edit', parent);
title.show();
edit.hide();
title.text($('.title-edit input').val());
}
function editTitle(e){
$('.title-edit', this).show();
$('.title', this).hide();
}
.title-edit{
display:none
}
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<div class="block">
<div class="title">Title</div>
<div class="title-edit">
<input type="text" name="title" value="Title">
<button>Save</button>
</div>
</div>
The issue as mentioned already is that your click events are fighting. In your code, the title-edit class is within the block, so when you click on the save button it triggers events for both clicks.
The easiest and, imho, cleanest way to resolve this is to switch your click event to be called on .title, and .title-edit button. You can also simplify the code beyond what you've got there.
$(function(){
$('.title').click(editTitle);
$('.title-edit button').click(saveTitle);
});
function saveTitle(){
$('.title').show();
$('.title-edit').hide();
$(title).html('abcd');
}
function editTitle(){
$('.title-edit').show();
$('.title').hide();
}
https://jsfiddle.net/ywezpag7/7/
I tried debug your code, and I had seen, that then you click to "Save" button, handled both functions, saveTitle() and editTitle(), and in that order. Therefore, the elements initially hidden, and then shown.

Not able to track change in input value

In the template I have a input element.
<input class='qq-edit-caption-selector qq-edit-caption kk-editing' placeholder='Enter Caption here ...' onkeypress='captionUpdate();'>
I want to track the change in the input value,and enable the Update button.Tried below options:
onkeypress='captionUpdate();'
Tried jquery change or click on the class
$('.qq-edit-caption').change(function() {
alert('qq-edit-caption');
});
Both options does not get fired up!!not sure I have anything issues with my setup or Fine Uploader does not allow that? Please see my screenshot:
Any way to solve this problem with FU?
If you are simply adding this inline event handler directly to the template element, then it's not surprising that it's never triggered. Fine Uploader templates are quite primitive in that the template is interpreted as an HTML string and then used to create DOM elements inside of your container element (the element referenced as your element option).
You really should never use inline event handlers. There are quite a few disadvantages to this approach. I talk about this in more depth in my book - Beyond jQuery. And the method of attaching event handlers is not necessary at all in your case, as far as I can tell. Instead, after constructing a new instance of Fine Uploader, simply attach an event handler of your choice to the input element using addEventListener. For example if your <input> element is given a CSS class name of 'qq-edit-caption', you can attach a "change" event handler like this:
var uploadContainer = document.querySelector('#my-uploader')
var uploader = new qq.FineUploader({
element: uploadContainer
...
})
uploadContainer.querySelector('.qq-edit-caption')
.addEventListener('change', function(event) {
// event handler logic here...
})
...and if you are creating this input element for each file and need to attach a "change" handler to all of these input elements, you should attach a single delegated event handler to the container element, and react based on the element that initially triggered the event (look at the target property of the event). You can determine the ID of the file by looking at the CSS class of the parent <li> of the event.target, or you can look for a 'qq-file-id' attribute on the parent <li> of the target element (the value will be the file ID). That code might look something like this:
var uploadContainer = document.querySelector('#my-uploader')
var uploader = new qq.FineUploader({
element: uploadContainer
...
})
uploadContainer.addEventListener('change', function(event) {
if (event.target.className.indexOf('qq-edit-caption') >= 0) {
var fileId = parseInt(event.target.getAttribute('qq-file-id'))
// ...
}
})
This might get you started:
$('.inp input').keyup(function(){
if (this.value.length > 0) {
$(this).closest('.row').find('.cell.btn button.upload').prop('disabled', false);
}else{
$(this).closest('.row').find('.cell.btn button.upload').prop('disabled', true);
}
});
* {position:relative;box-sizing:border-box;}
.row{overflow:hidden;}
.cell{float:left;height:40px;}
.pic{width:82px;}
.inp{width:230px;}
.inp input{font-size:1rem;padding:2px 5px;}
.btn{width:60px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="row">
<div class="cell pic">
<img src="http://lorempixel.com/80/40">
</div>
<div class="cell inp">
<input class='qq-edit-caption-selector qq-edit-caption kk-editing' placeholder='Enter Caption...'>
</div>
<div class="cell btn">
<button class="upload" disabled>Upload</button>
</div>
<div class="cell btn">
<button class="del" disabled>Delete</button>
</div>
</div><!-- .row -->
You can enable and disable the state of button by the input value.Using the Keyup function
$('.qq-edit-caption').keyup(function() {
if(this.value.length > 0){
$("#edit").prop('disabled', false);
}
else {
$("#edit").prop('disabled', true);
}
});
Have you tried the onchange event? Does it work?
<input class='qq-edit-caption-selector qq-edit-caption kk-editing' placeholder='Enter Caption here ...' onchange='captionUpdate();'>

How do I add an event listener to all the childnodes of a div in and array of those div?

I'm teaching myself JS and trying to avoid jQuery until my JS skills are better.
Goal: add an eventlistener, for click event, to all the divs of a certain class. Have all the child nodes of that class respond to the event.
My HTML
<div class="grid-panel six columns">
<div class="grid-panel-image">
<i class="fa fa-css3"></i>
</div>
<div class="grid-panel-title">
<h4>css3</h4>
</div>
</div>
<div class="grid-panel six columns">
<div class="grid-panel-image">
<i class="fa fa-paint-brush"></i>
</div>
<div class="grid-panel-title">
<h4>tamberator</h4>
</div>
</div>
I select all the .grid-panel divs using this JS
var gridPanels = document.querySelectorAll('.grid-panel');
then, since that returns an array of divs with the class .grid-panel
I add the event listener for click as such
for(i=0; i<gridPanels.length; i++){
gridPanels[i].addEventListener('click', myFunction);
}
my function is this
myFunction(){
var e = event.target;
switch(e){
case gridPanels[0]:
modalArray[0].setAttribute("data-modal-display", "show");
break
case gridPanels[1]:
modalArray[1].setAttribute("data-modal-display", "show");
break
}
console.log(e);
}
This does work if I click a very specific part of the .grid-paneldiv and the e logs that specific element. However, clicking any children of the div logs the e as the element i clicked, but the eventlistener is not applied to that element. I'm clearly missing something here with this event delegation. I really want the function to fire on the div clicked and all of its childnodes.
You're binding correctly, but if you want to get the element to which the handler is bound in the handler, then use this or event.currentTarget instead of event.target.
The event.target represents the actual element that was clicked, which is sometimes useful as well.
Also, you should define the event parameter in the function. Not all browsers have it available as a global variable.
function myFunction(event){
var e = this
// var e = event.currentTarget // same as above
switch(e){
case gridPanels[0]:
modalArray[0].setAttribute("data-modal-display", "show");
break
case gridPanels[1]:
modalArray[1].setAttribute("data-modal-display", "show");
break
}
console.log(e);
}

remove onclick when attached to children

I have the following code:
layoutOverlaysBldg = $("#layout-overlays-bldg")
layoutOverlaysBldg.on("click", "div", function(event) {
var floor;
console.log("floornum: " + this.dataset.floornum);
floor = parseInt(this.dataset.floornum);
...
$("#choose-floor").fadeOut();
$("#choose-apt").fadeIn();
});
later - based on data I'm getting back from the DB - I want to remove some of the .on("click", "div", ...) from only some of the divs. I already have the selector that is getting the right divs but I cannot figure out how to remove the click event. I have tried .off("click") after selecting the right div but it has no effect.
This issue here is because you are using a delegated event. You can add or remove the event for all child elements, but not individual ones given your div selector.
With that in mind the easiest way to do what you need is to add the event based on a class, then add and remove that class on the children as needed. Something like this:
layoutOverlaysBldg = $("#layout-overlays-bldg")
layoutOverlaysBldg.on("click", "div.clickable", function(event) {
// your code...
});
You can then enable/disable the event on the child div by adding or removing the .clickable class.
You can try like this :
Example :
<div id="test">
<div id="first">first</div>
<div id="second">second</div>
</div>
<div onclick="unbindSecondDiv();">UNBIND</div>
<script>
function unbindSecondDiv()
{
test = $("#second")
test.unbind("click");
alert('Selected Area Click is Unbind');
}
$(document).ready(function(){
//BIND SELECTED DIV CLICK EVENT
test = $("#test > div")
test.bind("click" , function(event) {
alert($(this).attr('id'));
});
});
</script>
In the above example , selected DIV elements click event is bind.
And after execute function unbindSecondDiv() , second DIV click event will be unbind.
Have a try , may helps you.

$(*).click event click it and all of its parent.

This is my code:
<p>
<div>
<div><span>Hello</span></div>
<span>Hello Again</span>
</div>
<div>
<span>And Hello Again</span>
</div>
</p>
<b>Click Hellos to toggle their parents.</b>
<script>
function showParents() {
$("div").css("border-color", "white");
var len = $("span.selected")
.parents("div")
.css("border", "2px red solid")
.length;
$("b").text("Unique div parents: " + len);
}
$("*").click(function () {
$("b").text($(this).parents().length);
});
</script>
The problem is when I click on a span, this shows 0 instead of 3!
I think the problem is *
Now the question is, how do I get the parent count when I don't know the type of the element?
The problem is event propagation(bubbling). The click event gets propagated to the root of the document from the clicked element triggering each of the click handler associated with those ancestor elements, so when the html element's click handler is triggered there is no more parents so you gets 0 as the result.
Demo: Fiddle - take a look at the console
Instead you can bind the click handler only to the document object then use the event's target property to find the element which triggered the click and find its parents
$(document).click(function (e) {
$("b").text($(e.target).parents().length);
});
Demo: Fiddle

Categories

Resources