Android lets you add a Javascript Interface, that will let you use "window.interfacename.myfunction()" to call a function in the Java program.
Is there any similar feature that allows a PyGTK with embedded webkit browser to have similar functionality, to call a specific Python function from Javascript?
You can do it in C using the JavaScriptCore library that comes with WebKit. I don't know any examples in PyGTK, but I assume that JavaScriptCore is available through GObject Introspection.
I ended up adding a handler for special urls. I overrode the webkit with:
webview.connect("navigation-policy-decision-requested", self.webkitGo)
where self.webkitGo is the name of the function: def webkitGo(self, view, frame, net_req, nav_act, pol_dec):
In this function, you can receive the url data from net_req.get_uri() and decide what to do with it, and return true to not do the default behavior.
Related
I am building a Cordova application for all major operating systems (iOS, macOS, Android and Windows).
I wrote a native Plugin (WinRT) in C++/CLI to call some native functions, this Plugin uses delegates to asynchronously give back results.
I also wrote a test application in C# that allows me to easily test the C++/CLI code without having to compile the whole Cordova project.
I am able to bind to the C++/CLI delegate without any issue in C#, but I am not able to do so in Javascript.
C# Way (Works like a charm):
myCppClass.log += (string logString) =>
{
Debug.WriteLine(logString);
};
Javascript Way (Does not work at all):
myCppClass.addEventListener("log", function (msg) {
console.log(msg);
});
I got the Javascript way from: https://msdn.microsoft.com/en-us/library/hh779077.aspx
Does anyone know how to bind to C++/CLI delegates in Javascript?
Thanks
Take a look once again on the https://msdn.microsoft.com/en-us/library/hh779077.aspx#Anchor_4 sample.
Have you tried this way?
var instance = new MyCppClass();
instance.addEventListener("log", function (e) {
console.log(e.msg);
});
With Qt 5.5, using the Minibrowser example they provide, it uses something different than QWebView widget. Instead, it uses QML and a QtWebView module. When you look in Javascript's navigator.appVersion, it lets you know that QWebView loads a custom AppleWebKit/538.1 (a thing shipped with Qt5.5), while QtWebView (note the difference) loads the native core OS AppleWebKit/601.1.56. This is confirmed because when I load Safari on my OSX (El Capitan version), it says 601.1.56.
The problem, however, is how can my Javascript functions in Minibrowser call C++ functions on the backend to do more powerful stuff? When I was using the QWebView widget, I was able to use the C++ webkit bridge that let me inject into the DOM my C++ object and therefore could call my C++ code. I'm not seeing any technique documented for how to do this with the QML-based Minibrowser example that uses QtWebView. What's the technique?
EDIT: Oh, and to clarify, I'm not calling remote web pages with this, via a web server. I'm just calling stuff through file://. In other words, I'm using the rich webkit interface to give me a super powerful GUI that goes way beyond what the Qt widgets and QML can provide for me.
I found the answer. Basically, in Qt5.5, I'm diving into experimental land with QtWebView. The class methods are largely undocumented and may change in the future.
For now, the only technique is message passing, not native C++ class method invocation like you could use in the QWebView C++ Bridge. The QWebView C++ Bridge only works with QWebView widgets, not the QtWebView QML. So, you do this message passing with navigator.qt.postMessage() API from your Javascript to your QML, and then QML can call C++. In order to get that extra functionality, you'll need to do a few steps. Here's an example:
Invoke C++ method from webviews Javascript
This is blogged a little here:
http://rschroll.github.io/beru/2013/08/21/qtwebview.experimental.html
As you can see from the example, you have to add these imports to your main.qml:
import QtWebKit 3.0
import QtWebKit.experimental 1.0
Then, in your WebView{} section, you have to add this line:
experimental.preferences.navigatorQtObjectEnabled: true
At that point, you can call navigator.qt.postMessage("call foo in C++"); to send a message to the QML, which you can then pick up inside your WebView{} section with:
experimental.onMessageReceived: { ...do something here in the QML... }
Your QML can then pass a message right back to the Javascript with:
experimental.postMessage("okay, I called foo in C++")
And then in your Javascript you can add an event listener like so:
navigator.qt.onmessage = function(ev) {
$('BODY').prepend(ev.data); // since console.log() is not possible
}
As for how to get your QML to call C++, here's an example:
https://stackoverflow.com/a/17881019/105539
EDIT: After more experimentation in Qt 5.5 with QtWebView, it appears fairly flaky in the following respects. I don't recommend it in 5.5 -- it's not ready for primetime. In Qt 5.5, you're better off using the QWebView widget for now and then migrate to QtWebEngine when the next version of Qt comes out (Qt 5.6, 5.7?).
By default, it gives you a rightclick context menu you may not want. Interestingly, you can turn it off if you import the experimental library and then set this property in your QML: experimental.preferences.navigatorQtObjectEnabled: true.
By default, HTML5 postMessage() API (the one native with HTML5) doesn't appear to work unless you enable experimental.preferences.navigatorQtObjectEnabled: true.
When you enable experimental.preferences.navigatorQtObjectEnabled: true, the scrollbars disappear if you enabled them on some HTML page elements, the checkboxes and radio buttons look extremely funky, and popdown select listboxes stopped working.
When you doubleclick a page, it zooms it.
Is it possible to use Javascript in flash. For example, as a simple test I am trying to use Javascript's alert method when a button is clicked.
I am using AS3. Is it possible?
Like Marty mentioned, you can use the ExternalInterface class to execute a Javascript. Your options are to execute a function embedded in the (html) page code and create one from scratch. Because alert is a default function you can use its name as the first parameter for the call method (of ExternalInterface) and the string as the 2nd one.
If you provide a single parameter, you might wanna write a function instead to execute (or return) something.
btn.addEventListener(MouseEvent.CLICK, btnClicked);
function btnClicked(e:MouseEvent):void {
ExternalInterface.call("alert","something");
// or
ExternalInterface.call("function(){alert('something');}");
}
No.. Flash uses ActionScript 3.
You can call a JavaScript function on the same page as an embedded SWF using ActionScript's ExternalInterface class, though.
A quick demo on implementing ExternalInterface:
if(ExternalInterface.available)
ExternalInterface.call("alert", "Hello!");
Tip: ExternalInterface calls will not work locally unless you add the location of the project in this security settings panel and check "always allow".
we have developed an Intranet Management Application with Silverlight 4. We have been asked to add the functionality to call a remote desktop tool which is installed on clients using the Intranet SL App. In an earlier version of the tool written in ASP.NET we just added a Javascript function to the aspx page like this:
function RunShellCommand()
{
var launcher = new ActiveXObject("WScript.Shell");
launcher.Run("mstsc.exe");
}
and called it from ASP.NET.
Now it's clear that SL4 is running in a sandbox and that I cant use the AutomationFactory to create a WScript.Shell object (out of browser mode is not an option).
I thought I could circle around the problem by, again, adding the RunShellCommand javascript method in the aspx page where the SL4 control is hosted and call it via
HtmlPage.RegisterScriptableObject("Page", this);
HtmlPage.Window.Invoke("RunShellCommand", "dummydata");
from my ViewModel. When I run the Application the debugger just skips the RegisterScriptableObject method and quits. Nothing happens.
My question is if am doing something wrong or if this just wont work this way.
Is it possible that I cant do a RegisterScriptableObject from a viewmodel?
EDIT: When I explicitly put a try, catch block around the two methods I get an ArgumentException from the first method stating that the current instance has no scriptable members. When I delete the first method and only run the Invoke, I get a browser error stating that the automation server cant create the object. So is there really no way (except OOB mode) to do this?
Yes, the explanation is correct: you should add at least one method with the ScriptableMember attribute in order that you can use the RegisterScriptableObjectmethod. But it is used only for calling C#-methods from JavaScript.
As far as I see, you want to do the opposite: to call JavaScript code from the Silverlight application. Then you need only one line:
HtmlPage.Window.Invoke("RunShellCommand");
The error automation server cant create the object has nothing to do with Silverlight. I'm sure that if you call the JS function directly - the error will remain.
According to the internet, the reason might be not installed Microsoft Windows Script. Or it is because of security restrictions of the browser.
i need to invoke QTP from a javascript without using ActiveXObject. can anybody guide me how to proceed with this?
Thanks,
Ramya.
Java Script programming cannot be done in QTP but it will
support Java script. We can make a DLL by using Java script
and add that to QTP and there after you can use that.
Regards,
Mannusanghi
QTP supplies a COM interface for automation, in order to create the automation object you need to use ActiveXObject (see this article on using OLE Automation in Javascript).
Why do you want to avoid using ActiveXObject?
Any particular reason why you don't want to use the ActiveXObject?
Anyhow, if you're running JavaScript through the Windows Script Host, instead of the way mentioned in the manual:
var qtApp = new ActiveXObject("QuickTest.Application");
...you can do this:
var qtApp = WScript.CreateObject("QuickTest.Application");
qtApp.Launch();
qtApp.Visible = true;
But you be might using ActiveX behind the scenes there anyway, I'm not entirely sure.