Calling a custom FLASH method from IE7 & IE8 - javascript

I am trying to call a custom method of an embedded flash like so:
var flash =
navigation_get_flash_movie_object('main');
if (flash) {
flash.continentOut(id); }
Which works great in Chrome ans Safari, but fails utterly in IE7 & IE8. The browsers throws an error that the object doesn't have such a method.
I am using the example from http://www.permadi.com/tutorial/flashjscommand/, and now that I've tested it, it also fails at it's testing page as well http://www.permadi.com/tutorial/flashGetObject/
Does anyone have a better way to invoke custom functions in a Flash object from Javascript?

Check out the ExternalInterface API Docs. They use this method:
function thisMovie(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName];
} else {
return document[movieName];
}
}
So you would do this:
var flash = thisMovie('main'); if (flash) { flash.continentOut(id); }
(I'm assuming of course that you're using ExternalInterface.addCallback() to define continentOut)
Here's another option:
function thisMovie(movieName) {
return document[movieName] || window[movieName];
}
Personally, this seems better because it doesn't use browser sniffing and would be future-compatible, but that's just me.

Related

Discover what methods javascript object has

I have a page that renders just fine. On the page is a control and I wanted to set the visibility to hidden. I can get a handle on the object just fine but then when I went to use what I thought were pretty typical methods such as:
.setVisible(false);
or
.css("visibility", "hidden");
I got the object doesn't support method error.
Now to solve my visibility problem there was a containing div for the control so I just set the div to hidden.
$('#footer_statecode').hide();
My question however for the future is how would I discover the methods supported by an object.
My google searches came close such as this SO post but in these example the person had a specific method they were looking for. I am interested in seeing everything available....and it doesn't have to be via an alert(); I'd be just fine using some capability in the different browsers Developer tools (F12).
Thank you once again for sharing your knowledge.
You can use this. It won't include built-in JavaScript methods (ex Array.prototype.push)
var methods = [];
for (var prop in object) {
if (typeof object[prop] === "function") {
methods.push(prop);
}
}
You can find it like this:
function getMethods(prop)
{
var res = [];
for(var prop in x) {
if(typeof x[prop] == 'function') {
res.push(prop);
}
}
return res;
}
You can also look at the Object.prototype.hasOwnProperty()

webScriptNameForSelector and javascript method with underscore

I am using a WebView in my application and it the page I am loading has some existing javascript function calls that were used in a windows environment and should now be used in a mac application. My issue is that the current javascript (ported from a windows app where the following works) function calls objective C like this:
function callObjectiveC
{
window.external.MY_ObjectiveCFunction();
}
I have been trying to use:
+ (NSString *)webScriptNameForSelector:(SEL)sel
{
if (sel == #selector(MyObjectiveCFunction))
{
return #"My_ObjectiveCFunction";
}
}
based on: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/WebKit/Protocols/WebScripting_Protocol/Reference/Reference.html but to no avail. Is there a way to do this? I can call the objective C method whatever I want I just need to be able to map that to what is in the existing javascript.
Thanks,
c.
Figured out a solution:
- (id)invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)args
{
NSLog(#"invoke undefined method: %#", name);
if([name isEqualToString:#"My_ObjectiveCFunction"])
{
return NSSelectorFromString(#"My_ObjectiveCFuntion");
}
return nil;
}
you just shouldn't use underscore characters. That is basically the only valid solution unfortunately.
see here at the apple docs
I don't think using invokeUndefinedMethodFromWebScript: is a good idea here
Missing colon.
if (sel == #selector(MyObjectiveCFunction:))

Storage.prototype not working in IE8

I have been trying to get this to work in IE8 and while it does not complain about these it completely ignores them.
if( typeof(Storage) != "undefined"){
Storage.prototype.setObject = function(key, value) {
this.setItem(key, escape(JSON.stringify(value)));
}
Storage.prototype.getObject = function(key) {
return JSON.parse(unescape(this.getItem(key)));
}
}
When I try:
localStorage.setObject("key", <Some object>);
I get an "Object does not support this method" error raised and the function is not even called. Of course this code works fine in Chrome and Firefox and probably even on my 1980's Casio watch.
Any help would be great.
Incidental and completely unrelated the IE8 when I get my object back I have to JSON.parse it twice to get the object...
Thanks
Paul
You'd be better off using a separate function instead of messing with the prototype of a built-in object.
function storeObject(key,obj) {
localStorage[key] = JSON.stringify(obj);
}
function retrieveObject(key) {
return JSON.parse(localStorage[key]);
}
This is more reliable than prototype operations, particularly in older browsers.

What version of IE uses window[objectName] instead of window.document[objectName]?

I am trying to use a Javascript callback to a Flex application embedded in my page. Looking through some examples, I've seen this code used to get a reference to the Flex application:
// Get the reference:
function thisFlexApp(appName) {
if(navigator.appName.indexOf ('Microsoft') != -1) {
return window[appName];
}
else {
return window.document[appName];
}
}
// Use it:
var someVariable = thisFlexApp('NameOfFlexApp').callbackMethod();
I used that method, but using IE9 I got errors indicating the "thisFlexApp" call didn't work. Turns out that window.document[appName] worked in IE9, but window[appName] didn't. Since I don't expect my government clients to be using IE9 yet, I'm wondering what version of IE this method would actually work on? Is there another test that would be better to use instead of the one above which just assumes all versions of IE work a certain way? Thanks in advance.
Don't check the browser version, check the browser's capabilities. You can just check if window[appName] exists, and if it does, use it.
function thisFlexApp(appName) {
if(window[appName]) {
return window[appName];
}
else {
return window.document[appName];
}
}
Or even shorter:
function thisFlexApp(appName) {
return window[appName] || window.document[appName];
}

Detect availability of Javascript from Actionscript?

I would like to open external URLs from within my Flash project. I typically use something like this:
getURL("javascript:newwin=window.open('http://someurl.com','','');");
But, if Javascript isn't available (in cases where the SWF is not embedded in HTML) then this will fail. How can I detect whether Javascript is available? If it isn't available, I'd probably just use getURL and give it the direct URL, although I only want to do this if using the Javascript method isn't possible. Thanks!
To accomplish what you're describing, the best way is to have Flash invoke a JavaScript function called "pingJavaScript". If JavaScript is running, that JavaScript function will then call a function on the Flash movie called "receiveJSNotification". So in your Flash movie, if that method gets called, you know JS is running.
To enable robust communication between a Flash movie and JavaScript, include this at the top of an Actionscript on the first frame of your movie:
import flash.external.ExternalInterface;
import flash.events.Event;
Add a function to receive a "yes, I'm alive" from JavaScript:
var js_available = false;
function receiveJSNotification(str:String):void {
_root.js_available = true;
}
ExternalInterface.addCallback("notifyFlash", receiveJSNotification);
ExternalInterface.call("pingJavaScript", null);
In JavaScript:
function pingJavaScript()
{
var movie = getFlash();
movie.notifyFlash();
}
function getFlash()
{
var movie = null;
if (navigator.appName.indexOf('Microsoft') != -1) {
movie = window['flashmovie'];
} else {
movie = document['flashmovie'];
}
return movie;
}
I find that there is actually a much easier way to accomplish this:
public function isThereJavaScript():Boolean{
return Boolean(ExternalInterface.call("window.location.href.toString"));
}
This requires no JavaScript back-end. It just works consistently. If there is the ability to call JavaScript, that means that there has to be a window property, which will have a non-null location.href. ExternalInterface is also available for both AS2 and AS3.

Categories