I'd like to receive callbacks from Javascript code to my Silverlight host without using ScriptableAttribute. I've seen it done before, but I couldn't work out how they did it. Has anyone got any ideas? Thanks
Simple enough use:-
HtmlPage.Window.Invoke("someJavascriptFunc", "Hello", "World");
In the javascript in the page hosting the silverlight have:-
function someJavascriptFunc(p1, p2)
{
alert(p1 + ' ' + p2);
}
Edit: Ken is right the above is the wrong way round.
Lets say you have this function in Silverlight:-
string GetStuff(string name)
{
return "Hello " + name;
}
You can now make this function available to javascript like this:-
HtmlPage.Window.SetProperty("sayHello", new Func<string, string>(GetStuff));
Now code in javascript can simply do something like this:-
alert(sayHello("Fred"));
If you're using events, in theory, you can use AttachEvent to subscribe to events. That's not quite the same thing as callbacks, but it's close.
Caveats: I haven't tested AttachEvent on Mozilla-based browsers (where the appropriate JS command is "addEventListener()" rather than "attachEvent()"), and I've had trouble getting AttachEvent() to work reliably even in IE. So I've always just used the [ScriptableMember] attribute, and called that from JS. Is there a reason you don't want to use that? (I'd be curious to hear if anyone has any better ideas.)
Related
I'm fairly new to C++ and v8 in general, and I wanted to build a native node.js addon, but now I'm stuck on something quite simple IMO, but I can't figure out what the issue is, the error message
C:\Path\To\Project\File.cpp(50): error C2664: 'v8::Local<v8::FunctionTemplate> v8::FunctionTemplate::New(v8::Isolate *,v8::FunctionCallback,v8::Local<v8::Value>,v8::Local<v8::Signature>,int,v8::ConstructorBehavior,v8::SideEffectType)': cannot convert argument 2 from 'v8::Local<v8::Value> (__cdecl *)(const v8::FunctionCallbackInfo<v8::Value> &)' to 'v8::FunctionCallback' [C:\Path\To\Project\build\node_gui.vcxproj]
is not that helpful.
I've got the following code,
v8::Local <v8::Object> Window::GetFunctions() {
v8::Local <v8::Object> DrawFunctions = v8::Object::New(isolate);
v8::Local <v8::FunctionTemplate> bgfnc = v8::FunctionTemplate::New(isolate, &Window::BackgroundCB);
DrawFunctions->Set(v8::String::NewFromUtf8(isolate, "background"), bgfnc);
return DrawFunctions;
}
void Window::Background(const v8::FunctionCallbackInfo <v8::Value> &args) {
v8::Isolate *isolate = args.GetIsolate();
renderer->Background(args[0]->NumberValue(), args[1]->NumberValue(), args[2]->NumberValue());
}
v8::Handle <v8::Value> BackgroundCB(const v8::FunctionCallbackInfo <v8::Value> &args) {
return ((Window*)v8::External::Cast(*(args.Data())->Value())->Background());
}
I want to create an object that contains a list of functions, the functions' callbacks would be member functions of the Window class. I know this has been asked before here, which worked once using a non-member function but otherwise not.
Thanks
Sidenote: I've looked far and wide for v8 docs that are suitable for beginners, the nodesource ones don't explain what the parameters mean or rarely give a thorough example of how to use the function / class, if anyone knows some better docs, that would be great, thank you.
Thanks to the gracious and prompt help of the community, I was able to quickly and effortlessly resolve this issue. Turns out, when writing NodeJS addons, it's a good idea to use NodeJS's own N-API, as the documentation is simpler, clearer, and most importantly, existant.
I've been all over here and can't find an answer. I have a .swf sitting in an HTML page and I am trying to call a function inside of it from javascript. I can talk out from flash to the javascript but I can't get it to talk back in. I know I am targeting the object properly because I use console.log() on it and confirms what it is targeting.
I'm triggering the test from flash, calling a javascript function from inside the .swf, and having that function call the internal Flash function.
Flash Code:
//adds callback
ExternalInterface.addCallback("sendToFlash", flashTalkedTo);
//function called by the callback
public function flashTalkedTo():void{
//runs another function in javascript to log a string
ExternalInterface.call("callMe")
}
//calls javascript that tries to talk to Flash
ExternalInterface.call("catchFromFlash")
Javascript Code:
//function called by Flash that initiates
function catchFromFlash(){
talkToFlash()
}
//function that tries to talk to flash
function talkToFlash(){
document.getElementById('Noodleverse').sendToFlash()
}
//function called by Flash in the end to confirm call made
function callMe(){
console.log("Call Me")
}
Any help works, thanks!
Flash, and plugins in general, are a little bit fiddly. They don't behave quite like normal elements, and their functions don't behave quite like normal functions. For example, you can't save the element into a value and call a function from that. You also need to be careful because in some browsers the object is used and in others the embed is used.
The best way to call a function is to use swfobject (https://code.google.com/p/swfobject/) to abstract everything. Personally though, I use this (based on experience, maybe somebody can offer improvements):
HTML:
<object id="myplugin" ...>
...
<embed name="myplugin" ... />
</object>
JavaScript:
var o1=document.myplugin;
if(o1&&!!o1.myFlashFunction){
return document.myplugin.myFlashFunction(); // DO NOT USE o1 here. It will fail.
}
var o2=window.myplugin;
if(o2&&!!o2.myFlashFunction){
return window.myplugin.myFlashFunction(); // DO NOT USE o2 here
}
The first case (document) is for most new browsers. For example, Chrome will find the embed object. The second (window) is for IE and finds the object (IE, at least old IE, ignores embed). I'm not 100% sure the second is needed, because IE might also work with document, so call that voodoo code. Also window.myplugin will give an array of all matching elements in Chrome, FireFox, etc. (but we expect those to already be taken care of)
Is this a possible solution for a pure javascript sandbox ?
My willing is to execute an untrusted string of code without giving access to DOM, window, this, and so on but allowing the user to acces Math, JSON and other functionalities.
I've tested it on Chrome.
UPDATE:
I want to give the possibility to save on server user-defined code and make it available to other users. I'm looking for a way to deny access to the document ni order to make it safe.
function safe(code,args)
{
if (!args)
args=[];
return (function(){
for (i in window)
eval("var "+i+";");
return function(){return eval(code);}.apply(0,args);
})();
}
ff=function()
{
return 3.14;
}
console.log(safe("this;"));//Number
console.log(safe("window;"));//undefined
console.log(safe("console;"));//undefined
console.log(safe("Math;"));//MathConstructor
console.log(safe("JSON;"));//JSON
console.log(safe("Element;"));//undefined
console.log(safe("document;"));//undefined
console.log(safe("Math.cos(arguments[0]);",[3.14]));//-0.9999987317275395
console.log(safe("arguments[0]();",[ff]));//3.14
I've proposed it on an old post : https://stackoverflow.com/a/11513690/76081
Thanks!
It's unsafe. The following construction will get the global window object from inside your sandbox:
(function(){return this;})()
At which point, you can extract anything you want from it, including goodies like document.
Hat tip to T.J. Crowder for his answer on https://stackoverflow.com/a/2673780/149341 in which he described this exploit.
I am trying to use javascript to run AS3 functions. When I attempt to compile I'm getting an "Access of undefined property" error message.
I've read a few things online about this but I'm still not understanding it. I want to have the flash file always listening for javascript.
Here is my AS3 code:
ExternalInterface.addCallback("song4", PauseMusicExt);
And my Javascript & HTML:
function returnVar3(song3) { return this[song3]; }
<input type="submit" name="playButton" id="playButton" value="Submit" onClick="returnVar('song3')"/>
Edit: Here is the pauseMusic function:
function pauseMusicExt():void
{
songPosition = channel.position;
channelSilence.stop();
channel.stop();
channel2.stop();
btnPlay.mouseEnabled = true;
}
I'm not sure about the extend of your app but you've got your addCallback function parameters mixed up..
See the doc, the first parameter is the name you want to expose the function as to javascript, the second is the actual internal AS3 function you want to trigger.
So the declaration should likely be something like:
ExternalInterface.addCallback("song4", pauseMusic);
(assuming that your function in the same scope as where you call addCallback)
That statement will create a "song4" method that you can call on your flash dom object
var fl = document.getElementById('myflashobject');
fl.song4()
After there's the issue that pauseMusic want a parameter (looks like you've made it a mouse event handler). You probably want to have a clean method that doesn't require a parameter like an internal as3 event param. Rewrite pauseMusic so it doesn't require it (you might need to create another method to handle the mouse event internally - like onPause(evt:MouseEvent), which then calls pauseMusic.
Edit: I don't know if a lot of people thought about doing that, but you can also totally use external interface to call firebug's console.log function to send messages to Firebug from flash (it's really helpful for debugging ExternalInterface issues, or any other flash problems - see the ExternalInterface.call function)
Hope u want to pause the audio player.
AS code :
ExternalInterface.addCallback("sndToAS",rcvdFmJS);
function rcvdFmJS(val){
if (val == "pause"){
audioPause();
}
}
JS code :
document.getElementById("movie").sndToAS("pause");
This may be dumb question. But somehow this engaged me for sometime and after some basic research I couldn't find an answer.
I was learning JavaScript and a code I wrote had an error and has been outputting infinite loops of alerts. I tried the normal shortcuts like Ctrl + C and Ctrl + Z but they didn't work. So I was thinking if there is any solution to this other than ending the browser process (like by doing a Ctrl + Alt + Del).
There are workarounds, as #Sarfras mentions, but no magic button that'll save you. The F5 workaround is the best I know of.
If you are using firebug, I would suggest you look into using the log feature rather then alerts. Many people find this as a useful way of debugging.
http://getfirebug.com/logging
If you are using alert as a debugging method, I strongly suggest you use the firebug plugin.
With it, you can use console.debug("whatever message", whatever, values).
Otherwise, if your intent is to actually use a dialog message, you could use some of these dialogs rather than the browser's built-in dialogs. Besides being a standard way of showing messages, they are way nicer ;)
You can log errors without a specific browser, with a global array.
This method allows you to 'turn off' an infinite alert,
but still be able to read the error log.
var logErrors= true, errorLog= [];
function Yikes(str){
if(str.constructor==Error)str=str.message;
errorLog.push(str);
if(logErrors== true){
logErrors= confirm(str+'\n keep showing errors? ');
}
return true;
}
window.onerror=Yikes;
you can also use it around problem code,
to return values:
try{
d2= Date.fromUTCArray(D.slice(0, D.length));
}
catch(er){
return Yikes(er.message+', '+D);
}