i'd like to do this:
show some form, handle Rectangle::onClicked event (disable form, set opacity to 0.2, process some javascript to submit form, then set opacity back to 1.0, enable form).
But I don't know how to do it.
It seems onClicked() is processed in "batch" mode, changing any ui properties aren't visible until the function exits. I played with states, transitions and animations, but still not succeed.
Thanks for any suggestion,
Michal
You can simply start two custom animations, one to hide the form and one to show it back. Something like this:
SequentialAnimation {
id: submitAndHideForm
ParallelAnimation {
// Animations to hide the form elements
}
ScriptAction {
script: submitForm()
}
}
ParallelAnimation {
id: showForm
// Animations to show the form elements
}
Then you could just start the first one with submitAndHideForm.start() when you want to submit the form, and when you get a response you can start the second one.
It should be possible to solve with states. You could try to do the Javascript processing in a WorkerScript. When the processing is done it will send back a reply to the QML WorkerScript element that sets the state of the form to enabled again. So in onClicked you do the disable animation by setting the state, and in the onMessage function of the WorkerScript element you do the enable animation by setting the state to "enabled".
Perhaps you talking about using XMLHttpRequest asynchronously. "Disable" form on sending request, and "enable" it when onreadystatechange called with readyState === XMLHttpRequest.DONE.
Related
I'm utilizing <v-dialog> component to display a form for my web app. I want to implement an unsaved changes dialog to popup when the user aborts their changes without saving and either close/keep the dialog open depending on a button press. Unfortunately, I'm having a bunch of trouble figuring out exactly how to prevent the default closing actions done by the framework.
So from what I can tell, you can close a dialog 3 different ways:
Setting the v-model property to false.
Clicking outside of the v-dialog modal unless the persistent prop is set to true.
Pressing the escape key.
Let's not worry about the 2nd way to close the dialog I referenced above and assume it is set to true.
Approach #1:
My first approach was to only allow the user to exit the dialog if they hit a cancel button on the form. I quickly hit a snag when I tried to disable the use of the escape button.
Here's what I have tried so far: In my App.vue mounted function:
mounted () {
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
console.log('The escape key was pressed.')
e.preventDefault()
e.returnValue = false
e.stopImmediatePropagation()
}
})
}
This should work. The log message is displayed in the console, but the dialog still closes after the escape key is pressed. I know I should be using key codes here, but this is for readabilities sake. I've also tried keyup and keypress with no success. There has to be something wonky happening in either the Vue.js or Vuetify framework that's messing this up.
Approach #2:
After I failed miserably trying to disable the escape key, I had to try something different. I tried adding this code inside the watch function to try and keep the dialog open if they cancelled:
dialog (val) {
if (val) {
console.log('Dialog is true')
} else if (!val && !confirm('Unsaved changes, do you still want to exit?')) {
console.log('User Wants to Keep Dialog Open')
this.dialog = true
} else {
console.log('Dialog is False')
this.close()
}
}
When I try and close the dialog, the confirm message pops up, and I hit the cancel button. Then, for some reason, the confirm dialog opens again. So, I hit cancel again, then the dialog dismisses like nothing ever happened. Here's what the console reads:
User Wants to Keep Dialog Open
Dialog is true
User Wants to Keep Dialog Open
Dialog is true
I understand why the dialog watch method is being called again, what I don't understand is why the confirm dialog is showing again. That code should never be executing after cancelling the confirm message the first time. The log message shows that there's no way that code should be executing again. Something must be happening behind the scenes that I don't realize.
Anyone have experience with preventing the v-dialog component from closing? Or any help with my two approaches? Thanks in advance.
It's a property on the dialog:
<v-dialog persistent
That will force them to keep it open unless you call the closure programatically by toggling the model.
I have an object I want to drag around the screen with the mouse in Processing. I set acquired to true on mouse down over the object, and to false on mouse up, thus:
void mousePressed() {
if (overThing()) {
acquired = true;
}
}
void mouseReleased() {
acquired = false;
}
I then query acquired in my update(), and drag the object if it is true.
void update() {
\\ other stuff...
if (acquired) {
\\ drag thing code ...
}
}
This all works fine in Processing. mouseReleased() gets called whether I release the mouse inside or outside the active window.
However, when I move the code to Chrome, using processing.js (v1.4.8), mouseReleased() is not called if I release the mouse outside the canvas (whether the mouse is still over the web page, or outside the browser window). So when I return the (now unclicked) mouse to the canvas, the object is still getting dragged around.
I tried including a test of mousePressed in update(), but that also returns true in these circumstances.
Any help on what I need to do to make mouse state changes outside the canvas visible with processing.js?
I don't know about Processing specifically, but releasing mouse buttons outside a widget is a common issue in GUI development.
I suspect that you have no way of knowing the precise time when the mouse is released outside the widget, but you do have two options:
Set acquired = false in mouseOut(), as #Kevin suggests.
I assume there is some type of mouseEntered() method in Processing, and also some way of knowing if the mouse button is currently pressed (either a global variable, or an event object passed to mouseEntered()). You can catch the mouse entered event, check if the mouse has been released, and set acquired = false then.
Like so:
void mouseEntered() {
if (mouse button is pressed) {
acquired = false;
}
}
Edit: From your comments, #Susan, it seems like there is a bug in processing.js, where mousePressed is not set to false if the mouse button is released outside the canvas. One thing pointing to this being a bug is that the mouse movement example on the processing website also shows this behaviour.
Depending upon how much control you have over the website this is going on, and how much effort you want to go to, you could fix the bug yourself by writing some javascript (separate from your processing code):
Define a mouseUp() event on the page <body>, to catch all mouse release events on the page.
In the mouseUp() event, check if the event comes from your Processing control. (There is probably an event object passed to the mouseUp() function, and you might have to give your Processing control an ID to identify it)
If the event doesn't come from your Processing control, then fire a mouseUp event yourself, on the Processing control. This should (hopefully!) trigger a mouse event inside your Processing code.
I'm not sure what Processing will make of the mouse (x,y) position being outside its control when it handles the event you send it. You might want to set a flag on the event object (assuming you can add extra data to the event object) to say "don't use the (x,y) position of this event - it's outside the control".
Edit2: It was easier than I thought! Here is the JavaScript code to detect the mouse being released outside of the Processing canvas and send the mouseReleased event to the canvas. I've tested it on the mouse movement example from the Processing website, and it fixes the bug.
It uses jQuery (although it could be re-written to not use jQuery), and it assumes your Processing canvas has the ID "processingCanvas":
$(':not(processingCanvas)').mouseup(function(){
Processing.getInstanceById('processingCanvas').mouseReleased();
});
To use this code, include it anywhere in your page (in a JavaScript file or in <script> tags) and make sure you have the jQuery library included before this code.
The Processing object allows JavaScript to call any functions defined in your Processing code. Here I've used it to call Processing's built in mouseReleased() function, but if you wanted to call a custom function to handle the mouse-released-outside state differently, then you could.
You should use the mouseOut() function to detect when the mouse leaves the sketch:
void mouseOut() {
acquired = false;
}
More info in the reference here.
I have an injected stylesheet that calls a popup with window...open() on two occasions. One when the user clicks an HTML button, and two, when a user clicks on a context menu item. To listen for the context menu item, I need to add a listener on the injected script like so
safari.self.addEventListener("message", messageCallBack, false); // Message comes from global.html when context menu item is clicked
And the following callback
function messageCallBack(msgEvent) {
...
window.open(...)
...
}
For some reason, the popup works when the button calls window.open, but NOT when the message callback calls window.open. I'm assuming it maybe have something to do with the window object.
I suspect this is due to restrictions on window.open designed to combat pop-up ads. This means it will only work in response to a click event.
To get around this, I would recommend you open the new window from your global page using the safari.application API:
safari.application.openBrowserWindow();
safari.application.activeBrowserWindow.activeTab.url = '...';
You can also open new tabs with:
safari.application.activeBrowserWindow.openTab('foreground').url = '...';
To achieve this, you may need to send a message from your injected script to the global page.
I am to create a view with a titlebar and a row of two buttons and a list.
When tapped on,each of the two buttons will make an ajax request to the server and update the list below.That is I will give each button a handler in which the store of the list will be fetched to have its proxy assigned with different params and then to call load() to refresh the list.
So my problem is : how to make the buttons and the list masked when the list is loading and unmasked when it finishes.
At first i wrap the buttons and the list with a container and masks it when the list is loading,but i can not unmask it when the list finish loading.I tried to listen the refresh event of the store,but not work.
Second,i tried to disable one button when the list is loading and enable it when the list finish loading.But i can not figure out how to make a call to enable the button when the mask of the list disappear.
How should i do ?
you will have to add load event of store before you call load() method and in load event's call back function you can unmask..just like below code
store.on({
load: {
fn: function( store ) {
//you can write code for unmask over here
},
scope: me,
single: true
}
});
store.load();
In addition to the 'back' button functioning as expected, I need to asynchronously invoke a function to update some db tables and refresh the UI.
Prior to making this post, I did some research and tried the following on this...
<h1 data-dojo-type="dojox.mobile.Heading" id="hdgSettings" data-dojo-props="label:'Settings',back:'Done',moveTo:'svStart',fixed:'top'"></h1>
dojo.connect(dijit.registry.byId("hdgSettings"), "onclick",
function() {
if (gblLoggerOn) WL.Logger.debug(">> hdgSettings(onclick) fired...");
loadTopLvlStats();
});
Since my heading doesn't have any other widgets than the 'back' button, I thought that attaching this event to it would solve my problem... it did nothing. So I changed it to this...
dojo.connect(dijit.registry.byId("hdgSettings")._body, "onclick",
function() {
if (gblLoggerOn) WL.Logger.debug(">> hdgSettings(onclick) fired...");
loadTopLvlStats();
});
As it turns out, the '._body' attribute must be shared by the Accordion widget that I just happen to use as my app's main UI component, and any attempt to interact w the Accordion rendered my entire app useless.
As a last resort, I guess I could simply forgo using the built-in 'back' button, and simply place my own tabBarButton on the heading to control my app's transition and event processing.
If the community suggests that I use my own tabBarButton, then so be it, however there has to be a way to cleanly attach an event to the built-in 'back' button support.
Thoughts?
The following should do the trick:
var backButton = dijit.registry.byId("hdgSettings").backButton;
if (backButton) {
dojo.connect(backButton, "onClick", function() { ... });
}
Remarks:
The code above should be executed via a dojo/ready call, to avoid using dijit's widget registry before it gets filled. See http://dojotoolkit.org/reference-guide/1.9/dojo/ready.html.
Note the capitalization of the event name: "onClick" (not "onclick").
Not knowing what Dojo version you use (please always include the Dojo version information when asking questions), I kept your pre-AMD syntax, which is not recommended with recent Dojo versions (1.8, 1.9). See http://dojotoolkit.org/documentation/tutorials/1.9/modern_dojo/ for details.