When I call a javascript function like this inside a WKWebView to post a message to iOS swift:
$('#button').on('click', function() {
window.webkit.handler.postMessage('Message from web pages.');
});
the current web page is always been reloaded. Is there a way to prevent it?
The correct JavaScript call is:
window.webkit.messageHandlers.<your-handler>.postMessage('Message from web pages.');
You need to replace <your-handler> with the namespace of the handler you defined in your WKWebView, e.g
[_webView.configuration.controller addScriptMessageHandler:self name:#"Ti"];
Related
I have a simple Titanium app which opens a webview, and loads a URL. I want the links to open in the default browser, not the app.
I have some jQuery code which adds a click event to all links in the page.
<script>
jQuery('a').click(function() {
console.log("Handler for .click() called for URL: " + this.href);
Ti.App.fireEvent('ynOpenURL', {url: this.href });
});
In the app.js file I have:
var win = Ti.UI.createWindow();
var mywebview = Ti.UI.createWebView({
url : 'http://xxxx.xxxxx.com/',
enableZoomControls: false
});
win.add(mywebview);
win.open();
Ti.App.addEventListener('ynOpenURL', function(e) {
Ti.API.info('yyyyyy');
Ti.API.info(e.url);
if (Ti.Platform.canOpenURL(e.url)){
Ti.Platform.openURL(e.url);
} else {
alert("Cannot open URL");
}
When I run the app on my Android (4.4) the web page loads correctly.
When I click a link on the phone I get the following in the console:
Handler for .click() called for URL: http://xxx.xxxxx.xxx/
Uncaught TypeError: Cannot read property 'App' of undefined (xxxx)
None of the Titanium console events are logged, only the javascript events in the webpage.
As you mentioned that the webview is loading remote url. So Ti.* or Titanium.* are not available at your remote server.
What you can do is :
Create a html file within the app and load the data via ajax and use fireEvent.
Load the data via titanium http client and use Ti.Platform.openURL accordingly.
Edit : Quote from Titanium WebView Docs
Remote Scripts
Scripts downloaded from remote web servers cannot access the Titanium namespace.
To interact with remote content, wait until the content is loaded, then use the evalJS method to execute a JavaScript expression inside the web view and retrieve the value of an expression.
I have been able to get content out of WebView using javascript and loadUrl() method having specified an interface thats called from javascript string that is injected into WebView.The problem is that this only works for me when the loadUrl() method is present in onPageFinished() method in the WebView client. What I want to do is I want to get the content out of the WebView (with the content already loaded). The WebView is in an activity instrumentation test case and I can for instance use findAll() method and that works fine. For some reason I can not use loadUrl() and get the desired behaviour (which is injecting javascript and getting content out of the WebView with a help of an interface).
PLease help.
Thanks
Pawel
EDIT:
Just adding code to show what I am doing exactly:
Yes I understand that but my problem is that I am trying to do it within a test case this way:
public void testWebView() throws Exception {
solo.sleep(3000); // wait for views to load on the screen
WebView a=null;
ArrayList<View> views = solo.getCurrentViews(); // I am using solo object to get views for the screen currently loaded
for(View s:views)
{
if (s instanceof WebView)
{
a = (WebView)s; // this is where I get my WebView
}
}
Instrumentation inst = getInstrumentation();
inst.runOnMainSync(new Runnable()
{
public void run()
{
int d =a.findAll("something"); // this method runs fine on the object and i get the desired result
WebSettings settings = a.getSettings();
settings.setJavaScriptEnabled(true);
a.loadUrl("javascript:document.location = document.getElementById('google').getAttribute('href')"); // this javascript is never executed and that is my problem
}
});
}
You can inject javascript in a loaded page much the same way you can do it in desktop browsers - via inline javascript entered into navigation bar.
Bind some Java object so that it can be called from Javascript with WebView:
addJavascriptInterface(javaObjectExposed, "JSname")
Force execute javascript within an existing page by
WebView.loadUrl("javascript:window.JSname.passData("some data from page");");
I was develop some Cocoa application with WebView. Now I can evaluate javascript to HTML file by using evaluateWebScript:
But I need to receive an alert() event from javascript to display in Cocoa's NSAlertSheet.
How to do with cocoa development ?
You need to set an object as the WebUIDelegate of the WebView (using the setUIDelegate: method) and in that object implement the ‑webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame: delegate method. This method will be called when a page loaded into the WebView calls the alert() JavaScript function.
In your implementation of the delegate method, you should display an alert. The alert should:
display the exact message string that is passed in to the method
indicate that the message comes from JavaScript
contain only one button, an OK button
Here is a basic example:
- (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message
{
NSAlert* jsAlert = [NSAlert alertWithMessageText:#"JavaScript"
defaultButton:#"OK"
alternateButton:nil
otherButton:nil
informativeTextWithFormat:#"%#", message];
[jsAlert beginSheetModalForWindow:sender.window modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
}
You can try to override JavaScript alert function on window. In your custom alert you can redirect to predefined url, e.g. app://alert/something%32is%32wrong. That kind of redirect can be handled by UIWebView through webView:shouldLoadRequest:.
PS: I didn't try it :)
I am developing a web app that is being displayed in a UIWebView. The app is loaded locally, i.e, not from a web server. I am communicating from Javascript to ObjC via the shouldStartLoadWithRequest: method in the UIWebViewDelegate protocol.
The last thing I need is to be able to call Javascript functions from ObjC without any page reloads. I hope this is possible.
Well, you can call
-[UIWebView stringByEvaluatingJavaScriptFromString:]
whenever you like, not just in response to a delegate method.
You can call any javascript function in your webview by simply using the stringByEvaluatingJavaScriptFromString method on your webview after you've loaded the webview:
[self.myWebView stringByEvaluatingJavaScriptFromString:#"myJavaScriptFunction(123.0)"];
You don't need to reload the webview to send this message (just don't release the webview before you're done).
Could't you just do this by doing a "loadRequest", and passing it an NSURL with contents like like:
javascript:myFunction("MyParameter");
It should call your function, but not reload the page.
One can use JavaScriptCore framework to run JavaScript code from Objective-C.
#import <JavaScriptCore/JavaScriptCore.h>
...
JSContext *context = [[JSContext alloc] init];
[context evaluateScript: #"function greet(name){ return 'Hello, ' + name; }"];
JSValue *function = context[#"greet"];
JSValue* result = [function callWithArguments:#[#"World"]];
[result toString]; // -> Hello, World
Here is a demo:
https://github.com/evgenyneu/ios-javascriptcore-demo
I'm got a custom webview setup which is working pretty well, but I'd like to be able to either:
1, change the url hash without the webview reloading the page (it would lose the state of my js app)
2, call some js that sits within my web page from within android. I can't change any JS within the site, unfortunately, so can't custom write any js to put on the site especially for the job, the only stuff I have control over is the Android app.
Can anyone think of a way of doing either of these?
Thanks in advance.
M
Or if you just want to change the hash, you can use:
view.loadUrl("javascript:location.hash=\"#" +fragment+"\"");
For #2, your Activity can invoke JavaScript methods. All you have to do is call the loadUrl method with the appropriate JavaScript call:
mWebView.loadUrl("javascript:wave()");
From:
http://developer.android.com/resources/articles/using-webviews.html
I know this question is old but this is what works for me in Android 4.4:
String fragment = "#test"
mWebView.evaluateJavascript("location.hash=\"" + fragment + "\";", new ValueCallback<String>() {
#Override
public void onReceiveValue(String value) {
// Yes, I like to log data :-)
Log.d("MyApp", "onReceiveValue(value): " + value);
}
});