Is it possible to call Dart code generated with dartdevc from JavaScript? - javascript

I have a bunch of Dart libraries that a customer wants to call from JavaScript. Is it possible to call functions created with dartdevc from JS?

If you only want to call functions, you can probably do that in this way. Although I only know it's works for functions, probably not for whole class. I am also not sure about dartdevc support, but dart2js should be able to do this:
import 'dart:js' as js;
main() {
js.context['methodFromDart'] = doMyStuff;
}
void doMyStuff(String text) => print(text);
And then in you Javascript you are free to do:
methodFromDart("Hello world to Dart!");

Related

Calling a Blazor method From JavaScript

I'm experimenting with Blazor in Visual Studio, specifically with calling Blazor code from JavaScript. I'm reasonably confident that I've got all the right libraries in place. However, when I attempt to call my Blazor method with invokeMethodAsync, I get the message "no .net call dispatcher has been set". In my Index.Html file, I have this:
<script>
DotNet.invokeMethodAsync("BlazorFour.App", "HelloYou").then(data => alert(data), reason => alert(reason));
</script>
(It's the alert(reason) that generates the error message)
I've added a class file to my Blazor project and it contains this:
using Microsoft.JSInterop;
using System.Threading.Tasks;
public class HelloWorld
{
[JSInvokable]
public static Task<string> HelloYou()
{
return Task.FromResult("Hello, ");
}
}
I've used all the templates in Visual Studio and the dotnet -new blazor commandline utility to create my start points but get the same message in all of the projects. It's seems likely to me that I'm missing something fundamental here.
Peter Vogel:
It would be great if you could call Blazor C# methods from your JavaScript code. Right now, that's not quite possible: Simply calling Blazor C# from JavaScript won't work (you'll get a message about a call dispatcher not being available).
What you can do, however, is once your Blazor code is running, call JavaScript code from your C# code. Once you've done that, your JavaScript code can, in turn, call Blazor code.
Hope this solves the problem...
I'm using server-side-blazor
I was getting js errors
No .NET call dispatcher has been set
So yep .. looks like Blazor wasn't initialized..
Not keen on a timeout
.. seems hacky and gives a laggy UI
Not keen on 'call JavaScript code from your C# code. Once you've done that, your JavaScript code can, in turn, call Blazor code.'
.. again seems hacky
This works for me ..
async function myBlazoryFunctionThing() {
// see https://sourcegraph.com/github.com/aspnet/AspNetCore#bd65275148abc9b07a3b59797a88d485341152bf/-/blob/src/Components/Web.JS/src/Boot.Server.ts#L41:9
await window.Blazor.reconnect();
..now it's safe to do my stuff
}
it 'seems' that Blazor.reconnect() will re-use the existing connection (if there is one)
...so it's not actually 're-connecting' (so 'seems' not much overhead ;-))
I tried a setTimeout (5000 ms delay) and it worked for me.(of course it is not needed to use the setTimeout every time, just the first time).
e.g. setTimeout( DotNet.invokeMethod(...), 5000);
I guess this is a timing issue, not everything is loaded/initialized.
Have you tried putting the js code in a button onclick event?
using Microsoft.JSInterop;
[Inject] protected IJSRuntime JSRuntime { get; set; }
From your blazor function call this function from this method
await JSRuntime.InvokeAsync<object>("fnToJavascriptCall", DotNetObjectReference.Create(this));
Create this function in blazor file
[JSInvokable]
public async Task fnToCallFromJavascript(int param1, int param2)
{
//Do some stuff
StateHasChanged();
}
In your javascript file
var fnToJavascriptCall = function (param1,currentInstance)
{
//Do your stuff
currentInstance.invokeMethodAsync("fnToCallFromJavascript", param1, param2);
}
The No .NET call dispatcher has been set error can be received when the JavaScript interop is used at the wrong time. Have a look at this StackOverflow question.

How to expose HtmlAgilityPack.CssSelectors into ClearScript

Context: Azure, C#, ClearScript, JavaScript, HtmlAgilityPack, HtmlAgilityPack.CssSelectors
I do this a lot: add scripting to C# apps using ClearScript. Ordinarily this just works.
...
using Microsoft.ClearScript;
using Microsoft.ClearScript.Windows;
...
class Program
{
static JScriptEngine JSengine = null;
...
JSengine = new JScriptEngine(WindowsScriptEngineFlags.EnableDebugging | WindowsScriptEngineFlags.EnableJITDebugging);
....
JSengine.AddHostType("CSHtmlDocument", typeof(HtmlAgilityPack.HtmlDocument));
...
and then later, in the JavaScript code itself, there are things like
...
var hap = new CSHtmlDocument();
hap.LoadHtml(html);
...
So this is going really well until I add HtmlAgilityPack.CssSelectors into the mix. On the C# side, this adds extra methods to the HtmlDocument object, specifically QuerySelector and QuerySelectorAll. They're visible on the C# side. However, on the JavaScript side they're not and code such as
...
var selection = hap.QuerySelector(".reduced");
...
throws an error and looking at the object from a debugging session in Visual Studio 2015 shows no QuerySelector method in the hap var.
So what's the story? Is it a ClearScript issue or a C# issue? And what do I do about it? I'm quite happy to write a wrapper class, I was just expecting everything to work as before.
These new methods are most likely extension methods defined by a particular class. To make them accessible from script code, you must expose that class to the script engine.
EDIT: I'm not familiar with them, but it looks like the methods you're talking about are provided by the HapCssExtensionMethods class (or something very similar). To expose the methods, simply expose the class:
// C#
JSengine.AddHostType(typeof(HapCssExtensionMethods));
Once you've done that, your JavaScript sample above should work as is.

IPython: Adding Javascript scripts to IPython notebook

As a part of a project, I need to embedd some javascripts inside an IPython module.
This is what I want to do:
from IPython.display import display,Javascript
Javascript('echo("sdfds");',lib='/home/student/Gl.js')
My Gl.js looks like this
function echo(a){
alert(a);
}
Is there some way so that I can embed "Gl.js" and other such external scripts inside the notebook, such that I dont have to include them as 'lib' argument everytime I try to execute some Javascript code which requires to that library.
As a very short-term solution, you can make use of the IPython display() and HTML() functions to inject some JavaScript into the page.
from IPython.display import display, HTML
js = "<script>alert('Hello World!');</script>"
display(HTML(js))
Although I do not recommend this over the official custom.js method, I do sometimes find it useful to quickly test something or to dynamically generate a small JavaScript snippet.
Embedding D3 in an IPython Notebook
https://blog.thedataincubator.com/2015/08/embedding-d3-in-an-ipython-notebook/
To summarize the code.
Import the script:
%%javascript
require.config({
paths: {
d3: '//cdnjs.cloudflare.com/ajax/libs/d3/3.4.8/d3.min'
}
});
Add an element like this:
%%javascript
element.append("<div id='chart1'></div>");
Or this:
from IPython.display import Javascript
#runs arbitrary javascript, client-side
Javascript("""
window.vizObj={};
""".format(df.to_json()))
IPython Notebook: Javascript/Python Bi-directional Communication
http://jakevdp.github.io/blog/2013/06/01/ipython-notebook-javascript-python-communication/
A more extensive post explaining how to access Python variables in JavaScript and vice versa.
I've been fighting with this problem for several days now, here's something that looks like it works; buyer beware though, this is a minimal working solution and it's neither pretty nor optimal - a nicer solution would be very welcome!
First, in .ipython/<profile>/static/custom/myScript.js, we do some require.js magic:
define(function(){
var foo = function(){
console.log('bar');
}
return {
foo : foo
}
});
Copy this pattern for as many functions as you like. Then, in .ipython/<profile>/static/custom/custom.js, drag those out into something persistent:
$([IPython.events]).on('notebook_loaded.Notebook', function(){
require(['custom/myScript'], function(custom){
window.foo = custom.foo;
} );
});
Yes, I am a horrible person for throwing stuff on the window object, namespace things as you deem appropriate. But now in the notebook, a cell like
%%javascript
foo();
should do exactly what it looks like it should, without the user having to explicitly import your JS. I would love to see a simpler solution for this (plz devs can we plz have $.getScript('/static/custom/util.js'); in custom.js to load up a bunch of global JS functions) - but this is the best I've got for now. This singing and dancing aside, HUGE ups to the IPython notebook team, this is an awesome platform!
Not out of the box by installing a package, at least for now.
The way to do it is to use custom.js and jQuery getScript to inject the js into the notebook.
I explicitly stay vague on how to do it, as it is a dev feature changing from time to time.
What you should know is that the static folder in user profile is merged with webserver static assets allowing you to access any file that are in this folder by asking for the right url.
Also this question has been asked a few hours ago on IPython weekly video "lab meeting" broadcasted live and disponible on youtube (you might have a longer answer), I've opened discussion with the author of the question here
For some reason, I have problems with IPython.display.Javascript. Here is my alternative, which can handle both importing external .js files and running custom code:
from IPython.display import display, HTML
def javascript(*st,file=None):
if len(st) == 1 and file is None:
s = st[0]
elif len(st) == 0 and file is not None:
s = open(file).read()
else:
raise ValueError('Pass either a string or file=.')
display(HTML("<script type='text/javascript'>" + s + "</script>"))
Usage is as follows:
javascript('alert("hi")')
javascript(file='Gl.js')
javascript('echo("sdfds")')
You can use IJavascript (a Javascript kernel for Jupyter notebooks).
I was interested in calling JavaScript from a Jupyter code (Python) cell to process strings, and have the processed string output in the (same) code cell output; thanks to Inject/execute JS code to IPython notebook and forbid its further execution on page reload and Why cannot python call Javascript() from within a python function? now I have this example:
from IPython.display import display, Javascript, Markdown as md, HTML
def js_convert_str_html(instring_str):
js_convert = """
<div id="_my_special_div"></div>
<script>
var myinputstring = '{0}';
function do_convert_str_html(instr) {{
return instr.toUpperCase();
}}
document.getElementById("_my_special_div").textContent = do_convert_str_html(myinputstring);
</script>
""".format(instring_str)
return HTML(js_convert)
jsobj = js_convert_str_html("hello world")
display(jsobj)
Note that the JavaScript-processed string does not get returned to Python per se; rather, the JavaScript itself creates its own div, and adds the result of the string conversion to it.

JSObject-like stuff in ActionScript 3?

I would like to ask if there is a liveconnect equivalent for ActionScript 3. I understand that there is the ExternalInterface class inside AS3 but it only supports calling a method by name. The really cool thing about Java and LiveConnect is that you can do something like
function jsFunc(name) = {
this.name = name;
this.talk = function(){
alert('hello world my name is ' + this.name);
}
}
javaapplet.function(new jsFunc("bob"));
The above approaches pseudo code since I never tested it but I've seen it in action. In AS3, while I am able to pass in an instance of JavaScript "object" into AS, it is often converted into an ActionScript Object instance which does away with all the functions as far as I'm aware.
I saw an implementation of JSInterface but I don't think it does specifically that. Is there any way to make OO like javascript work with ActionScript 3?
Try this library on Google code:
http://code.google.com/p/jsobject/
ExternalInterface.call("f = function() { alert('Is this like live connect?'); }");
Actually the main usage scenario is to have JS "objects" interacting with the Flex SWF application. Therefore when the JS "object" wants to say wait for something happening in the SWF object, it will put in a "this" with a callback.
After researching, the way I used to accomplish this is via the Flex Ajax bridge. It may not be a direct answer to the way I phrased the question but it was sufficient for my needs.
Basically what I do is via FABridge, after initializing, I'll attach event listeners to the object.
// JS
FlexApp.addEventListeners('flexDidSomething', this.doSomething().bind(this)); //using mootools;
and in Flex, the main application itself
// AS
dispatchEvent(new CustomCreatedEvent(param1, param2));
And inside the JS function I'll access the get methods of the event object to retrieve the params.
There's tight coupling in that sense but it works at least for what I need.
Hope this is helpful!
JSInterface designed exactly for such things.

Call a JavaScript function from C++

I have a CDHTMLDialog, with which I have 2 HTML pages and a .js file with a few fairly simple functions.
I would like to be able to call one of the JS functions from my program with a simple data type passed with it. e.g. MyFunc(int). Nothing needs to be returned.
I would appreciate any guidance on how I go about this,
thanks.
Edit: Thanks to CR for his answer, and everyone else who submitted there ideas too.
Something a little like this worked in the end (stripped a little error handling from it for clarity):
void callJavaScriptFunc(int Fruit)
{
HRESULT hRes;
CString FuncStr;
CString LangStr = "javascript";
VARIANT vEmpty = {0};
CComPtr<IHTMLDocument2> HTML2Doc;
CComPtr<IHTMLWindow2> HTML2Wind;
hRes = GetDHtmlDocument(&HTML2Doc);
hRes = HTML2Doc->get_parentWindow(&HTML2Wind);
if( Fruit > 0 )
{
FuncStr = "myFunc(808)"; // Javascript parameters can be used
hRes = HTML2Wind->execScript(FuncStr.AllocSysString(), LangStr.AllocSysString(), &vEmpty);
}
}
Easiest approach would be to use the execScript() method in the IHTMLWindow2 interface.
So you could get the IHTMLDocument2 interface from your CDHTMLDialog by calling GetDHtmlDocument, then get the parentWindow from IHTMLDocument2. The parent window will have the IHTMLWindow2 interface that supports execScript().
There might be an easier way to get the IHTMLWindow2 interface from your CDHTMLDialog but I'm used to working at a lower level.
the SpiderMonkey library can "Call a JavaScript function from C++", please refer to
http://egachine.berlios.de/embedding-sm-best-practice/ar01s02.html#id2464522
but in your case, maybe this is not the answer.
To give you a hint - javascript injection in server-side-technologies is usually performed through bulk-load at startup (GWT) or injected when the HTML is generated and served each post-back (ASP.NET).
The important point of both approaches is that they inject the javascript calls somewhere in the page (or in a separated .js file linked in the HTML in case of GWT) when generating the HTML page.
Even if you're on win development (looks like it since you're on MFCs) it might be the case that you have to insert your js method call in the HTML and then load (or reload if you wish to interact with the html from your MFC app) the HTML file in your CHTMLDialog.
I don't see any other way of achieving this (maybe I am just not aware of some suitable out-of-the-box functionality) other than editing your HTML and (re)loading it - which is pretty convenient and workable if you have to call your js method once off or just inject some kind of event-handling logic.
Might be a bit of a pain if you have to interact with the page from your MFC app. In this case you have to re-generate your HTML and reload it in your CHTMLDialog.
Either way you can simply have some kind of placeholder in your HTML file, look for that and replace with your javascript code, then load the page in your CHTMLDialog:
onclick="__my_Javascript_Call_HERE__"

Categories

Resources