Angular Stopping event propagation - javascript

This is an extension of my previous post here. I got everything working but I have 1 issue. When I start the intro the dropdown opens up exactly like I want, however when I click on the buttons inside the intro window (next, previous) then the dropdown closes. If I navigate the intro using my arrow keys it stays open. So how do I get the dropdown to stay open even if I'm using the intro window buttons to navigate the intro.
Here's the js portion for reference:
MainCtrl.prototype.startHelp = function() {
var _this = this;
_this.$timeout(function () {
angular.element('#drop-down').click();
}, 0, false);
_this.CallMe();
};

well you can try adding following to those buttons click event handler functions:
function onClickedNext(event) {
...
event.preventDefault();
event.stopPropagation();
}

This may be too late. But I achieved this by modifying intro.js code. Just stop the click event propagation inside "nextTooltipButton" defined in intro.js file.
Change the onclick listner function from this :
//next button
var nextTooltipButton = document.createElement('a');
nextTooltipButton.onclick = function() {
if (self._introItems.length - 1 != self._currentStep) {
_nextStep.call(self);
}
};
to :
//next button
var nextTooltipButton = document.createElement('a');
nextTooltipButton.onclick = function() {
if (self._introItems.length - 1 != self._currentStep) {
_nextStep.call(self);
var e = window.event;
e.stopPropagation();
}
};
Works for me on Chrome browser version 56.0.2924.87. As of today this code snippet is here.
We need no other changes in angular side.

Related

How do I trigger a click event on a disabled button element (using pure vanilla JS)?

I have this event: this.show.onclick = this.sendData.bind(this);
in my bindEvents() function:
bindEvents: function() {
var that = this;
// On click "Show" BTN
this.show.onclick = this.sendData.bind(this);
// On Change inputs
this.$form.change(function(){
that.updateDatesInputs(this);
});
},
That runs this:
sendData: function(e) {
e.preventDefault();
let that = this;
console.log(this.show.disabled);
if (this.show.disabled) {
alert('a disabled button has just been clicked!');
this.showErrorDiv("Please select a new date range.");
} else {
$.ajax({
....
}
});
that.dataDisplayed = true;
}
Clicking on my "show" button-element doesn't activate any click event. All I found googling this is that jQuery can fix it, but I want to use vanilla JS.
How can I trigger an event on a disabled element so that my alert will get executed using only pure JS?
It cannot be done, nor should it for accessibility reasons. Someone who navigates with a keyboard can never get to the button to interact with it.

Javascript function interacts with other function

I am completely new to javascript (and jquery) and have been experimenting with drop down menus the past couple of days. I found this one fancy notification menu, and I tried to see what happens when I have two of them on the page. Anyways, I made a quick example of my problem here:
http://jsfiddle.net/rgt03mu4/24/
The problem is that I can have both notification containers open up if I click on both.
If I am already clicked on one of the bells, then I click on the other, it should close the other one. Instead it keeps it open, and even when you click on the other container one, it still doesn't close it. You have to click off the page or click the notification bells. I am trying to make it to where you can only have one open at a time. So in order to do this, I tried changing the names of the functions:
As you can see:
$(function() {
var nContainer = $(".notification-popup-container");
//notification popup
$("#notification-link").click(function() {
nContainer.fadeToggle(300);
return false;
});
//page click to hide the popup
$(document).click(function() {
nContainer.hide();
});
//popup notification bubble on click
nContainer.click(function() {
return false;
});
});
I added the next function to be called test(), which you would think, since it's an entirely new function it would work differently. Instead, the error still persists.
What am I doing wrong? I even gave the the new bell it's own divs and link name. I also renamed container to container2.
Set the global variable for your container:
var nContainer = $(".notification-popup-container");
var nContainer2 = $(".notification2-popup-container");
$(function() {
var nContainer = $(".notification-popup-container");
//notification popup
$("#notification-link").click(function() {
nContainer.fadeToggle(300);
nContainer2.hide(); //hide the second container
return false;
});
//page click to hide the popup
$(document).click(function() {
nContainer.hide();
});
//popup notification bubble on click
nContainer.click(function() {
return false;
});
});
And you can do same with other function.
DEMO
There is no need to give the popup containers different classnames.
I would give the a-tags a common classname instead of an id. The href can be used to identify the target popup, so the binding between the link and the target popup is set in the origin of action. The JS part would be abstracted and could be reused.
<a class='notification-link' href='#firstpopup'>X</a>
<a class='notification-link' href='#secondpopup'>X</a>
<div class='notification-popup-container' id="firstpopup">
... firstpopup
</div>
<div class='notification-popup-container' id="secondpopup">
... secondpopup
</div>
The click handler first hides all the popups before opening a new one.
$(".notification-link").click(function () {
$(".notification-popup-container").hide();
var targetId = $(this).attr('href');
$(targetId).fadeIn(300);
return false;
})
working example: http://jsfiddle.net/qyLekdwk/
The problem here is how the event propgation is handled
$(function () {
var nContainer = $(".notification-popup-container");
//notification popup
$("#notification-link").click(function () {
nContainer.fadeToggle(300);
});
//page click to hide the popup
$(document).click(function (e) {
if (!$(e.target).closest('#notification-link, .notification-popup-container').length) {
nContainer.hide();
}
});
});
$(function test() {
var nContainer2 = $(".notification2-popup-container");
//notification popup
$("#notification2-link").click(function test() {
nContainer2.fadeToggle(300);
});
$(document).click(function (e) {
if (!$(e.target).closest('#notification2-link, .notification-popup-container').length) {
nContainer2.hide();
}
});
});
Demo: Fiddle

How to disable the click if a function is in active status

I have created a fiddle of my function here( http://jsfiddle.net/rhy5K/10/ ) . Now i want to disable the button click i.e play/pause if the sound is playing like Get ready,5,4,3,2,1 .
I know only how to disable the form submit button , but I am very confused how to disable the click in my case the hyperlinks.
Explanation using code example:
I want to disable this
PLAY
click, while interpreter is executing the below code:
var playGetReady = function (done) {
var ids = ['audiosource', 'a_5', 'a_4', 'a_3', 'a_2', 'a_1'],
playNext = function () {
var id = ids.shift();
document.getElementById(id).play();
if (ids.length) {
setTimeout(playNext, 1000);
} else {
done();
}
};
playNext();
};
Warning: This JS fiddle demo may play sound on load
You may try this (Changes in following function), but not sure if this is you want and maybe there are other ways to do it.
App.prototype.start = function () {
var self = this;
// unbind for a while
self.$button.unbind('click', self.buttonHandler); // <--
var start = function () {
// start countdown
self.intervalHandle = setInterval($.proxy(self.tick, self), 1000);
// bind again
self.$button.click($.proxy(self.buttonHandler, self)); // <--
// change button text to PAUSE
self.$button.text('PAUSE');
};
if (this.newTimer) {
playGetReady(start);
} else {
start();
}
};
DEMO.
In jquery, it can be done easily by cancel default action. Here's the sample.
$("#btn_start").click(function(event){
if(not_active_flag){
// Prevent anchor to active
return false;
}else{
// Anchor active as usual
return true;
}
});
In your case, the link will ultimately call this.buttonHandler, which has the following code:
App.prototype.buttonHandler = function (e) {
e.preventDefault(); // prevent anchor default action
this.toggle(); // toggle play/pause
};
Because buttonHandler is attached before playGetReady is executed, it is not possible to let playGetReady attach a click handler to that anchor element that uses .stopImmediatePropagation() to prevent the other click handler from executing.
In this case #gp.'s solution in the comments is most likely the best solution. In your case you might even be able to use a local variable in your app. If you use a global variable, reference it with window.yourglobalvariable. If you use a local variable, make sure you define it somewhere and reference it with this.yourvariable. Change your buttonHandler to:
App.prototype.buttonHandler = function (e) {
e.preventDefault(); // prevent anchor default action
if( this.soundready )
this.toggle(); // toggle play/pause
};
On the appropiate place make this variable false to prevent the 'button' from working. When the button should work, change the variable to true. I think that should be just before done() in the code you have in your question, but you probably have a better idea in what order the code is executed.

Hiding Bootstrap Popover on Click Outside Popover

I'm trying to hide the Bootstrap Popover when the user clicks anywhere outside the popover. (I'm really not sure why the creators of Bootstrap decided not to provide this functionality.)
I found the following code on the web but I really don't understand it.
// Hide popover on click anywhere on the document except itself
$(document).click(function(e) {
// Check for click on the popup itself
$('.popover').click(function() {
return false; // Do nothing
});
// Clicking on document other than popup then hide the popup
$('.pop').popover('hide');
});
The main thing I find confusing is the line $('.popover').click(function() { return false; });. Doesn't this line add an event handler for the click event? How does that prevent the call to popover('hide') that follows from hiding the popover?
And has anyone seen a better technique?
Note: I know variations of this question has been asked here before, but the answers to those questions involve code more complex than the code above. So my question is really about the code above
I made http://jsfiddle.net/BcczZ/2/, which hopefully answers your question
Example HTML
<div class="well>
<a class="btn" data-toggle="popover" data-content="content.">Popover</a>
<a class="btn btn-danger bad">Bad button</a>
</div>
JS
var $popover = $('[data-toggle=popover]').popover();
//first event handler for bad button
$('.bad').click(function () {
alert("clicked");
});
$(document).on("click", function (e) {
var $target = $(e.target),
var isPopover = $target.is('[data-toggle=popover]'),
inPopover = $target.closest('.popover').length > 0
//Does nothing, only prints on console and wastes memory. BAD CODE, REMOVE IT
$('.bad').click(function () {
console.log('clicked');
return false;
});
//hide only if clicked on button or inside popover
if (!isPopover && !inPopover) $popover.popover('hide');
});
As I mentioned in my comment, event handlers don't get overwritten, they just stack. Since there is already an event handler on the .bad button, it will be fired, along with any other event handler
Open your console in the jsfiddle, press 5 times somewhere on the page (not the popover button) and then click bad button you should see clicked printed the same amount of times you pressed
Hope it helps
P.S:
If you think about it, you already saw this happening, especially in jQuery.
Think of all the $(document).ready(...) that exist in a page using multiple jquery plugins. That line just registers an event handler on the document's ready event
I just did a more event based solution.
var $toggle = $('.your-popover-button');
$toggle.popover();
var hidePopover = function() {
$toggle.popover('hide');
};
$toggle.on('shown', function () {
var $popover = $toggle.next();
$popover.on('mousedown', function(e) {
e.stopPropagation();
});
$toggle.on('mousedown', function(e) {
e.stopPropagation();
});
$(document).on('mousedown',hidePopover);
});
$toggle.on('hidden', function () {
$(document).off('mousedown', hidePopover);
});
short answer
insert this to bootstrap min.js
when popout onblur will hide popover
when popout more than one, older popover will be hide
$count=0;$(document).click(function(evt){if($count==0){$count++;}else{$('[data-toggle="popover"]').popover('hide');$count=0;}});$('[data-toggle="popover"]').popover();$('[data-toggle="popover"]').on('click', function(e){$('[data-toggle="popover"]').not(this).popover('hide');$count=0;});
None of the above solutions worked 100% for me because I had to click twice on another, or the same, popover to open it again. I have written the solution from scratch to be simple and effective.
$('[data-toggle="popover"]').popover({
html:true,
trigger: "manual",
animation: false
});
$(document).on('click','body',function(e){
$('[data-toggle="popover"]').each(function () {
$(this).popover('hide');
});
if (e.target.hasAttribute('data-toggle') && e.target.getAttribute('data-toggle') === 'popover') {
e.preventDefault();
$(e.target).popover('show');
}
else if (e.target.parentElement.hasAttribute('data-toggle') && e.target.parentElement.getAttribute('data-toggle') === 'popover') {
e.preventDefault();
$(e.target.parentElement).popover('show');
}
});
My solution, works 100%, for Bootstrap v3
$('html').on('click', function(e) {
if(typeof $(e.target).data('original-title') !== 'undefined'){
$('[data-original-title]').not(e.target).popover('hide');
}
if($(e.target).parents().is('[data-original-title]')){
$('[data-original-title]').not($(e.target).closest('[data-original-title]')).popover('hide');
}
if (typeof $(e.target).data('original-title') == 'undefined' &&
!$(e.target).parents().is('.popover.in') && !$(e.target).parents().is('[data-original-title]')) {
$('[data-original-title]').popover('hide');
}
});

Prevent 'click' event from firing multiple times + issue with fading

Morning folks. Have an issue with a simple jQuery gallery i'm making. It lets the user cycle through a collection of images via some buttons and at the same time, rotates through these images on a timer. My problem is that the user is able to click the button multiple times which queues up the fade in animation and repeats it over and over, e.g. user clicks button 5 times > same image fades in/out 5 times > gallery moves to next image.
I've tried using:
$('#homeGalleryImage li a').unbind('click');
After the click event is fired and then rebinding:
$('#homeGalleryImage li a').bind('click');
After it's done but this simply removes the click event after pressing a button once and never rebinds to it?
I've also tried disabling the button via:
$('#homeGalleryImage li a').attr('disabled', true);
To no avail... ?
There is a secondary issue where if you manage to click a button while the image is in a transition, the next image appears 'faded' as if the opacity has been lowered? Very strange... Here is the code for button clicks:
var i = 1;
var timerVal = 3000;
$(function () {
$("#homeGalleryControls li a").click(function () {
var image = $(this).data('image');
$('#galleryImage').fadeOut(0, function () {
$('#galleryImage').attr("src", image);
});
$('#galleryImage').fadeIn('slow');
$('.galleryButton').attr("src", "/Content/Images/Design/btn_default.gif");
$(this).find('img').attr("src", "/Content/Images/Design/btn_checked.gif");
i = $(this).data('index') + 1;
if (i == 4) {
i = 0;
}
timerVal = 0;
});
});
Here is the code that cycles through the images on a timer:
//Cycle through gallery images on a timer
window.setInterval(swapImage, timerVal);
function swapImage() {
$('#galleryImage').fadeOut(0, function () {
var imgArray = ["/Content/Images/Design/gallery placeholder.jpg", "/Content/Images/Design/1.jpg", "/Content/Images/Design/2.jpg", "/Content/Images/Design/3.jpg"];
var image = imgArray[i];
i++;
if (i == 4) {
i = 0;
}
$('#galleryImage').attr("src", image);
$('#galleryImage').fadeIn('slow');
});
var currentButton = $('#homeGalleryControls li a img').get(i - 1);
$('.galleryButton').attr("src", "/Content/Images/Design/btn_default.gif");
$(currentButton).attr("src", "/Content/Images/Design/btn_checked.gif");
}
I realise it might be a better idea to use a plugin but I'm very new to jQuery and I'd like to learn something rather than using some ready made code.
Any help at all, is much appreciated.
Thankyou
You could always try adding something to the element to cancel the click event?
For example
$(".element").click(function(e) {
if ( $(this).hasClass("unclickable") ) {
e.preventDefault();
} else {
$(this).addClass("unclickable");
//Your code continues here
//Remember to remove the unclickable class when you want it to run again.
}
}):
In your case you could try adding a check on the click.
$('#homeGalleryImage li a').attr('data-disabled', "disabled");
Then inside your click event
if ( $(this).attr("data-disabled" == "disabled") {
e.preventDefault();
} else {
//Ready to go here
}
Edit
Here is a working example showing the element becoming unclickable. http://jsfiddle.net/FmyFS/2/
if you want to make sure that the registered event is fired only once, you should use jQuery's one :
.one( events [, data ], handler ) Returns: jQuery
Description: Attach a handler to an event for the elements. The handler is executed at most once per element per event type.
see examples:
using jQuery: https://codepen.io/loicjaouen/pen/RwweLVx
// add an even listener that will run only once
$("#click_here_button").one("click", once_callback);
using vanilly JS: https://codepen.io/loicjaouen/pen/gOOBXYq
// add a listener that run only once
button.addEventListener('click', once_callback, {capture: true, once: true});

Categories

Resources