Event Bubbling or Looping Callbacks? - javascript

I am having trouble with JQuery / javascript / Knockout.js
The events are looping incrementally every time they are called.
Like for example, a click event with alert.
If I click once, it will alert once.
BUT, if I click the second time, it will alert twice.
That goes on the third time and so on, It loops by the number of times it was called.
I am quite risking myself here because I cannot paste the codes unless I give you the whole program which is not possible because this is an incomplete company project.
So I am very sorry if I don't have any codes to provide. I just need ideas / answers / possible solutions.
What do you call this problems? Is it Event Bubbling?
So my main question is, is it possible to stop all the events after calling it once? I have no loop statements whatsoever, all I have is some functions and an .on('click'... events

I finally found the answer to my question.
Since the .on events are stacking every time it's clicked, and once you clicked it twice, the events will also fire twice, then I had to insert .off() before .on('click', functionName);
That makes it like this:
$('testBtn').off().on('click', functionName);
That should clear up all the event stacking.

One common situation when binding click events is to have a common handler being used in both parent and child elements.
Example:
<div id="parent" data-bind="click: doSomething">
<a data-bind="click: doSomething">Clickable</a>
</div>
When the child is clicked its handler, doSomething, will be triggered once, and then the parent click handler, that again calls doSomething, will be also triggered.
To prevent event propagation in scenarios like this you can set the extra clickBubble binding to false in the inner element.
Example:
<div id="parent" data-bind="click: doSomething">
<a data-bind="click: doSomething, clickBubble: false">Clickable</a>
</div>
More about all the details of the click binding here.

Related

Simulate clicking a button

If I have an existing click event associated with a button, can I use code to simulate that button being pressed so the code in the click event will run? I'm asking because I want there to be certain times where the user does not have to press the button for code to be executed. I would like to press the button automatically for them in certain instances if that makes any sense.
As simple as this,
$(function() {
$('#button').trigger('click');
});
var button = document.getElementById('yourButtonIdHere');
button.click();
This will fire a click event in the button
You can trigger a click event on an element by calling the .click() function on the element. By passing no value to the function the click event will fire, as opposed to setting up a listener for the click event.
If the button has an id of "form-btn", here's what that would like:
<button id="form-btn">Submit</button>
<script type="text/javascript">
//Setup the click event
$('#form-btn').on('click', function (e) {
alert('clicked!');
});
//Call the click event
$('#form-btn').click();
</script>
This should work fine, although I usually try to use a named function when setting up my event handlers, instead of anonymous functions. By doing so, rather than triggering the event I can call the function directly.
Note that in my experience, older browsers (IE6, IE7) sometimes limit what code-triggered events can do as a safety precaution for the user.
Here's documentation on the .click() function: http://www.w3schools.com/jquery/event_click.asp
Edit 1
I forgot that jQuery also has the .trigger() function, as used in choz's answer. That will also the job quite nicely as an alternative to .click(). What's nice about .trigger() is that it can trigger standard events as well as custom events, and also allow you to pass more data in your event.
Just make a function and run the function from within the button.
Three Choices:
You can call the click event handling function directly when appropriate:
if(timeIsRightForClick){
yourClickHandler();
}
You can simulate a button click by calling the .click() method of the button.
$("#ButtonID").click()
https://api.jquery.com/click/
Same as #2, but using jQuery's trigger() function, which can be used on standard events and custom ones:
$("#ButtonID").trigger("click");
http://api.jquery.com/trigger/
Choices #2 and #3 are usually better because they will cause the event handling function to receive a reference to the click event in case it needs to use that object. Choice #1 doesn't cause an actual click event (just runs the code you tell it to) and so no event object is created or passed to the event handler.

Click event hijacked by jQuery instead of knockout

I'm using the Knockout webmail tutorial as a template for a Single Page Application I'm working on.
However I'm having trouble implementing the click binder, I've had this sort of thing working before but his time the click events are being hijacked.
My view model has a function:
var self = this;
self.goToItem = function(item) { location.hash = "#/Item/" + item.id };
which is standard.
<h2>Saved Items</h2>
<div data-bind="foreach: savedItems">
<div data-bind="click: $root.goToItem">
<p data-bind="text: name"></p>
</div>
</div>
I've tried the:
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
but, tellingly, this came back empty although the foreach has data to loop over.
The problem now is that the mousevent click is now caught by jQuery, I haven't had to delve into this before, but I am sure knockout runs without jQuery. At the moment the only jQuery I use is for the Ajax calls.
So where do I go to inspect the events on DOM objects, preferably in Chrome?
How can jQuery butt in?
Have you tried to use clickBubble binding?
Preventing the event from bubbling
By default, Knockout will allow the click event to continue to bubble up to any higher level event handlers. For example, if your element and a parent of that element are both handling the click event, then the click handler for both elements will be triggered. If necessary, you can prevent the event from bubbling by including an additional binding that is named clickBubble and passing false to it, as in this example:
<div data-bind="click: myDivHandler">
<button data-bind="click: myButtonHandler, clickBubble: false">
Click me
</button>
</div>
Normally, in this case myButtonHandler would be called first, then the click event would bubble up to myDivHandler. However, the clickBubble binding that we added with a value of false prevents the event from making it past myButtonHandler.
More details about click binding is here http://knockoutjs.com/documentation/click-binding.html
If I replaced
click: $root.goToItem
with
click: goToItem
it works again.
It seems the jQuery event firing was a red herring, I compared it to a working system and it started off in jQuery. I had to brush up on my DOM debugging, which is no bad thing.
Is the $root superflous, it took someone else to point this out to me. I was sure that in a foreach loop you could only access the $root functions via $root.

stopPropagation() of MSGestureTap event

I confused about how propagation of MSGestureTap event works in IE and on Windows Phone. Here is a code example:
First
http://jsfiddle.net/gTLKB/2/
(example tested on desktop IE11 and on Windows Phone 8 IE)
As you can see there are two nested div elements. On both of them I hanged MSGestureTap event listeners using approach described here http://msdn.microsoft.com/en-us/library/ie/dn433243(v=vs.85).aspx.
As you can see there is e.stopPropagation() for MSGestureTap event of inner element. So supposed behavior is next:
User clicks on inner element and see inner click alert message.
MSGestureTap event stop propagate and nothing happens after.
Actual result: MSGestureTap fires for outer element.
The problem will be solved if stopPropagation() for both MSGestureTap and MSPointerDown but in real life I have another element upper in DOM tree which has MSPointerDown listener which should be called, so I can't stopPropagation() for MSPointerDown event.
Second
If you remove e.stopPropagation() for MSGestureTap event for inner element then MSGestureTap listener for outer element will fire twice, which for me looks very odd. Code example:
http://jsfiddle.net/gTLKB/4/
Order of events execution:
inner click
outer click
outer click
Third
In previous example if you will change order in which listeners are hanged on elements the order of event execution will change too. Example:
http://jsfiddle.net/gTLKB/5/
outer click
inner click
outer click
Order of events execution in this particular case should not depend on order in which listeners have been added.
Can someone explain all that? I will be extremely appreciate for any help.

onclick and jQuery event binding causing pain

I have a link which has an onclick attribute, and there is a toggle event that I bind to the link (I know I'm committing a sin here by mixing these two, but there is nothing I can do about it.)
Now to this background, I have 2 scenarios:
The user clicks on the link - The order of execution of events is :- onclick first, then the toggle event bound via jQuery
Fire the click event via jQuery - The order of execution here is different, the bound event fires first then the onclick.
Something goes horribly wrong because of these 2 scenarios and the flipping of the order. I need the bound events to run first before the onclick. Is there any better way to do this than removing the onclick attribute on init and saving them to the link via .data() and then handling through the toggle event?
Another thing that I need to take care of (life is complicated), the link can be toggled through the querystring. i.e. if the user comes in from another page via another link, there will be a querystring parameter with the link id, which is read by another JavaScript function that does scenario 2 mentioned above.
So if the onclick is to be removed, it will have to be done on init.
What can I do to untangle this mess?
What is so wrong to remove the .onclick function and re-bind it afterwards (after you bound all your methods which should fire before) ?
HTML
<div id="foo" onclick="inline();">click me</div>
Javascript
function inline() {
alert('I was bound through onclick=');
}
$(function() {
var $foo = $('#foo'),
stored = $foo[0].onclick;
$foo[0].onclick = null;
$foo.bind('click', function() {
alert('I was bound via jQuery');
});
$foo.bind('click', stored);
});
After that code, the order of alerts would be:
'I was bound via jQuery'
'I was bound through onclick='
Demo: http://jsfiddle.net/3MKWR/

Performance difference between jQuery's .live('click', fn) and .click(fn)

I love the new live event in jQuery 1.3. The question I have is the performance of this event. I know the advantages of using live over click/bind('click') but is there a performance hit for using it over click/bind('click')?
If not, why would you ever use click or bind('click')?
If not, why would you ever use click
or bind('click')?
Because $.live() has some significant disadvantages
Live events do not bubble in the traditional manner and cannot be
stopped using stopPropagation (This changed in jquery 1.4.4) or
stopImmediatePropagation. For example,
take the case of two click events -
one bound to "li" and another "li a".
Should a click occur on the inner
anchor BOTH events will be triggered.
This is because when a
$("li").bind("click", fn); is bound
you're actually saying "Whenever a
click event occurs on an LI element -
or inside an LI element - trigger this
click event." To stop further
processing for a live event, fn must
return false.
Live events currently only work when used against a selector. For
example, this would work: $("li
a").live(...) but this would not:
$("a", someElement).live(...) and
neither would this:
$("a").parent().live(...).
See this.
As for why you would ever use click or bind instead of live, the answer is because you don't need the extra functionality.

Categories