how to bind click trigger, only to clicked element? - javascript

I have some elements having fbutton class. How can I bind a click element only to clicked element. I have a code like this:
$('.fbutton').click(function() {
/*
Some Code 1
*/
$(this).next().click();
/*
Some Code 2
*/
enough;
});
$(this).next().click(); line triggers a click on an element, but also all other fbutton elements are triggered too (this part bothers me).
First solution that comes to mind is that end script processing after Some Code 2. As return; does not work, I used an illegal javascript code that results abnormal end of execution of code. It works, but it is not the correct way of ending execution. How can I end javascript execution or How can I trigger an event only for clicked element.
More Clarification
I want only clicked .fbutton to trigger. So does jquery identify clicked element? Also I can not define any class for any .fbutton element, because trigger should depend on user click.

Have you tried using stopPropagation?
$('.fbutton').on('click',function(e){
e.stopPropagation();
$(this).next().trigger('click');
});

onclick give it a class, and bind the click triggering to it.
$('.fbutton').on('click',function() {
// Code 1
$(this).hasClass('clicked')) ? $(this).next().trigger('click') : $(this).addClass('clicked');
// Code 2
});
Also, using jQuery vs $? I kept it consistent for you, but if you can use $ I recommend it.
EDIT
To clarify my answer:
This is a ternary if statement. It checks to see if the item clicked has a class of clicked, and if it does, then it assigns the click you want to $(this).next(), but if it doesn't have the class already it adds the class (without binding the click statement yet). When the element is clicked again, it will have class clicked, so it should fire then.
This allows you to only have the click event binded to elements that have already been clicked.
SECOND EDIT
Here is a jsFiddle to show it works.
Click example once and nothing will happen but adding the class, click it again and it will trigger the click of the next button, but not anything else. The same is true for the second button, so that you can see they are separate events for each pairing, unrelated to any other button pairs.

Related

Google Tags - Javascript variable value changing on every click

First time working with Google Tag Manager. I have a click event trigger based on a button class, yet it executes on every click.
My variable {{bookingUnit}} is gets its value from text taken off the HTML on the page. It is a Custom Javascript variable (and returns the correct value):
function() {
return $({{Click Element}}).closest('table')).find('td.rnc').text();
}
I have to detect a button click which on the page (of a 3rd party system) was defined as:
<input type="submit" name="ctl00$plcBody$BookingFormGrid$ctl16" value="BOOK NOW" onclick="$('form').attr('action', 'DetailsEntry.aspx?bfid=c5efdee5-7280-4593-8256-564e9b7ac01a&bfpid=8072faaa-c89f-4a63-be19-e54a91f0f1a0&bfrtid=3d6e96c3-e557-4f85-97d1-c750787dc6d8&arr=2019-03-07&nts=3&a=1&c=0');WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("ctl00$plcBody$BookingFormGrid$ctl16", "", true, "", "", false, false))" class="btn btn-primary bnow">
I have a trigger as follows:
Type: Click - All Elements
Fires On - Some Clicks
Click Classes - equals - btn btn-primary bnow
Click Element - equals - input
Wherever I click on the page I see the event firing:
gtm.click
Yet I can see the value of my variable being updated every time (so it seems to ignore my Click Classes trigger condition and only update when the button is pressed).
What did I miss? Thanks.
UPDATE: Using info from this forum, I changed my trigger like so:
Click Element - matches CSS selector - .btn .btn-primary .bnow
But still the variable gets updated by clicking anywhere on the page.
It sounds like you have a Click - All Elements trigger active in your container. This will fire with every mouse click. Every time a trigger is fired, all variables will be re-evaluated at that time. So the best thing to do is to deactivate the Click - All Elements trigger if you are not using it.
Edit:
Go to Variables > Configure Built-In Variables
Select the following: Click Element, Click Classes, Click ID, Click Target, Click URL, Click Text
Go to Triggers > New
Trigger Type: Click - All Elements
This trigger fires on Some Clicks
Click Classes matches CSS selector .btn.btn-primary.bnow
As bit more technical detail - GTM does not bind events to the element specified by the classes in your filter. Instead it binds the event to the document, waits for the event to bubble up to the root element of the page, and then inspects the event target if it matches your filters.
As vinoaj said the net effect is that the trigger is fired every time you click anywhere on the page. That also means that the Click Element changes everytime, and with it the return value for the selector in your custom variable.
However the actions connected to the trigger will only fire if the event target matches the conditions in your trigger. So this should actually not create a problem for you.
Do it like this:
Type: Click - All Elements
Fires On - Some Clicks
Click Classes - equals - btn
Just use one class and one condition. Also make sure that it's the only button with that class or that only the buttons you want to track have that class.
In the debug console you will always see the event gtm.click firing but the variable should only be sent when clicking the button with that particular condition.
The gtm.click event you are seeing is not your event firing - it is simply one of GTM's default events. If your tag had fired you would instead see your tag name in the preview.
It sounds like you want to send an event to GA every time your trigger fires along with the value of {{bookingUnit}}, if this is the case:
create a Google Analytics tag - set it to "events".
From here you could:
place the variable as the event action along with any other details
you would want to send.
Make sure you have created a variable for your Google Analytics ID to
link the event to your GA account.
Once this is done you can attach your CSS selector trigger to this tag (Click Element - matches CSS selector - .btn .btn-primary .bnow) this will then fire an event every time the matched selector is clicked to your GA account. You can check for the tag firing in preview mode, just look out for the name of your GA event tag.

Triggering button click in jQuery not working

Using dot.js I'm adding a button to a specific web page that, when clicked, should add some text to a text field and then trigger another button to also be clicked. I simulate this by adding a click handler to my button which has this code:
var button = $('.some-class').find('button')[0];
console.log(button); // element I expect
button.click();
However, this doesn't work and I'm not sure why. If instead of .click() I perform .remove(), the button is removed from the page. If I use the console to execute the same code, the button does get clicked. This tells me I do have the right element, but there is something wrong with the click() event specifically.
Can someone explain why this isn't working in either Safari or Chrome? I've tried a lot of different things, but I'm new to jQuery so I'm probably missing some detail in how that works.
We went to the bottom of this in the chat. What probably caused the problem was another event-handler attached to (possibly) body, that undid the click.
So the solution was to stop the event from propagating:
event.stopPropagation();
While assigning the click event handler to the button you should use jquery on
This should ensure that whenever a new button with added with same selector (as in when event was assigned), event handled will be assigned to that button
Some examples here
The problem is the click() function is from jquery and you're attempting to fire the click function from the DOM object.
Try
$(button).click();
Here's a plunk.
http://plnkr.co/edit/2pcgVt
You can use the following statement.
var button = $('.some-class').find('button')[0].trigger('click');
try jquery's trigger() function:
$(button).trigger('click');
see jsfiddle: https://jsfiddle.net/665hjqwk/

Can we detect whether a link was clicked within a DIV that has a jQuery.click()?

I'm wondering whether there is an easy way to detect a click on a link that appears within a div on which I want to handle clicks...
So, there is an simple example of HTML code:
<div class="checkmark">
<div class="box"> </div>
<div class="label">Checkbox label possibly with an anchor.</div>
</div>
So in this example, I use a set of <div> tags to create a checkmark. The "box" is where I show a little square and when checked, also show the checkmark (a red cross, for example.)
To make the checkmark work as expected, I use jQuery and capture mouse clicks on the main <div> tag:
jQuery("checkmark").click(function(e){
e.stopPropagation();
e.preventDefault();
jQuery("box", this).toggle("checked");
});
Pretty easy, that works great (the "checked" class is enough to show a checkmark since that can be defined using CSS.)
However, as we can see in the example, the "label" includes an anchor. If I click the anchor, the jQuery I just presented runs, but the anchor does nothing. If I remove the stopPropagation() and preventDefault() the anchor gets clicked, but the checkmark is toggled too.
What I'm wondering is: is there an easy way to check whether the propagation would trigger the anchor and in that case just ignore the click in the "checkmark" code?
Something like that:
jQuery("checkmark").click(function(e){
if(!(anchor.clicked())) // how do we do this?
{
e.stopPropagation();
e.preventDefault();
jQuery("box", this).toggle("checked");
}
});
P.S. I do not know whether there are anchors in the label. So the discovery has to happen in the click() function (unless there is a better setup and that "if" could happen differently).
Note: here I show a target="blank" parameter. In the real deal I will actually open a popup, but that doesn't really make a difference here.
This is what event.target is for.
For example, in this case:
if($(e.target).is("a")) {
// It was the anchor element that was clicked
}
jsFiddle here
You can just add this handler:
jQuery("checkmark a").click(function(e){
e.stopPropagation();
}
It will stop the click event from bubbling from the link to the div, so the link will be activated, and the event never reaches the div where it would be stopped.
You could use the event delegateTarget property to see which DOM element triggered the event.
if($(e.delegateTarget).is("a"))
// execute code

Keydown event not removed from document and not registering on div element

NOTICE: The cause of the problem has been found, read the comments to the first answer.
I have a dropdown list of things, that is hidden until the user invokes it.
It's something like this:
<div>
<button></button>
<ul>
<li></li>
....
<li></li>
</ul>
</div>
The basic idea:
The list becomes visible when the user presses the button shown in the code above.
I need to make the list able to be navigated by keyboard,
i.e. if the user presses up or down while the list is open, the appropriate li will be selected (as if the mouse was hovering over it instead)
The event listener responsible for giving this functionality to the list should be attached when the list becomes visible and be removed when the list becomes hidden again.
Something like what Bitbucket does for the dropdown lists, but even simpler.
The issue:
I tried to attach an event listener to the ul and then on the div element, when the former had no effect, to no avail.
The code is this
ON SHOW
this.<ul or div element here>.addEventListener('keydown', this.keyboardNavigation.bind(this));
ON HIDE
this.<ul or div element here>.removeEventListener('keydown', this.keyboardNavigation.bind(this));
and the callback is like so
function keyboardNavigation(e) {
console.log('foo');
}
NOTE: "this" is an object to which the div and the ul are both properties of, and the callback function is actually a method of that object.
QUESTION 1:
Why is the keydown event not working when I attach it to either the ul itself or the parent div?
Anyway, since these did not work, I decided to attach the listener to the document.
ON SHOW
document.addEventListener('keydown', this.keyboardNavigation.bind(this));
ON HIDE
document.removeEventListener('keydown', this.keyboardNavigation.bind(this));
Same callback.
Now, while this works, I noticed that the event listener is not removed from the document.
I later noticed that another keydown event listener I had attached to the document for another task, is also not removed when that task is done, while it should.
QUESTION 2:
Why are the event listeners not removed? I cannot understand what I am doing wrong, I am removing the exact same callback on the exact same event as were those that were added.
Any help will be much appreciated.
NOTE:
I have tried doing it with jQuery's .on() and .off() instead, as suggested here, although I do not want to use jQuery, yet same thing is happening.
My thoughts:
1 Is it because the DIV or UL isn't getting the keyboard events because the don't have focus? Whereas the document is always getting the bubbled events?
To test this, click in the DIV/UL and type and see if the keyboard events get triggered then.
I think binding to the document - if you want the user to be able to just start typing after clicking - is the right thing to do here.
2 Is this because you are not removing the same handler you created? You should retain a reference to the handler you create with the first bind call and pass this reference in to the remove call - otherwise you're creating another (different) handler and asking to remove that.
E.g.:
var f = this.keyboardNavigation.bind(this);
document.addEventListener('keydown', f);
document.removeEventListener('keydown', f);

jQuery .not() isn't filtering elements from function - Ideas?

I'm trying to create a function that disables voting button after an Ajax POST success. The voting buttons are enabled until POST completes, and then are fixed with 'disabled' styling and are in-clickable. I'm trying to use jQuery .not() to disable starting the function from clicked buttons (with the class 'disabled') but I'm not having much luck. Here's a fiddle of my function so you can see my problem, I'm not sure what I'm missing but I'm hoping someone can help me find my error, it's frustrating me : )
jQuery Code:
$("a.votebutton").not(".disabled").each(function(index) {
var el = $(this);
$(this).click(function() {
el.addClass("active disabled").unbind("click");
el.siblings().addClass("disabled");
});
});
​
The problem is that your code:
$("a.votebutton").not(".disabled")
selects all of the links that are not disabled at the time that line of code runs, and then you loop through assigning click handlers. These click handlers remain bound to those links even if they happen to be given the "disabled" class at a later time - so when you add the "disabled" class to the clicked element's siblings those siblings still have a working click handler. If you unbind the click from the siblings that should fix it:
// change
el.siblings().addClass("disabled");
// to be
el.siblings().addClass("disabled").unbind("click");
Note that you don't need the .each():
$("a.votebutton").not(".disabled").click(function() {
$(this).addClass("active disabled").unbind("click")
.siblings().addClass("disabled").unbind("click");
});
Another way to do it would be to use delegated event handling:
$("div.panel").on("click", "a.votebutton:not(.disabled)", function() {
$(this).addClass("active disabled")
.siblings().addClass("disabled");
});
That way the clicks are only handled once they bubble up to the containing div ("div.panel"), at which time your click handler is only run if the event's source element matches the selector that is the second parameter to .on().
Updated demo: http://jsfiddle.net/RSezp/2/

Categories

Resources