Why is my button propagating event to its parent? - javascript

I've made a small trick in a div where I put my own "data" precising what to do if the user clicks on it.
My JavaScript code looks like (lot of code omitted for sake of clarity):
$('[data-hqf-switch]').click(function() {
var t = $(this).attr('data-hqf-switch').split('/'),
i = 0;
if (t % 2) {
alert('Burn the dev. Its the dev. himself who wrote that.');
return;
}
while (i < t.length) {
var ev = sw(t[i++], '$')+'.'+sw(t[i++], 'd')+';';
eval(ev);
}
});
Now in my HTML I have something like that:
<div class="col-lg-12" data-hqf-switch="$.pt().pv()/Xd/$.pt()/Xu">
<h4>25 mars 2016 22:07 - You wrote...</h4>
<p>J'ai refusé votre invitation</p>
<button type="button" class="btn btn-default"
data-toggle="modal"
data-target="#modal-msg-7-24" title="Répondre">
<i class="fa fa-envelope-o"></i> Répondre
</button>
<div class="modal fade" id="modal-msg-7-24" tabindex="-1"
role="dialog"
aria-labelledby="Envoyer un message" aria-hidden="true"
style="display: none;">
<div class="modal-dialog">
<div class="modal-content">
</div>
</div>
</div>
<button class="btn btn-warning"
data-hqf-switch="$.pt().pt().pv()/Xd/$.pt().pt()/Xu">
Fermer
</button>
</div>
The most important is the first button: when clicked it shows the modal dialog box which is declared just after the button.
Everything should work fine except that when you click on the button it's like you click on the button and on the "surrounding" div because the event of the div is launched too.
What am I missing?

Event propagation means the event is handled for the clicked element and all ancestors.
You may want to look into event.stopPropagation().
I believe your small trick will eventually make you regret the day you invented it if you're doing anything moderately complicated.

The solution is here. And it's not a duplicate, even though it's close to.
I just test if the element the user "has pushed" has actually the "switch data". If not, I return instantaneously because I suppose (and I dont imagine a case where it's not) that it's one of the children of this element, not the element itself.
$('[data-hqf-switch]').click(function(e) {
if ($(e.target).filter(':not([data-hqf-switch])').length) {
return;
}
/* ok the target contains a 'data-hqf-switch' attribute */
/* ... blabla ...*/
}

Related

Javascript cookie dismiss forever

I have modal pop-up that asks users if they would like to subscribe to my newsletter. If the user closes the modal I don't want it to appear again. Using my code below the pop-up is shown frequently multiple times a day. What would I need to add so that once dismissed the pop-up wouldn't appear again?
//custom.js
if (!readCookie("close_subcribeModal")) {
function subcribeModal() {
$("#subcribeModal").modal("show");
}
setTimeout(function () {
subcribeModal();
}, 5000);
}
Web page:
#if(!isset($_COOKIE['close_subcribeModal']) && #$_COOKIE['close_subcribeModal'] != "1")
<div id="subcribeModal" tabindex="-1" role="dialog" aria-labelledby="subcribeModalLabel" aria-hidden="true">
<div role="document">
<div class="modal-content">
<button type="button" id="subcribeModal__close" class="cancel" data-dismiss="modal" aria-label="Close"></button>
<div class="modal-body">
<h2 class="title">Welcome</h2>
<p>Would you like to receive our weekly newsletter?</p>
<x-mail.newsletter-subscription />
</div>
</div>
</div>
</div>
#endif
It looks like you are using Bootstrap, when the modal window gets hidden (or closed) the event hidden.bs.modal gets triggered.
So we create a cookie if the event occurs (add this on the bottom of your view)
$("#subcribeModal").on('hidden.bs.modal', function() {
Cookies.set('modalShowed','active');
});
Change if (!readCookie("close_subcribeModal")) to if(Cookies.get('modalShowed') != 'active')
and get rid of this if statement #if(!isset($_COOKIE['close_subcribeModal']) && #$_COOKIE['close_subcribeModal'] != "1") on your view.

Javascript/JQuery Callback confusion

I've a Modal which I show for confirmation:
<div class="modal" tabindex="-1" role="dialog" id="modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
... Body ...
<div class="modal-footer">
<button type="button" id="btnCancel" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" id="btnOk" class="btn btn-primary" data-dismiss="modal">Ok</button>
</div>
</div>
</div>
</div>
Here is the code for showing the above Modal..
var M = {
confirm: function(body, yes, no) {
$('#btnCancel').on('click', function() {
$('#btnCancel').off();
$('#confirm-modal').modal('hide');
if (no) {
return no();
}
});
$('#btnOk').on('click', function() {
$('#btnOk').off();
$('#modal').modal('hide');
if (yes) {
return yes();
}
});
}
}
And here is how I am using it... (In any view for example)
M.confirm("Body", function(){
// Function Body
})
Now, the problem is: If I call confirm, it shows the Modal. But if I click Cancel and than again call confirm and this time, I hit OK: the function (second param in the snippet above) is called twice. If I hit cancel 10 times, the function above is called 10 times.
Any idea why this is happening?
Thank You.
Every time you call confirm you add an event handler to each of btnCancel and btnOk.
However, you only remove the effect handler on one of those buttons when that button is clicked.
So if you call confirm, then click btnCancel, then call confirm you'll have two event handlers on btnOK: One from the first call to confirm and once from the second.
When either button is clicked you need to remove both event handlers.
… or just add the event handlers when the document is loaded and don't touch them thereafter.

jQuery append element duplicates itself

I have my alert box that appears on every CRUD operation.
<section class="content container-fluid">
<div id="notif-box" style="display: none;" class="alert alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4 id="head-title"><i id="icon-box" class="icon fa"></i></h4>
<span id="alert-message"></span>
</div>
</section>
I have problem with #head-title where I write headText.
In my methods on success I call:
displayNotif('danger', 'check', 'User added successfully', 'Success!');
and this fucntion:
function displayNotif(type, icon, text, alertTitle) {
$("#notif-box").removeClass();
$("#icon-box").removeClass();
$("#head-title").removeClass(alertTitle);
$("#notif-box").show();
var notifBoxClass = "alert alert-"+type+" alert-dismissible";
var iconClass = "icon fa fa-"+icon;
$("#notif-box").addClass(notifBoxClass);
$("#icon-box").addClass(iconClass);
// this is the issue
$("#head-title").append(alertTitle);
$("#alert-message").html(text);
setTimeout(function () {
$("#notif-box").fadeOut();
}, 5000);
}
When I hit first time add button, head title is 'Success!'
When hit second time head title is 'Succsss!Success'!
Third is ''Success!Success!Success!'
Other elements work as expected! Can not figure where the problem is!
Instead of appending again and again, simply replacing the text should solve the issue.
Change
$("#head-title").append(alertTitle);
To
$("#head-title").html(alertTitle);

Is it possible to update modal content via javascript? [resolved]

[Resolved - I had two modals defined with different Ids but when I disabled one, it worked as expected. Changed it so all content goes through one modal. At some point I may revisit to figure out where the conflict was.]
I have a mvc core page on which I have a modal that uses a partial view. In the modal, I'd like to present a summary list and let the user click an item in the list to view additional details on the modal. However, while the element is reporting it has been changed (via an alert check) it is not visibly updated. I then created a simple test to change the background color of a div to see if the approach itself is valid.
In this case the alerts identify that the color was changed, but again, it does not visually change. So the question is, how can I dynamically update text or CSS within a modal dialog using a js/jquery function? Is it even possible? I'm not interested in reloading the modal.
My test modal content (_TestContentModal):
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close" id="closeMe"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<div id="test">
background color test
</div>
<div>
<button onclick="UpdateDetails('yellow');">Change background to yellow</button>
</div>
</div>
<div class="modal-footer">
<button data-dismiss="modal" id="cancel" class="btn btn-default" type="button">Close</button>
</div>
</div>
<script>
function UpdateDetails(newColor) {
alert('Before change: ' + $('#test').css("background-color")); // Before change: rgba(0, 0, 0)
$('#test').css("background-color", newColor);
alert('After change: ' + $('#test').css("background-color")); // After change: rgba(255, 255, 0)
// clicking a second time confirms that the color was updated:
// Before change: rgba(255, 255, 0)
// After change: rgba(255, 255, 0)
}
</script>
Clicking the button properly triggers the function and the alerts show/confirm that the background color is being changed, however it is not visibly changed. A second button click confirms the new color was set.
I'm relatively new to modals and it is quite possible that I'm going about this entirely the wrong way. Thanks in advance for any advice or solution.
Edit:
Including some additional code in response to initial answer. Since the above code seems to function as intended elsewhere the problem must lie in the handling of the modal.
On parent page is the reference to the modal:
<partial name="_TestModal" />
This is the content of _TestModal.cs:
<!--Modal-->
<div aria-hidden="true" aria-labelledby="modal-test-label" role="dialog" tabindex="-1" id="modal-test" class="modal fade">
<div class="modal-dialog modal-lg">
</div>
</div>
A button on the parent page activates the modal:
<div>
<a class="btn btn-secondary popup"
style="color: black;"
data-url='#Url.Action("GetTest","Runways")'
data-toggle="modal"
data-target="#modal-test">
Update<i class="fa fa-plus"></i>
</a>
</div>
The GetTest action of the controller returns the partial that contains the modal content shown at the top:
return PartialView("_TestContentModal");
And finally, the parent page has this script to handle the modal:
(function ($) {
function Index() {
var $this = this;
function initialize() {
$(".popup").on('click', function (e) {
modelPopup(this);
});
function modelPopup(reff) {
var url = $(reff).data('url');
$.get(url).done(function (data) {
$('#modal-test').find(".modal-dialog").html(data);
$('#modal-test > .modal', data).modal("show");
});
}
}
$this.init = function () {
initialize();
};
}
$(function () {
var self = new Index();
self.init();
});
}(jQuery));
To be clear: the color is not visibly changing. There are no errors reported in the browser console so the alerts were added to see how the element was responding. Minus the alerts, Brando Zhang's answer demonstrates the expected behavior, but in my case it does not turn yellow, with or without the timer delay. And again, the alerts were only added as a debug aid.
Do you mean you want to show the test backgournd color to yellow before the alert After change?
If this is your requirement, I suggest you could try to use setTimeout to not fired the alert immediately.
More details, you could refer to below codes:
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close" id="closeMe"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<div id="test">
background color test
</div>
<div>
<button onclick="UpdateDetails('yellow');">Change background to yellow</button>
</div>
</div>
<div class="modal-footer">
<button data-dismiss="modal" id="cancel" class="btn btn-default" type="button">Close</button>
</div>
</div>
<script>
function UpdateDetails(newColor) {
alert('Before change: ' + $('#test').css("background-color")); // Before change: rgba(0, 0, 0)
$('#test').css("background-color", newColor);
setTimeout(function () { alert('After change: ' + $('#test').css("background-color")); }, 1)
// After change: rgba(255, 255, 0)
// clicking a second time confirms that the color was updated:
// Before change: rgba(255, 255, 0)
// After change: rgba(255, 255, 0)
}
</script>
Result:

How to define $var only if parents('.class').attr('id') exists?

Here is my code:
<div class="superBlock" id="blabla">
<a class="watch"><img src="images/blabla.png"/></a>
</br>
<div class="btn-group-xs" role="group">
<a type="button" class="btn btn-info info" data-toggle="modal" data-target="#myModal">Information</a>
</div>
</div>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-footer">
<a type="button" class="btn btn-success watch" data-dismiss="modal">Watch</a>
</div>
</div>
</div>
</div>
$('.info').click(function() {
var $watchID = $(this).parents('.superBlock').attr('id');
});
$('.watch').click(function() {
if($(this).parents('.superBlock').attr('id') != "") {
var $watchID = $(this).parents('.superBlock').attr('id');
}
alert($watchID);
});
What I'd like to do is to set the $watchID to the .superBlock's ID whether I click on the .watch button or on the .info button.
And I get $watchID is "undefined" when I click on the modal watch button after clicking on the info button.
And I'd like the $watchID to keep on being set to the .superBlock's ID if the $(this).parents('.superBlock').attr('id') is undefined. So the $watchID not to change to the undefined $(this).parents('.superBlock').attr('id').
What should I do? Is this only about syntax? If so, how should I change this?
This HTML divs are repeating with different IDs, that's why I can't just set the ID to "blabla".
To tell if a selector matches anything, check the length of the jQuery object.
var superblock = $(this).closest(".superBlock");
if (superblock.length > 0) {
$watchID = superblock.attr('id');
}
Also, if you want the $watchID variable to persist between calls, it should be declared outside the functions. Your variable is local to each function, so it gets discarded when the function returns.
And since you just want the closest parent with that class, use .closest() rather than .parents(), which searches the entire DOM hierarchy for multiple matches.

Categories