Is there a "onExpand" event or similar for dijit.TitlePane? - dojo

Is there any way to get an event callback when the dojo-dijit's TitlePane expands?
I can capture onClick on the TitlePane. However, that is not enough for me. I have a button for "Expand All" TitlePanes. When user clicks on that I iterate on all TitlePanes and call it's toggle() method. When that happens, onClick event is not fired (as expected). I was wondering if there is any event fired upon toggle().
Or any other smart ways to address it also will be appreciated.

After looking into documentation in detail, I do not think there is any built in event that is fired during the toggle/expand. I ended up firing a custom event, and that helped me get what I wanted.
This answer helped me - https://stackoverflow.com/a/12852043/3810374
Basically,
First using isOpen() method, ensure the title pane is not already expanded. Then call toggle() method, and fire a custom event like this:
require(["dojo/on"], function(on){
// Send event
on.emit(target, "onExpand", {
bubbles: true,
cancelable: true
});
});
And then handle the event:
require(["dojo/on"], function(on){
// register event handler
on(target, "onExpand", function(e){
// handle event
});
});
You may be wondering, why not just do the work right after toggle(), instead of going through the pain of firing/handling event. I needed to handle the event in a particular closure, where I have access to other objects and variables.

Related

Vue 3 - Prevent event propagation on custom event handlers

If i have a custom event handler like #my-event and i emit it with
this.$emit('my-event')
it calls all the events of #my-event from all parent components.
But i want to prevent this.
On normal event handlers like #click, we can simply add .stop behind it to prevent this behaviour.
But .stop does not work on custom event listeners.
Fiddle without stop: https://jsfiddle.net/xn9sq4cp/
Fiddle with stop: https://jsfiddle.net/xy18mspz/
I know i can add
inheritAttrs: false
to prevent event propagation globaly, but i dont want this.
So, how can i prevent event propagation for custom event handlers.
Thanks.
You can stop the component from emitting the event to stop it from being bubbled up by adding this:
// ...
emits: {
'my-event': false
}
// ...
JS Fiddle

How to cancel execution of debounced function in form event?

I have a form with 2 handlers:
<form onChange={_.debounce(func, 1000)} onBlur={func} />
I used this construction to handle update of the data via websocket connection, and this solution is just what I need, but in this particular case func fires twice on blur, is there any way to cancel execution of onChange handler when onBlur is being triggered?
Ok, I've found that lodash .debounce function has two handy methods: cancel and flush which are just what I've needed.

Strange behaviour of custom drag and drop function

I'm currently creating an electron application (Frontend is in Vue) which can trigger native Drag-and-Drop-Operations. These Operations behave strange if i trigger them with HTML5 Drag Events (like dragstart, dragstop, etc.). So I have to implement my own Drag-and-Drop Handler using mouseup, mousedown and mousemove. So in simple theory:
If MouseDown is triggered -> Set Flag
If MouseUp is triggered -> Remove Flag
If MouseMove AND Flag -> checkCurrentPosition vs. initialPosition -> Do something
new Vue({
el: "#app",
data: {
mousedown: false
},
methods: {
onMouseDown: function(e){
console.log('mousedown');
this.mousedown = true;
},
onMouseUp: function(e){
console.log('mouseup');
this.mousedown = false;
},
onMouseMove: function(e){
if(this.mousedown) {
console.log('mousedown && mousemove');
console.log('clientX:', e.clientX);
console.log('clientY:', e.clientY);
}
},
}
})
Fiddle
if you check this example, open up your browsers console and play a little bit around with the image (click, drag and drop,...) you will see that if you drag the placeholder image, the mousedown event is triggered and the flag is set. Then I would expect that the mousemove event would be triggered frequently, but this is not happening.
Normally if you bind mousemove to some Div its triggered frequently if you hover with your mouse over it and you can get the actual position for example. But this is not happening after mousedown.
NOTE: The mouseup event in the Fiddle is not bound to Window, so if you Drop the Element outside of its area the mouseup event will not be triggered for the element. So the flag is not removed and then you can see the behaviour I would expect. the mousemove event is frequently triggered. So I think that the problem is that while the mouse is pressed the mousemove event is not triggered correctly.

Vue ctrl+s event listener not firing

My application dialog should respond to "Ctrl+S" for a save function and cancel the default browser Save event.
<div
#keyup.83="doSave"
#keyup.ctrl.83="doSave"
#keyup.alt.83="doSave"
tabindex="0">
The doSave event is fired on pressing 's' (and alt+s) but not on ctrl+s.
Why is ctrl+s not fired?
BONUS QUESTION: Is there a way to preventDefault without coding it? Somehow it should be possible adding .once but the docs are vague.
https://codepen.io/cawoodm/pen/qvgxPL
There are several questions packed into your question, so I am going to answer them one by one:
Why is ctrl+s not fired?
Several reasons. You are using the keyup event, while the browser starts to save the page on a keydown event. Your keyup event is thus never fired.
For any event to be registered on your div, your div must have focus, because otherwise the event will not originate from that element, but instead from (presumably) the body.
Is there a way to preventDefault without coding it?
Yes. Add the prevent modifier to your event. In the same way, you can use once to unregister an event after it has triggered once, stop to use stopPropagation() and passive to explicitly not stop propagation. You would use something like: #keydown.ctrl.83.prevent="saveMe".
How do I get this working?
If you are fine with the user having to focus the element before being able to save, and otherwise getting the default behaviour, use the following:
<div
id="app"
tabindex="0"
#keydown.ctrl.83.prevent.stop="saveInsideComponent"
>
<!-- -->
</div>
Otherwise, this is one of the few moments where registering your own event listener is useful. Just make sure to remove it before your component is destroyed, or you will have a rogue event listener throwing errors on other components + a memory leak to deal with.
mounted() {
document.addEventListener("keydown", this.doSave);
},
beforeDestroy() {
document.removeEventListener("keydown", this.doSave);
},
methods: {
doSave(e) {
if (!(e.keyCode === 83 && e.ctrlKey)) {
return;
}
e.preventDefault();
console.log("saving from DOM!");
},
}
#Sumurai8's answer is great but I would add support for apple devices by checking if e.metaKey is == true. The code then looks like this:
mounted() {
document.addEventListener("keydown", this.doSave);
},
beforeDestroy() {
document.removeEventListener("keydown", this.doSave);
},
methods: {
doSave(e) {
if (!(e.keyCode === 83 && (e.ctrlKey || e.metaKey))) {
return;
}
e.preventDefault();
console.log("saving from DOM!");
},
}

ReactTestUtils.Simulate can't trigger event bind by addEventListener?

Here is the example:
http://jsfiddle.net/hulufei/twr4thuh/7/
It just worked when bind onClick in virtual dom(like line 18), but If I comment line 18 and comment off line 8 to bind click with addEventListener, it failed.
So what's the problem?
TestUtils triggers events within react's synthetic event system, so the native event that addEventListener listens for is never going to be triggered. You will need to use the native click method on the element in your test:
var events = Events();
ReactTestUtils.renderIntoDocument(events);
events.refs.button.getDOMNode().click();
events.state.event.should.equal('click');
Additionally, you've misspelled clickHandler in your addEventListener definition.
jsfiddle
You can also simplify adding your event listener by reusing your prop definition:
componentDidMount: function () {
this.refs.button.getDOMNode().addEventListener('click', this.clickHandler);
},
Note:
Is there a reason why you want to use addEventListener instead of just passing an onClick attribute for your button? Unless there's a specific and good reason otherwise, i'd suggest doing things the react way when handling events for sanity :)
Edit
I originally mentioned that I did not know what TestUtils' SimulateNative.click did not trigger the event. I was wrong in thinking that it ever would since it would be simulating a native click event within the react even system. #thilo pointed me in the right direction :)
I had many problems while testing addEventListener, and I got the following conclusion.
You can create the events listener with pure javascript, jquery, but when running the tests with Jest I always had a problem.
The rendering of ReactTestUtils does not work directly with the document, and when we do:
For example, our events were added in the document, when rendering with ReactTestUtils it creates a div and renders it in the div, This way I could not get Simulate to trigger the call.
My first solution was to use jquery to create the listener and to test I did the render manually by appending the div in document.body, and triggered the events with the dispachEvent of javascript. But I thought the code was dirty, not the best way to work.
I made a sample code by adding the event and testing it with Jest, also have a test teaching to get all the listener that were created.
You can find the code here: https://github.com/LVCarnevalli/create-react-app/tree/master/src/components/datepicker
Component:
componentDidMount() {
ReactDOM.findDOMNode(this.datePicker.refs.input).addEventListener("change", (event) => {
const value = event.target.value;
this.handleChange(Moment(value).toISOString(), value);
});
}
Test:
it('change empty value date picker', () => {
const app = ReactTestUtils.renderIntoDocument(<Datepicker />);
const datePicker = ReactDOM.findDOMNode(app.datePicker.refs.input);
const value = "";
const event = new Event("change");
datePicker.value = value;
datePicker.dispatchEvent(event);
expect(app.state.formattedValue).toEqual(value);
});
Links:
window.addEventListener not triggered by simulated events: https://github.com/airbnb/enzyme/issues/426
Creating and triggering events: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events