PDA

View Full Version : some tooltips needed during drag, stopPropagation doesn't seem to do the trick



harmomelodic
12 Oct 2010, 8:19 AM
I'm trying to enable tooltip information over a part of my page during a drag.
The after executing the code below (and finishing the procedures that called onDragOver), the event seems to die. I made sure the event is correctly not getting cancelled by DragDropMgr, but can't figure out why the tooltips still fail to show (they work fine when not dragging).

Interestingly, if I mousedown within the target element, the tooltips work, but if I mousedown outside of the target, but not on my drag targets, the tooltips do not show.

Is the target for the mousemove somehow getting messed up by where I 'mousedown'ed? How can I fix this?
I did look at the target, and at least in onDragOver it is the proxy element for the drag. Is it possible to change the target? Is there a better way to deal with this problem?



onDragOver: function(e, targetId) {
//console.log('dragOver: ' + targetId);
var temp = Ext.dd.DragDropMgr;
if ('target_id' === targetId) {
// target_el.fireEvent('mousemove', e);
temp.stopPropagation = false;
} else {
temp.stopPropagation = true;
}
}

harmomelodic
13 Oct 2010, 11:29 AM
I've tried pussing something like
var dragEl = Ext.get(this.getDragEl()); dragEL.relayEvent('mousemove', mask); to my startDrag, but it doesn't seem to work.

I also tried adding
mask_el.dom.dispatchEvent(e.browserEvent()); to the above onDragOver, but that also seems to not work at all.

I need help learning how to forward this event to the element underneath the drag element.
Or more generally, how do you take a Ext event and forward/repackage it for a new target?

jtpacheco
13 Oct 2010, 11:31 AM
If you know the component that needs to get the event, then (at the end of onDragOver or whatever method it may be) you can add

Ext.getCmp(<your component's id>).fireEvent(<event name>, <event params>, ...).


Swap out Ext.getCmp with Ext.get if you need the event for an element.

harmomelodic
13 Oct 2010, 12:32 PM
I think my problem is actually in dealing with how to wrap an existing div with an Ext.Component.
I say this because when I set this up as...


var mask = document.getElementById('mask');
mask_el =new Ext.Element(mask);

mask_component.addListener('mousemove',function (e) {
svgdoc.DoMouseMove(replace_e_for_embed(e));
});
mask_component.addListener('mousedown',function (e) {
e.browserEvent.preventDefault();
svgdoc.DoMouseDown(replace_e_for_embed(e));
});
mask_component.addListener('mouseup',function (e) {
svgdoc.DoMouseUp(replace_e_for_embed(e));
});

things work, except during the drag.
I modified this to bring in component (actually Observable) functionality...



mask_component =new Ext.Component({
applyTo:'mask'
});


and then to use in the place of mask_el.
Something is working right...the el of the mask_component is correct and I can access it using getEl(). I can then use this as if it was mask_el, but the additional functionality (like fireEvent) that I need doesn't work, and if I register listeners directly with the compoent it doesn't work.

Maybe the config needs the parent or something???

btw...<div id='mask'> is part of the body.

harmomelodic
13 Oct 2010, 1:35 PM
So weird...
I moved all the code for the div into the config for the component...


mask_component = new Ext.Component({
renderTo: Ext.getBody()
, style: "display:block; left:"
+ box.x
+ "px; top:"
+ box.y
+ "px; width:"
+ (box.x + box.width)
+ "px; height:"
+ (box.y + box.height)
+ "px; z-index:100;"
, cls: "embed_mask"
, id: 'mask'
});

It does the same thing it did before...
attaching the listeners to the component: fireevent gets to them, but normal mousemove, mousedowns on the div do not get there.
the tooltips, attached to the element (getEl() ) do not fire when I am dragging.

Is there something I'm missing here? Why doesn't the component call the events on its element and all the listeners to that as well as the listeners to the component itself?
Can I attach the tooltips to the component instead of the element somehow (it errors deep in ext code when I try).
Can't I just re-fire the event on the element instead of the component and just forget all this mess? If yes, how?

jtpacheco
14 Oct 2010, 4:55 AM
Try debugging with Firebug and inspecting the mask_el object to see if the listeners are actually getting attached and registered. It could be that, for whatever reason, mouse events aren't valid for this element...but that would make no sense, would it.

Regardless, I've had that problem before, but maybe the event is named differently, ie mouseover instead of mousemove.

harmomelodic
14 Oct 2010, 7:17 AM
found this in the code...

<br><p>While <i>some</i> ExtJs Component classes export selected DOM events (e.g. "click", "mouseover" etc), this
* is usually only done when extra value can be added. For example the {@link Ext.DataView DataView}'s
* <b><code>{@link Ext.DataView#click click}</code></b> event passing the node clicked on. To access DOM
* events directly from a Component's HTMLElement, listeners must be added to the <i>{@link Ext.Component#getEl Element}</i> after the Component
* has been rendered. A plugin can simplify this step:<pre><code>

still confused....but I think learning how to create synthetic DOM events and passing them directly to the underlying element might be a better approach (although I am having some difficulty). Component just does seem like it is supposed to do this...

jtpacheco
14 Oct 2010, 7:35 AM
Well, it does make sense, because that's how I've disabled the default context menu on right clicks.

menu's config
listeners :
{
render : function(menu)
{
menu.getEl().on('contextmenu', Ext.emptyFn, null, {preventDefault:true});
}
}This adds (on) the contextmenu event listener to a menu, so that when the custom menu renders, the default menu won't show as well. It could be that this is how you have to add event listeners, in the component's onRender listener.

harmomelodic
14 Oct 2010, 9:09 AM
Well, that doesn't deal with the issue of how to use the component's fireEvent to call to the elements event listeners.

I did find a solution.



onDragOver: function(e, targetId) {
var temp = Ext.dd.DragDropMgr;
if ( (e.browserEvent.detail == 0)
&& ('valid_drag_target' === targetId)) {
var mask_el = mask_component.getEl();

var mouse_event = document.createEvent('MouseEvents');
mouse_event.initMouseEvent(e.type
, true
, false
, window
, e.browserEvent.detail+1//mouse click count
, e.browserEvent.screenX//screex
, e.browserEvent.screenY
, e.browserEvent.clientX//clientx
, e.browserEvent.clientY
, e.browserEvent.ctrlKey//cntrl
, e.browserEvent.altKey//alt
, e.browserEvent.shiftKey//shift
, e.browserEvent.metaKey//meta
, e.browserEvent.button//event button arg
, null);//related target
mask_el.dom.dispatchEvent(mouse_event);
}
}


Kindof ugly and I wish I could see a more elegant solution, but it works. For some strange reason the event returns to onDragOver, hence the fiddling with event.detail (this prevents an infinite loop). I guess events call up layers for some reason but not down them??? Anyways, problem solved...thank god as it took endless fiddling...

harmomelodic
14 Oct 2010, 9:10 AM
of course, the event listeners have been moved back to the Element, and out of the component.

jtpacheco
14 Oct 2010, 10:02 AM
Strange, I can't imagine why you'd be forced to make the element respond to events like that. I'm not all that sharp on DOM/Element events, so maybe someone more enlightened can shed some light on it.

But, glad you got it working, however ugly it is. Shame its just not easier to get a handle on right away.