Using a Javascript Function from Typescript - javascript

I am trying to build a nice windows phone application with an HTML front end. I want to use TYPESCRIPT to do my processing onto my html page. There is one javascript function which is crucial for my application to work - window.external.notify
This method isn't created till runtime I assume, so I build a javascript wrapper function to determine if it exists when it is called.
if (window.external.notify != undefined)
window.external.notify(msg);
The issue is I need to get my Typescript files to see this function.
I am using Visual Studio 2012 and I have seen the post - How to use an exported function within the local module
The issue is when I just include my javascript file with the function I want to use I get the error TS2095.
error TS2095: Build: Could not find symbol
Any ideas or help or possible SDKs to circumvent this issue?

//notif.js
let notify = function(message) {
alert(message);
}
//test.ts
declare function notify(message: string): any;
if(notify != undefined)
notify("your message");
Make sure notif.js is loaded first.

You need to tell typescript that this function exists on window.external in order to use it. So :
interface External{
notify: Function;
}
if (window.external.notify != undefined)
window.external.notify("your message");

Related

Is it possible to only convert a dart function to javascript

I am currently using the following package where the readme illustrates the following
final bool loaded = await JsIsolatedWorker().importScripts(['test.js']);
I am using the isolate worker package so my code can work on web and outside of web. I would like to generate javascript code from my dart code. I have one file with a top level function and I use
dart compile js -O0 -o test.js test.dart
which I found here
https://dart.dev/tools/dart2js
this is my dart file
void main(List<String> args) {
doComputation('');
}
String doComputation(String input) {
return 'output';
}
I can generate javascript only if I have a main function but this generates a javascript file where the doComutation is not a top level function, so I am not sure if the package can call the function. It looks like it generates an entire program instead of just generating one function.
The generated file is too long to post
So what my question comes down to is this. Is there a way to generate javascript from dart for 1 function with its dependencies included instead of having to generate the entire program? So that I can call this function from dart.
I am not an expert but I also had this problem. Here's what worked for me:
In web_worker.dart:
import 'package:js/js.dart';
main(){
allowInterop(doComputation);
}
#JS('doComputation')
String doComputation(String computationInput) {
// Replace this with your actual computation.
final String computationOutput = "output";
return computationOutput;
}
Compile it using:
$ dart compile js web_worker.dart -o webWorker.js
Manually edit webWorker.js, the JS file generated by the compiler:
Delete this line at the top of the file:
(function dartProgram() {
and the line at the bottom of the file with the corresponding closing brace:
})();
I don't understand what's going on here but I found the Javascript version of the function doComputation() defined in webWorker.js as a property of the object "A".
I defined a wrapper at the top of the file like this:
function doComputation(computationInput) {
return A.doComputation(computationInput)
}
and then I was able to use the file with JsIsolatedWorker like this:
final bool loaded =
await JsIsolatedWorker().importScripts(['../web/webWorker.js']);
if (loaded) {
final String computationResult = await JsIsolatedWorker()
.run(functionName: 'doComputation', arguments: computationInput);
} else {
debugPrint('Web worker is not available');
}
If someone who understands this better can elaborate or improve on this solution, that would be great. I don't really have any idea what I'm doing. I'm just posting this to hopefully help other people save time in the future by sharing what worked for me.
You can use js package to call JavaScript APIs from Dart code, or vice versa. To make a Dart function callable from JavaScript by name, use a setter annotated with #JS().
#JS()
library callable_function;
import 'package:js/js.dart';
/// Allows assigning a function to be callable from `window.functionName()`
#JS('functionName')
external set _functionName(void Function() f);
/// Allows calling the assigned function from Dart as well.
#JS()
external void functionName();
void _someDartFunction() {
print('Hello from Dart!');
}
void main() {
_functionName = allowInterop(_someDartFunction);
}
JavaScript code may now call functionName() or window.functionName().
Check google chartjs https://github.com/google/chartjs.dart/tree/master/example for a complete example.
From dart2js "Helping dart2js generate better code" there is a tip :
Don’t worry about the size of your app’s included libraries. The dart2js compiler performs tree shaking to omit unused classes, functions, methods, and so on. Just import the libraries you need, and let dart2js get rid of what you don’t need.
Related to this post https://stackoverflow.com/a/21124252/3733730.
You can do this instead by using the package dart2js
one make a program for your main.dart dart2js where the function or command you wanted to make is there, then create a separate dart file what function you wanted to call, and it will fix your problem, it is a separate file but will only execute one function that you needed to do so and that is the separate file

JavaScript run eval() with imported modules - or alternative?

I am currently trying to build a "web IDE", similiar to e.g JSFiddle.
I want to execute user input (JavaScript) locally in the browser - which works fine.
For that I simply used
let userInput = `console.log("the user typed this")`
eval(userInput) // correctly executed the script from above
However, I want to access statically hosted modules as well - like myModule.js
export { test }
function test() {
console.log("I am a module")
}
and let the user use that module like that
let userInput = `
import { test } from "./myModule.js"
test()
`
eval(userInput) // throws an error
which throws an error that cannot use import outside a module
now to my question(s):
Can I somehow use import() dynamically inside the eval() statement?
Is there perhaps an alternative that allows me to execute user input inside the browser with imported modules?
Note: I am using Vue (nuxt) for an easy UI
Thanks!

Is there any way I can load a class in webworker instead of just plain javascript file?

I want to load a file in webworker but its not a plain javascript file. It is a class. So, instead of writing javascript file url in
new Worker(filename.js);
I am initializing the class by writing
new Worker(new ClassName());
It is reading the file and loading it properly. It even shows the console.log message in constructor. But when the control moves to postMessage method in main file, it throws error.
The application I am working on has a very complex structure. We have a common module that contains several classes which are executing some common functionalities throughout the application. The functionality I am working on can cause the performance issues if I execute it directly in the application. So, I am loading it in a webworker. Since its a class so I have to invoke it using new keyword. So instead of:
var ww = new Worker(filename.js);
I am writing:
var ww = new Worker(new ClassName());
Now, it invokes the class, it console logs the statement written in constructor but when in the main file it executes postMessage, javascript throws an error and stops the method from execution.
See the code below:
mainFile.js
var ww = new Worker(new CommonWebWorker());
ww.postMessage('LOAD');
ww.onmessage = function (e) {
console.log(e.data);
}
CommonWebWorker.js
'use strict';
class CommonWebWorker {
constructor() {
console.log("commonWebWorker invoked");
this.onmessage = function (e) {
this.postMessage((e.data === 'LOAD' ? 'Loading...' : 'Loading Error'));
}
}
}
module.exports = CommonWebWorker;
I expect that the file will load in the background through WebWorker but actually it is breaking and throwing below mentioned error
GET http://localhost:3000/[object%20Object] 404 (Not Found)
Any kind of help is much appreciated.
The reason for the error is that Worker expects a URL string as its first parameter, not an object. So it converts it to a string, and when you do that on most objects you get "[object Object]" (although I would have expected "[object CommonWebWorker]" from your code, but I assume you're using a transpiler or something outputting ES5 code, which would give you "[object Object]" instead).
Your main page and your work are completely different JavaScript environments. You can certainly use a class in your worker if you want, but you'd need to instantiate it in the worker, e.g.:
class CommonWebWorker {
// ...
}
new CommonWebWorker(); // To instantiate it
Your worker can also import the class from another JavaScript file via importScripts (before too long it'll be able to use ES2015+ module syntax instead), so if you want to use the same class in multiple workers, you could put it in its own file and do:
importScripts("common-web-worker.js");
new CommonWebWorker(); // To instantiate it
Once ES2015+ syntax is widely available in workers¹, you'd start your worker with the relevant module flag (new Worker("worker.js", {type: "module"})), and do this instead:
import CommonWebWorker from "./common-web-worker.js";
new CommonWebWorker();
¹ I checked just a month ago or so, and the only browser supporting it was Chrome behind a --enable-experimental-web-platform-features flag. But this stuff changes fast... :-)

Kotlin Call Javascript function in Android without webView

Is there any way we can call JS function from Kotlin without having WebView in Android?
Let's say as mentioned below I have one JS function helloJS() in test.js file,
test.js:-
function helloJS(){
return "Hello from JS"
}
And now I want to call this function from Kotlin file like
TestClass.kt:-
class TestHello{
fun getHelloFromJS(){
val name = test.helloJS()
}
}
Till now I am using Webview and loading JS file into that and getting result as call back
But, I read that Kotlin is interoperable with JS like Java
So I am curious to know if there is any way we can use that on Android without having webView
This is not possible straight forward but I found one library Execute JavaScript in Android without WebView for achieve this.
Read that blog carefully and follow below step.
Keep your JavaScript file (test.js) in assets folder in android project.
I have converted that code into Kotlin.
CallJavaScript.jks
import org.mozilla.javascript.Context
import org.mozilla.javascript.Function
import java.io.InputStreamReader
object CallJavaScript {
fun callFunction(mContext: android.content.Context): Any? {
var jsResult: Any? = null
val params = arrayOf<Any>("")
// Every Rhino VM begins with the enter()
// This Context is not Android's Context
val rhino = Context.enter()
// Turn off optimization to make Rhino Android compatible
rhino.optimizationLevel = -1
try {
val scope = rhino.initStandardObjects()
// Note the forth argument is 1, which means the JavaScript source has
// been compressed to only one line using something like YUI
val assetManager = mContext.assets
try {
val input = assetManager.open("test.js")
val targetReader = InputStreamReader(input)
rhino.evaluateReader(scope, targetReader, "JavaScript", 1, null)
} catch (e: Exception) {
e.printStackTrace()
}
// Get the functionName defined in JavaScriptCode
val obj = scope.get("helloJS", scope)
if (obj is Function) {
// Call the function with params
jsResult = obj.call(rhino, scope, scope, params)
// Parse the jsResult object to a String
val result = Context.toString(jsResult)
}
} finally {
Context.exit()
}
return jsResult
}
}
Add this line to build.gradle:
implementation 'org.mozilla:rhino:1.7R4'
In your assets folder, create a file called test.js:
function helloJS()
{
return "Hello from JS";
}
Now simply call above function from Activity.
Log.e("JS : ", CallJavaScript.callFunction(this).toString());
Output :
E/JS :: Hello from JS
It's not possible. You must not confuse the language with the platform.
Kotlin is interoperable with JS like Java
means Kotlin/JS can use and be used in a Javascript platform (Node.js or browsers). The Kotlin code compiled (transpiled) into js is able to call other js files. And external Js code can call the js code build from Kotlin. This is the interoperability with JS.
There is no interoperability between Kotlin/JS and Kotlin/JVM.
Kt looks like JS, but it is not. It will be compiled for Android runtime, not for the java script engine.
JS code require a JS runtime, but it is not in Android Runtime.
i.e. you cannot run JS directly in Java / Kt code for Android.
Am not a pro in Kotlin but Java is a pie for me. Anything you can implement in Java can be implemented in Kotlin and To execute Javascript code, I use rhino which does the job pretty easier than using the webview
Implement it:
try {
Scriptable scope = rhino.initStandardObjects();
rhino.evaluateString(scope, javaScriptCode, "JavaScript", 1, null);
Object obj = scope.get(functionNameInJavaScriptCode, scope);
if (obj instanceof Function) {
Function jsFunction = (Function) obj;
// Call the function with params
Object jsResult = jsFunction.call(rhino, scope, scope, params);
// Parse the jsResult object to a String
String result = Context.toString(jsResult);
}
}finally {
Context.exit();
}

Where to place javascript functions in Meteor applications

In Meteor we normally attach javascript functions to Templates. Where do we place standard javascript functions?
For instance, in one of my apps I have a UserInfo.js file which has a bunch of javascript functions for handling users logging in and getting user information.
Below are two of my functions in UserInfo.js
File is located in the client/scripts folder:
isAdminById = function(userId) {
var user;
user = Meteor.users.findOne(userId);
return user && isAdmin(user);
};
isAdmin = function(user) {
if (!user || typeof user === 'undefined') {
return false;
} else {
return !!user.isAdmin;
}
};
When I run the app and call isAdmin() from the browser console it says:
ReferenceError: isAdmin is not defined
---- Edit ----
It seems the problem was fixed temporarily when I placed the javascript file under the client/compatibility folder but now the issue has resurfaced. The only thing I remember changing was calling >> Meteor Reset
More Info:
I think the issue arises when I use coffeescript. When I convert my coffeescript files to js files everything seems to work.
You need to declare coffeescript variables as global with #:
#isAdmin = user -> ...
This is due to how Meteor variable shadowing works in connection with coffeescript automatic variable declaration.
Coffeescript by default does the "smart" variable declaration by itself - basically by placing var variableName in the first place in javascript where the variable is visible. In your case, this causes isAdmin to be declared by var in js, and therefore it's scoped to the file.
Using # char supersedes this default behavior by binding the variable to this, global or window object instead.
Your code is correct, it's probably a load order problem.

Categories

Resources