GWT - How to stop propagation from a child's event to its parent - events

I'm building a GWT application with a Tree.
Every tree items represent an object which has a boolean attribute that we can set through a checkbox displayed in the tree item itself.
I have a selection handler to do some stuff on my tree which gets called on click on every tree items.
What I want to do, is to prevent selection event to firing up when I'm clicking on the checkboxes ...
However, checkboxes don't have a SelectionHandler, so I tried to put a ClickEventHandler with event.stopPropagation(), but SelectionHandler is still getting called ...
EDIT: actually SelectionHandler is getting fired before ClickEventHandler anyway ...
Thanks in advance

You might consider following this method provided in the GWT documentation here. That should do the bit what you are interested in.

Try using the separate click handler for the checkbox and use the event.StopProgation() there after inorder to prevent the event bubbling.

For stop propagation from child's event to parent in GWT you need to use
event.stopPropagation();

Related

Why do the xforms-select and xforms-deselect elements bubble?

According to the XForms specification most events are said to "bubble".
As per the DOM Level 2 Event Specification an event that "bubbles" means that the handlers for this event associated with ancestor elements of the event dispatch target will also receive this event.
For an event to be specified as "bubbles" it means the xf:dispatch action cannot modify the bubble behavior to limit it to the target.
I don't understand what the benefit is of so many xforms events to bubble. For example, xforms-select and xforms-deselect. They apply to xf:item (of xf:select*) and xf:case (of xf:switch, i.e., used in a form with tabs).
Let's say I have an xf:case with an xforms-select handler that will cause a refresh on an expensive rendering widget, just when the tab is actually selected rather than every time the model is updated. Now I also have an xf:select in that same tab. Now whenever the user selects another item in that selection, the xf:case would receive the xforms-select at the bubble phase, doing the costly update operation every time.
This doesn't seem to make sense.
In fact xforms-node-attached has it right: we really want to be specific as to which form element gets the node attached. But apart from that, most events are said to bubble.
I could conform myself better with this issue if I understood the reason for this. Otherwise I am tempted to change my XForms engine to change the definition of xforms-select and xforms-deselect not to bubble.
This is to allow what is known as event delegation:
"Event delegation refers to the process of using event propagation (bubbling) to handle events at a higher level in the DOM than the element on which the event originated. It allows us to attach a single event listener for elements that exist now or in the future." (from an older version of this jQuery doc page)
In general, this is a good thing:
You use less event listeners.
A listener can listen on multiple targets.
You don't need to remove/add listeners as DOM elements are added/removed.
It seems that, in the HTML world, things have moved towards letting everything bubble. For example, the old focus event didn't bubble, and the newer focusin event bubbles.
If you have an event handler which gets activated by events dispatched to multiple targets, in some cases you need the ability to discriminate. This is where event context information is useful. Libraries like jQuery also allow you to associate an event handler filtered by CSS selector, which is neat.
Now in the case of xforms-select specifically, your issue is that you cannot discriminate between this event dispatched to an xf:case vs. an xf:select. This might mean XForms shouldn't have a single event for these two scenarios, or it should have enough event context information to discriminate between the two. I don't think that this is making a case for not letting the event bubble.

Is it possible to stop the propagation of a taghelpers in one of the taghelpers linked to that tag?

I would like to stop the propagation of any taghelpers linked to a tag. I have a attribute based taghelper that I use to check whether the user can see or use a tag, and based on that I would like to stop any further processing to happen.
output.SuppressOutput();
does not work in this regard.
Some more detail.
I have a grid that has rows and actions per row ( actually there are other types of actions, ie on the grid etc) the rendering of the actions happens using a grid renderer.
The actions are added to a context that is provided to the grid via the items property.
I have another taghelper that can be placed on any tag element which determines whether the user has rights to see the element or whether it is disabled. This taghelper is first in the hierarchy.
Now since the actual action taghelper doesn't render itself, the grid renders it, I can't suppress the output of the action, as it continues to the next taghelper in the hierarchy and adds it to the context.
I would like it stop executing the taghelper hierarchy and not add it to the context, without being able to stop the execution I have to now pass whether the action should be displayed or disabled along in the context and update all my various renderers code to handle this. Stopping the exectution is much simpler and touches a lot less code.

Am I using marionettejs properly?

hi i've been using backbonejs for almost 2 years now and am just starting out on marionettejs with my first app at this website.
the reason for my question is that in my app i have a Layout with a 2 composite view rendered as dropdown list and table (which updates itself whenever we change the selection on the dropdown list).
what i did was for the "change" event on my dropdown list, i have an MyApp.vent.trigger() which i have a listener at the MyApp.addInitializer() function that updates the other compositeview (the table below the dropdown list). actually for the whole app i have almost 6 of this triggers inside itemViews and compositeViews and listeners are inside the addInitializer() for some of the other functions.
i just want to know if i did this right? or is this how dev in marionettejs normally is?
thank you
Yes, that's the recommended idea. However, you don't necessarily need to use the top-level vent attribute: each sub-app and view has their own (scoped) event manager. In addition, you don't necessarily need to add the listener in an addInitializer.
Here's an example (from my Marionette book):
trigger an event at the view scope: https://github.com/davidsulc/marionette-gentle-introduction/blob/master/assets/js/apps/contacts/list/list_view.js#L15 This uses the triggers hash, but you could also do this.trigger("my:event") from within the view, like here: https://github.com/davidsulc/marionette-gentle-introduction/blob/master/assets/js/apps/contacts/list/list_view.js#L29
listening to the events (and retriggering them if necessary): https://github.com/davidsulc/marionette-gentle-introduction/blob/master/assets/js/apps/contacts/list/list_controller.js#L48 and https://github.com/davidsulc/marionette-gentle-introduction/blob/master/assets/js/apps/contacts/list/list_controller.js#L38
Hope this helps !

Adding live functionality to dynamically added element in jQuery

I make an element in jQuery plugin:
this.addButton = $("<a>", {
text: "ADD",
"class": "addButton"
}).appendTo(this.element);
Then i add live functionality:
this.addButton.live("click", function() {
that.somefunction("addSomething");
});
And it isn't working.
IF i change "live" to "bind" it works OR when i do:
$('.addButton').live("click", function() {
that.somefunction("addSomething");
});
it works too. But why adding live to an dynamically added element doesn't work?
Any ideas?
live() needs to examine the event on a parent element to work. The way you have set it up, the event can not propagate to any parent element.
Because of the way live() works:
The .live() method is able to affect elements that have not yet been
added to the DOM through the use of event delegation: a handler bound
to an ancestor element is responsible for events that are triggered on
its descendants. The handler passed to .live() is never bound to an
element; instead, .live() binds a special handler to the root of the
DOM tree. In the example above, when the new element is clicked, the
following steps occur: A click event is generated and passed to the
for handling. No handler is directly bound to the , so the
event bubbles up the DOM tree. The event bubbles up until it reaches
the root of the tree, which is where .live() binds its special
handlers by default.
* As of jQuery 1.4, event bubbling can optionally stop at a DOM
element "context". The special click handler bound by .live()
executes. This handler tests the target of the event object to see
whether it should continue. This test is performed by checking if
$(event.target).closest(".clickme") is able to locate a matching
element. If a matching element is found, the original handler is
called on it. Because the test in step 5 is not performed until the
event occurs, elements can be added at any time and still respond to
events.
lives doesn't bind an event to an object, it attach a listener to the window and then when the events bubble ups it checks for the original target. So you don't add it to the new object.

How do I obtain the GWT widget that wraps a given DOM element?

When a click event occurs, I want to determine which of my widgets was clicked. Note that, for performance reasons, I specifically don't want to add click handlers to each of my widgets.
It's easy enough to obtain the element that was clicked (it'll be the event target of the native event), but then how do I find the corresponding widget?
There is no standard functionality for it, afaik. But you can do it in a similar way as is done in GWT's com.google.gwt.user.client.ui.Tree class.
Basically it work there by first collecting the chain of Elements from the Element of your root Widget to the element of the Widget that clicked (see private method collectElementChain in Tree class). With this chain of Elements the Widget is found by traversing from the Root widget down to the Widget clicked (see private method findItemByChain in the Tree class).
This works for Tree because the Widget and Element index of the children of each Widget/Element match, and because it only allows a specific widget set as TreeItem's.
Actually you can get the widget associated with the main element of a widget using either gwtquery or the DOM.getEventListener(element) method which returns the widget associated with an element.
You can check out my response in another thread for some working code: GWT - How to retrive real clicked widget?

Resources