I want to call javafx functions from javascript on my HTML. I do the following (and it works correctly):
JSObject win = (JSObject) webEngine.executeScript("window");
win.setMember("app", new MyController(this.webEngine));
URL url = getClass().getResource("page1.html");
this.webEngine.load(url.toExternalForm());
Inside the page1.html i can call functions from MyController with JavaScript using the app object:
app.hello();
Then, in some moment I change the displaying page like this:
URL url = getClass().getResource("page2.html");
this.webEngine.load(url.toExternalForm());
The problem is that in page2.html i can't call any function from MyController. I've tried to recreate the object app (before and after the page change) but it doesn't work.
How can I maintain the interaction within JS and JavaFX?
I found the solution. After loading a new page, the DOM is replaced so the window object change too. The original JSObject object, that was created on the previous page, is pointing to a wrong window so JS can not call its methods. Is need to create a new JSObject object every time that the page is reloaded.
To recreate the new JSObject object you have to be sure that the page is completly loaded, so:
webEngine.getLoadWorker().stateProperty().addListener((obs, oldState, newState) -> {
if (newState == State.SUCCEEDED) {
JSObject win = (JSObject) webEngine.executeScript("window");
win.setMember("app", new MyController(this.webEngine));
}
});
URL url = getClass().getResource("page2.html");
webEngine.load(url.toExternalForm());
Related
Redux seems to be a very nice architecture for mobile app development. However, mobile apps have some features that are not common for web apps.
In my case, I would like to start long polling /monitoring location/tracking file system (any action that watches some external state) after the start of some particular screen and stop when the screen is closed.
Let's say we have a function, that can emit multiple events over time.
Stream<Event>monitor();
I would like to listen to the function only when some particular screen is active.
What is the best way of doing that?
Suppose you have 3 pages: 'PageHome.dart', 'Page1.dart', 'Page2.dart'.
Create another dart file 'GlobalVariables.dart', create a class gv inside this file, create static redux 'stores' for the three pages.
create static var strCurPage in gv.
suppose each page has a variable that is to be changed by an external event, declare them in gv as static var also.
Codes in GlobalVariables.dart:
import 'package:redux/redux.dart';
enum Actions {
Increment
}
// The reducer, which takes the previous count and increments it in response to an Increment action.
int reducerRedux(int intSomeInteger, dynamic action) {
if (action == Actions.Increment) {
return intSomeInteger + 1;
}
return intSomeInteger;
}
class gv {
static Store<int> storePageHome =
new Store<int>(reducerRedux, initialState: 0);
static Store<int> storePage1 =
new Store<int>(reducerRedux, initialState: 0);
static Store<int> storePage2 =
new Store<int>(reducerRedux, initialState: 0);
static String strCurPage = 'PageHome';
static String strPageHomeVar = 'PageHomeInitialContent';
static String strPage1Var = 'Page1InitialContent';
static String strPage2Var = 'Page2InitialContent';
}
Import 'GlobalVariables.dart' in all other dart files.
Before navigate to a new page, e.g. from PageHome to Page1, set:
gv.strCurPage = 'Page1';
Inside your monitor function, if an external event happens, say, change the values of the variables in Page1 and Page2 (But user currently navigating in Page1):
void thisFunctionCalledByExternalEvent(strPage1NewContent, strPage2NewContent) {
gv.strPage1Var = strPage1NewContent;
gv.strPage2Var = strPage2NewContent;
if (gv.strCurPage == 'Page1') {
// Dispatch storePage1 to refresh Page 1
storePage1.dispatch(Actions.Increment);
} else if (gv.strCurPage == 'Page2') {
// Dispatch storePage2 to refresh Page 2
storePage2.dispatch(Actions.Increment);
} else {
// Do not need to refresh page if user currently navigating other pages.
// so do nothing here
}
}
I don't know whether this is the best way, but using redux and GlobalVariables.dart, I can:
know which page the user is currently navigating.
change the content of a page even when the user is not at that page when the event fires. (But the content will be shown when the user navigate to that page later)
force the user to go to a specific page no matter which page the user is navigating, when the event fires.
I'm building an AIR application. Basically, what I'm looking to do is using navigateToUrl() to open a browser window, assign it a "name" and then, send variables to that newly opened window using the POST method.
EDIT : I need the window to be visible, this is why I absolutely need to use the navigateToUrl() function
I already know that I CAN'T DO something like this, that the AIR application will send the variables using the GET method...
var vars:URLVariables = new URLVariables();
vars.myVar = "Hello my friend";
var req:URLRequest = new URLRequest("http://example.com/my-page.php");
req.method = "POST":
req.data = vars;
navigateToURL(req);
Considering the amount of variables I have to send (multiline texts) I absolutely need to send my variables using the POST method else Internet Explorer is truncating the query string... Works fine in Firefox and Safari but unfortunately, we will always have (hope not!) to deal with IE..
So I was thinking something like this :
import flash.net.navigateToURL;
private var _timer:Timer;
protected function loadPage():void
{
var req:URLRequest = new URLRequest("http://example.com/my-page.php");
navigateToURL(req, "myPageName");
_timer = new Timer(3000, 1);
_timer.addEventListener(TimerEvent.TIMER, postVars);
_timer.start();
}
protected function postVars(event:TimerEvent):void
{
// I'm looking to send variables using the POST method to "myPageName"
// and possibly using URLVariables()??
_timer.stop();
}
Any idea Flex coders? THANKS!
I think what you're going to need to do is open up a page you have control over, then use ExternalInterface to inject the values into a hidden form and then execute the post operation in that page form.submit(), etc.
This can happen almost instantly and it will all appear very seamless to the end user.
I am trying to use the jQuery UI autocomplete feature in my web application. What I have set up is a page called SearchPreload.aspx. This page checks for a value (term) to come in along with another parameter. The page validates the values that are incoming, and then it pulls some data from the database and prints out a javascript array (ex: ["item1","item2"]) on the page. Code:
protected void Page_Load(object sender, EventArgs e)
{
string curVal;
string type ="";
if (Request.QueryString["term"] != null)
{
curVal = Request.QueryString["term"].ToString();
curVal = curVal.ToLower();
if (Request.QueryString["Type"] != null)
type = Request.QueryString["Type"].ToString();
SwitchType(type,curVal);
}
}
public string PreLoadStrings(List<string> PreLoadValues, string curVal)
{
StringBuilder sb = new StringBuilder();
if (PreLoadValues.Any())
{
sb.Append("[\"");
foreach (string str in PreLoadValues)
{
if (!string.IsNullOrEmpty(str))
{
if (str.ToLower().Contains(curVal))
sb.Append(str).Append("\",\"");
}
}
sb.Append("\"];");
Response.Write(sb.ToString());
return sb.ToString();
}
}
The db part is working fine and printing out the correct data on the screen of the page if I navigate to it via browser.
The jQuery ui autocomplete is written as follows:
$(".searchBox").autocomplete({
source: "SearchPreload.aspx?Type=rbChoice",
minLength: 1
});
Now if my understanding is correct, every time I type in the search box, it should act as a keypress and fire my source to limit the data correct? When I through a debug statement in SearchPreload.aspx code behind, it appears that the page is not being hit at all.
If I wrap the autocomplete function in a .keypress function, then I get into the search preload page but still I do not get any results. I just want to show the results under the search box just like the default functionality example on the jQuery website. What am I doing wrong?
autocomplete will NOT display suggestions if the JSON returned by the server is invalid. So copy the following URL (or the returned JSON data) and paste it on JSONLint. See if your JSON is valid.
http://yourwebsite.com/path/to/Searchpreload.aspx?Type=rbChoice&term=Something
PS: I do not see that you're calling the PreLoadStrings function. I hope this is normal.
A couple of things to check.
Make sure that the path to the page is correct. If you are at http://mysite.com/subfolder/PageWithAutoComplete.aspx, and your searchpreload.aspx page is in another directory such as http://mysite.com/anotherFolder/searchpreload.aspx the url that you are using as the source would be incorrect, it would need to be
source: "/anotherFolder/Searchpreload.aspx?Type=rbChoice"
One other thing that you could try is to make the method that you are calling a page method on the searchpreload.aspx page. Typically when working with javascript, I try to use page methods to handle ajax reqeusts and send back it's data. More on page methods can be found here: http://www.singingeels.com/Articles/Using_Page_Methods_in_ASPNET_AJAX.aspx
HTH.
I'm building a Flex app which requires me to download files.
I have the following code:
public function execute(event:CairngormEvent) : void
{
var evt:StemDownloadEvent = event as StemDownloadEvent;
var req:URLRequest = new URLRequest(evt.data.file_path);
var localRef:FileReference = new FileReference();
localRef.addEventListener(Event.OPEN, _open);
localRef.addEventListener(ProgressEvent.PROGRESS, _progress);
localRef.addEventListener(Event.COMPLETE, _complete);
localRef.addEventListener(Event.CANCEL, _cancel);
localRef.addEventListener(Event.SELECT, _select);
localRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _securityError);
localRef.addEventListener(IOErrorEvent.IO_ERROR, _ioError);
try {
localRef.download(req);
} catch (e:Error) {
SoundRoom.logger.log(e);
}
}
As you can see, I hooked up every possible event listener as well.
When this executes, I get the browse window, and am able to select a location, and click save. After that, nothing happens.
I have each event handler hooked up to my logger, and not a single one is being called! Is there something missing here?
The problem seems to be with my command being destroyed before this could finish.
For a proof of concept, I set my localRef variable to be static instead of an instance variable, and everything went through successfully! I guess Cairngorm commands kill themselves asap!
I used Flash player 10, and Flex SDK 3.4. The code as followings:
// Following comes callbacks
function imageLoadOpenCallback(evt:Event):void
{
trace("in--open");
}
function imageLoadCompleteCallback(evt:Event):void
{
trace("in--load");
var fr:FileReference = evt.target as FileReference;
trace(fr.data);
}
function imageLoadErrorCallback(evt:IOErrorEvent):void
{
trace("in--ioerror");
}
function imageSelectCancelCallback(evt:Event):void
{
trace("in cancel");
}
function imageSelectCallback(evt:Event):void
{
trace("in -- select");
for (var i:int=0; i<frl.fileList.length; i++)
{
frl.fileList[i].addEventListener(Event.OPEN, imageLoadOpenCallback);
frl.fileList[i].addEventListener(Event.COMPLETE, imageLoadCompleteCallback);
frl.fileList[i].addEventListener(IOErrorEvent.IO_ERROR, imageLoadErrorCallback);
frl.fileList[i].load();
trace(frl.fileList[i]);
trace(frl.fileList[i].creationDate);
trace(frl.fileList[i].creator);
trace(frl.fileList[i].data);
trace(frl.fileList[i].name);
}
}
// Following comes UI handlers
function onAddPictures():void
{
var imageFilter:FileFilter = new FileFilter("Images", "*.jpg;*.png");
frl.addEventListener(Event.SELECT, imageSelectCallback);
frl.addEventListener(Event.CANCEL, imageSelectCancelCallback);
frl.browse([imageFilter]);
}
Only the imageSelectCancelCallback handler get called when I select some files in the dialog. But no load/open/io_error handler get called at all. I have Google some code example, in which it used FileReference instead of FileReferenceList. I don't know the reason, could you please help me?
In Air the fileReference objects in fileReferenceList do not fire the complete event when doing fileList[i].load(). In a Flex project it works fine. Adobe has not responded to bug reports on this appropriately.
Make sure in your compiler settings for flex, that you have at least 10.0.0 for "Use a specific version".
The main reason to use FileReferenceList instead of FileReference would be if you need to upload multiple files at once. If you only want to allow uploading one file at once, simply use FileReference.
Some clarification: imageSelectCallback(), and NOT imageSelectCancelCallback(), should get called when you select some files in the file browser AND click OK. imageSelectCancelCallback() is only called when you click Cancel.
Other than that, I never used the load() API, but I did use the upload(URLRequest) API. I am not sure what's your use case, but if you need to upload an image to a server, you should use the upload() method.
Speaking of upload events, I experienced some reliability issues when listening to Event.COMPLETE events, so I actually got better results listening to DataEvent.UPLOAD_COMPLETE_DATA.