dojo widget won't emit event - javascript

I have a custom dojo widget that I need to listen for an event on another 3rd party widget and then emit that an event with the event object to another custom widget. For some reason, my custom widget is not emitting the event or the event is not registering properly with my second custom widget.
Here is the event-related code in my 1st custom widget:
onSelectComplete : function(evt) {
// this custom widget inherits from dojo/Evented. I've tried using this.emit and I've tried inheriting from _WidgetBase
on.emit(self, "select", evt);
},
startDrawing : function() {
//self._drawToolbar is the 3rd party widget from an API
self._drawToolbar.activate(Draw.POLYGON);
self._drawEndHandle = self._drawToolbar.on("draw-end", self.onSelectComplete);
},
Here is the listener in my 2nd custom widget:
on(self._selector, "select", function(evt) {
console.log(evt);
});
For the listener, I've tried listening for onSelectComplete, selectComplete, SelectComplete, selectcomplete, select-complete and none have worked. I've also tried using aspect.after instead of on, but that also didn't work. I was able to determine while debugging that the onSelectComplete of the 1st custom widget is being called correctly.
I'm stuck...

Sorry I didn't provide the answer sooner, but I did discover a solution.
Instead of having my dojo module inherit from dojo/Evented, I made it inherit from dijit/_WidgetBase. By doing so, my custom dojo module/widget now implements the on function.
So in my 1st widget I have an empty function called onSelectComplete : function (evt) {}, which I call when I want to emit the event.
And in my 2nd widget my code is:
on(self._selector, "selectComplete", function(evt) {
console.log(evt);
});

Do make things clear: The onXXX functions was the old way to emit.
I was fine with it, but it is deprecated!
What the hell is 'self'? Did you mean: 'this'?
Any widget inheriting from dojo/Evented can
on.emit(this, "select", {anyProperty: 'will be mixed in the event'});
The above is bubbling up which seems to be what you want to do ?
You could also do
this.emit("select", {anyProperty: 'will be mixed in the event'});
But this is only triggered once and not bubbled up.
From any other widget you can subscribe as you stated.
Tell me if you need a working example.

Related

How to get event from inside a custom plugin fired from the outside without passing it as an argument?

I am making a JQuery plugin that needs to know the the context event that called the plugin so I can do e.preventDefault(); from inside.
The plugin is here: https://github.com/brenosilver/JQuery.PopupBox
Currently I have this:
$("#el").click(function(event){
$("#targetEl").popupBox(event);
});
But I don't want the event to be passed as I'm trying to make it as user friendly as possible.
Inside the plugin I have this:
$.fn.popupBox = function(event, options){
event.preventDefault();
event.stopPropagation();
}
I had success using:
var contextObject = window.getSelection().getRangeAt(0).startContainer.parentNode;
var event = $._data( $(contextObject)[0], "events" );
but this doesn't return a native event type object. So I can't use event.preventDefault();.
Further explanation:
I need to have event.stopPropagation because if not, the element the plugin handles just shows on the screen then hides instantly.
Based on the comments and the example of the plugin usage, it's seems to me that the design of the plugin should be a little different.
Plugin should not be concerned with outside-world events, and of course it should not mess with events and whatever happens outside of it. After all this is the purpose of the plugin - to be plugged in and operate.
I recommend to change the strategy to the one where you bind click events on the click target inside of the plugin.
The configuration then might look like this:
$("#targetEl").popupBox({
clickOn: '#el'
});
or other way around:
$("#el").popupBox({
target: "#targetEl"
});
In both cases you would bind click event inside of the plugin yourself and be able to do with event whatever you need.

Reinitialize (or Re-declare) Dojo widget

I have a piece of code that initialises a resize handler in the following way:
dojo._hasResource["dojox.layout.ResizeHandle"] = true;
dojo.provide("dojox.layout.ResizeHandle");
dojo.experimental("dojox.layout.ResizeHandle");
dojo.declare("dojox.layout.ResizeHandle", [dijit._Widget, dijit._Templated], {
_init: function(){},
create: function(){
this.connect(this.resizeHandle, "mouseover", "_init");
}
// ... more properties
});
This is written in a core app file which I cannot edit. I need to rebind this resize handler to respond to touch events. I was thinking of overwriting this widget and rebind the resize handler with "touch" events. Something like so,
this.connect(this.resizeHandle, "touchstart", "_init");
I have never worked on Dojo before. So, I am not sure how the module system works. I tried creating a new widget by changing the string that identifies the widget ("dojox.layout.ResizeHandle") but no luck there.
How do I destroy the existing widget and rebind with touch events?
This code does not initialize a widget. The declare function creates a class. In this case it creates a class called "dojox.layout.ResizeHandle". To use this class you need to require it and then instantiate it. Something like this
require(["dojox/layout/ResizeHandle"], function(ResizeHandle) {
var resize = new ResizeHandle();
}
From there you can attach new handlers.
on(resize.resizeHandle, "touchstart", "_init);
It's also worth pointing out that you are using old deprecated dojo syntax (connect vs on, etc) although you may be using an older version of dojo.

Agility.js + jQueryUI, pass parameters to event handlers in controller

The Agility.js documentation seems to say pretty clearly that Agility objects can accept any valid jQuery event type:
Usual DOM events such as click, dblclick, mouseenter, etc are supported through
jQuery's event API. Please consult jQuery's API for a list of events supported.
But in the docs and in all other examples I've seen, all the controller functions bound to events take no parameters. For example, the following snippet is taken straight out of the online docs:
var button = $$({msg:'Click me'}, '<button data-bind="msg"/>', {
'click &': function() {
this.model.set({msg:"I've been clicked!"});
}
});
$$.document.append(button);
Here the lambda attached to the click event obviously is parameterless. This works OK for ordinary jQuery events, but to use jQueryUI events, each event function has associated data. For example, if I want to use Draggable and Droppable widgets, the drop() function is called on the Droppable to indicate that a Draggable has been dropped onto it, and I need the parameters to drop(event, ui) to figure out which Draggable it was.
Is there any way to declare my controller event handlers so that I can get access to those parameters? Alternatively, is there some other way to do what I'm trying to do? Not getting any information about an event on a controller other than "it fired" seems like a real shortcoming here. I'm not even sure it is possible to extend Agility so that it can handle events other than the standard DOM ones, although I don't see any reason why it shouldn't be, from my reading of the code.
Agility does provide a trigger() function for client code to fire events, which allows for parameters other than the event type. I thought of wiring that up to the jQueryUI event somehow, but I don't see quite how. More to the point, why can you even pass parameters to trigger() if controllers can't see them?
That the example does not show it is unfortunate, but that doesn't mean the argument is not there.
var button = $$({msg:'Click me'}, '<button data-bind="msg"/>', {
'click &': function(jqEvent) {
this.model.set({msg:"I've been clicked!" + jqEvent.target.nodeName});
}
});
$$.document.append(button);
When in doubt just include a console.log(arguments) in your event handlers and see for yourself. You will get the same arguments jQuery gives you.
If you experiment with .trigger() and extra params you will find that there are no surprises there, either.

Why JQuery doesn't trigger added eventlistener?

I have recognized, that eventhandler added with addEventListener where not influenced by
$.trigger. The special reason for that question is, that I have several self created html elements which implements some logic without using external libraries (only pure js).
Now in my main project I want to use these controls and further there I have external libaries like jQuery.
Now for example I want to trigger the change event (remember...events are added with element.addEventListener("event", function)) with $(element).trigger("change").
Result: nothing happened
The event only is triggered, when i use code like this:
event = document.createEvent("HTMLEvents");
event.initEvent("change", true, true);
event.eventName = 'change';
element.dispatchEvent(event);
On the other side...eventhandler added with jQuery, where also triggered by a custom created event.
Now the magic question: Why??
You can find a little example in the following jsfiddle. http://jsfiddle.net/UYyXv/3/
I have got an explanation from the jquery forums.
jQuery events are a level higher than the native events. Trigger fakes
a jQuery event. If you want to fake a native event you need to call it
as you wrote in the question.
Simple answer, don’t use native events.
JΛ̊KE
why don't you just try
$(SELECTOR).change(function(e){
e.preventDefault();
//***DO STUFF HERE***
})

'click' event disappears in Backbone.View after using Quicksand

There is a 'View' in the model with the event click. After using the Quicksand effects plug-in for jQuery, the objects loose their event handlers. I have tried to add the listener for the event with standard methods in backbone.js:
events: {
"click .objContact" : "openChat"
}
and the same tools jQuery delegate:
var self=this;
this.$el.delegate('.objContact','click', function(){
self.openChat();
});
and live:
var self=this;
this.$el.find('.objContact').live('click', function(){
self.openChat();
});
but the click event disappears.
What could be the problem? And how do I solve it?
UPD: Calling 'Quicksand' is in Backbone.Router (subject to change is obtained directly by means of jQuery, not Backbone), so changes are not handled in Backbone.View
UPD 2: The problem is solved in the following way - by moving the handling of the click event from the View-model to View-collection. And treated with live (did not work in on)
Simple Answer: instead of linking the function to the link with the classic ajax method that is
$('a.oldJqueryClass').click(function(){....
you need to make that function standalone, declaring a new function
function myfunction(params) {alert(params);}
than in the link you call that with the old school way:
Click here
In this way the cloned element will contain itself the call to the function and you can forget about restoring the dom integrity broken by the cloning of quicksand.
I did it in my project, it works fine.
Do a call to delegateEvents() after the related DOM entries have changed or become overwritten. In a traditional Backbone app this is typically done in the render method, but you probably need for figure out when and where quicksand does it's magic (I do not know anything about it), and call delegateEvents that will reactivate the events for the current elements in the DOM.

Categories