I'm just curious if it's possible that Flash objects can access the DOM of the document that has embedded it.
Yes, through the ExternalInterface class.
You can make calls to Javascript from within the Flash movie and get back any public information about the page that your heart desires.
Addendum
Looking at this a year and a half later, i decided to add some examples:
Say you have a JS function on your client page like this:
function foo(bar,type) {
// do something with bar and type
}
You call it from Flash (using AS3) like so:
ExternalInterface.call(foo, bar, type);
Note that the function name is the first object and the arguments are listed sequentially thereafter.
To expose a method of the Flash movie to outside Javascript, you would do this in your Flash or Flex (again, AS3):
application1_applicationCompleteHandler(event:Event) {
// the app has finished loading, so do whatever we
// have to do on load, plus add that callback
ExternalInterface.addCallback(foo, bar);
}
public function bar(arg1, arg2) : void {
// do something with arg1 and arg2
}
In the Javascript on the page you invoke it like this (where myMovie is the ID of the SWF):
myMovie.foo(anArg, anotherArg);
In the addCallback method, the first argument is the external name of the function, and the second argument is the closure that will get called.
Yes.
An example: http://livedocs.adobe.com/flex/3/html/help.html?content=ProgrammingHTMLAndJavaScript_07.html
Not that I know of, but they can execute javascript in the containing document, which obviously can then access the DOM itself.
Related
I am new to JSONP and had implemented cross domain functionality for my application and everything is working fine. Now i want to change my javascript code to apply object orientation.
My api is
http://localhost:8080/myApplication/getComments?callback=displayComments
CrossDomain.prototype.displayComments = function(data) {
// code to display the comments
}
Now I am getting an error in firebug given below
ReferenceError: displayComments is not defined
I changed the api to
http://localhost:8080/myApplication/getComments?callback=this.displayComments
and found that the function is appended inline to the callback like this
http://localhost:8080/myApplication/getComments?callback=callback=function (jsonData)
{
//code to display the comments
}
this time another error in firebug
SyntaxError: function statement requires a name
I have a doubt whether to use JSONP in object oriented javascript or not.
Please help.
Thanks in advance.
There's no point in defining the function on the prototype of a function unless you are going to create instances of that function, so start by doing that.
var myCrossDomain = new CrossDomain();
Then you have to call the method on the object, not as a global (it isn't a global, so you can't do that anyway)
var uri = "http://localhost:8080/myApplication/getComments?callback=" +
encodeURIComponent("myCrossDomain.displayComments");
In response to edits and comments:
Yes i am creating an instance of this in another js file
Then reference it as shown above.
I changed the api to
http://localhost:8080/myApplication/getComments?callback=this.displayComments
It's JSON-P. It runs by adding a new script element. Everything gets called in the global context. That is going to call this.displayComments which will be the same as window.displayComments.
If you want to call your method directly, then you need to specify the global variable holding the instance explicitly.
If you don't want to call it directly then you can use the more traditional approach of generating a new, anonymous function which has access to said object through a closure, assigning that function to a global variable (with a unique name) and using that name as your callback argument.
and found that the function is appended inline to the callback like this
http://localhost:8080/myApplication/getComments?callback=callback=function (jsonData)
You haven't shown us the code that creates the URI so we can't tell why that might be the case.
I want to use window.open to open a window to one of my JSP file. But the browser keeps showing connecting... And even firebug stops working every time I click the text. Neither the p nor the input tags work, but when I use a href to link the JSP it can link to the file:
<!DOCTYPE html>
<html>
<head><title>Sample JSP Page</title>
<script>
function open(){
//window.open("hello.jsp","hello","height=700, width=800");
var x=window.open("hello.jsp","window","status=1,height=700, width=800");
x.focus();
}
</script>
</head>
<body>
<h1>Sample JSP Page</h1>
<p onclick="open()">do not work</p>
<form>
<input type="button" value="new window" onclick="window.open('test-with-utils')"></form>
</body>
</html>
That's because you have redefined window.open when you defined the function open. Use a different function name instead.
Change the name of the function.
The window object is the top level object in JavaScript, and contains in itself several other objects, such as "document", "history" etc.
When you define a variable or a function of your own you really add a new property to the window object. And this will work ( and a little live example ):
var foo = "bar";
alert ( window.foo ); // says "bar"
In addition if you add this little snippet to your code:
window.onerror = function ( msg, url, num ) {
alert ( "Error: " + msg + "\nURL: " + url + "\nLine: " + num );
return true;
};
you will get this error, when press the button:
Error: Uncaught RangeError: Maximum call stack size exceeded
This means an endless recursion. It is a side effect - you define a new open function, and when you call window.open(), you recursively call your function.
Just to expand on the reason that you are having problems here, you may want to read a little about javascript Scope (Very Helpful Blog). Essentially, consider the following code:
<script>
var thisOne=true;
function thatOne() {
alert("whizbang");
}
var theOther={foo:"bar"};
//More code here...
</script>
Once you reach the comment, you know you can access those variables and the function directly, like if (thisOne) {...}, element.onclick=thatOne; or console.log(theOther.foo). However, you can also access them as children of the root object which, in a web browser, is called window. So you can do:
console.log(window["thisOne"]);
window.thatOne.call(obj, params);
console.log(window.foo.bar);
so by defining open() as a function which is not inside another element (which is to say, is inside the root element), you overwrite the window.open() function. When you attempt to call the function later on, you get problems because the open function calls window.open, which calls window.open, which calls window.open...
There's a few ways to get around this -
Define the onclick handler inline
To do this, get rid of the whole <script>..</script> element then, using whichever element you choose (that supports it) add the onclick attribute:
onclick="window.open('hello.jsp','window','status=1,height=700, width=800');"
This is a nice and quick method, and it keeps all the logic right there with it's triggering element, but it is not easily extensible and you may find yourself sneered at by some. ("Oh, you use inline javascript? how quaint")
change the method name
This will take the least effort from you in terms of getting your page working now from what you have (it's also essentially what everyone else has suggested). Just change the name of the open method to something like openANewWindow() or gotoJSP() or anything that doesn't already exist in the root object, making sure to get both where you define it (in the script element) and where you use it (in the onclick attributes).
Use a closure
This is almost definitely not what you want in this case, its more complexity than you need for a single function. Just including this as an example of how to get out of the root object, seeing as being in it seems to be the heart of your problem.
You have probably already seen in javascript how to define an object, but you may not know that by defining an object, all you are really doing is adding an object property to the root object. You can use this behavior to your advantage, to give a hierarchical structure to your functions.
For example:
<script>
var MyFunctions = (function() {
function open(){
var x=window.open("hello.jsp","window","status=1,height=700, width=800");
x.focus();
}
return {open:open};
})();
</script>
This creates an anonymous function that is immediately run. Inside the scope of this function, another function, open() is defined, however it is defined within the scope of that anonymous function, not the root object (window). After open() is defined, a reference to it is returned as the value of the object property: open.
The result of all this is that the open property of the MyFunctions object is the function you need. You can then call it with MyFunctions.open() or even window.MyFunctions.open().
I have a coding difficulty which have been asked in this forum before:
Calling a JavaScript function returned from an Ajax response
But I didn't find the answers quite satisfying. To be more precise of the problem I'm dealing, here is the detail:
I dynamically load a document (HTML and javascript) using jquery
var url = 'document.php';
$('#container').load(url);
Example of what the document.php looks like:
<form>
<input name="firstname"></input>
</form>
<script>
function dosomething()
{
console.log($('input[name=firstname]').val());
}
</script>
*The dosomething() function is the one I'd like to call later
And then I want to call the functions from that document.php. Due to my requirement, I don't want to call the function after the documents' loaded, but rather to call it later when I need it. Because it was dynamically loaded, the DOM doesn't recognize the functions. How to properly call this function?
Thank you
the DOM doesn't recognize the functions
This sounds like your other functions are wrapped in $(document).ready() in the remote page. If that is the case they are out of scope for you to call them from code in the main page and you need to move them out of the ready handler to make them globally accessible.
EDIT: Other possibilities
Script tags in head- move to body after html, or use $.getScript in ajax callback to retrieve
I think that you're trying to implement the technique called on-demand javascript (or lazy-loading). In other words, your page should initially load just a small script - but use a bunch of objects and functions, which are available in some other files, but will be loaded when they're required.
If that's the case, I have to warn you: you'll probably need to update your existing code. Instead of just calling some function right as it is, in all gun-blazing glory, you should check for its existence first - and if it's not available, wait for its loading:
if (typeof lazyObjects.someLazyFunction !== 'function') {
lazyLoad('lazyFunction.js');
}
lazyObjects.someLazyFunction();
The key point here is that lazyLoad should be synchronous. In other words, you'll have to wait until the script containing your function is actually loaded. Otherwise someLazyFunction just won't be defined when it's called, even with this sort of checks.
lazyFunction.js, in turn, will contain some code that will alter lazyObjects, adding to them the required method as a property:
// in lazyFunction.js
lazyObjects.someLazyFunction = function() { ... }
While it's technically possible to use global (=window) object for these cases, I usually don't do this - and won't recommend doing it either.
See, it's not that simple. ) I'd recommend reading this article to find out more about this technique - and actually using some established components to implement it in your code (some of them are mentioned in the linked article).
I have a page with multiple flash objects which are written by a third party and thus can't be changed. They call a JS function but don't seem to pass any identifying parameters. Is there any way to determine inside the function which flash object called it?
This may not be cross-browser compatible, and in the end you may find only that "Flash" is calling the function, rather than a specific movie, but this is the only way I can think of:
function myFunction() {
if (myFunction.caller) {
console.log("This function's caller is " + myFunction.caller);
}
else {
console.log("This function was called directly");
}
/* rest of function */
}
This should run in Firefox and will log to the console.
Unfortunately the only information a function gets from the place that called it is whatever parameters are passed in with the call.
I want to call a Javascript function from Flash, which I can do with ExternalInterface, but the Javascript function takes a callback. Is there a way to give it a Flash callback?
I've thought of something like this:
ExternalInterface.addCallback("foo", function(){...});
ExternalInterface.call("theFunction", "foo");
But that wouldn't work since theFunction would attempt to do foo(), while it should really do swfObject.foo(). The problem is the page and its Javascript are not under my control (though I can request changes if really needed).
This is closely related to the first question in the related questions section.
Along the same lines as the answer to that question, you can do:
ExternalInterface.addCallback("foo", function() { /* ... */ }); // The callback
ExternalInterface.call("theFunction(function() { swfObject.foo(); })");
You're misunderstanding the documentation, I think. callback in this instance is just a reference to a function inside Flash, not a callback to something you call.
Basically, you use .call() to call a JS function from AS; and you use .addCallback() to tell the Flash Player which AS function should be called based on the name.
On your example, theFunction would get one parameter as being 'foo', which is the name that references your anonymous AS function. Not sure why you would want to pass the function like that, but if you need, you could just call it from JavaScript with
function theFunction(callback) {
// .. do something...
swfObject[callback]();
}
Now, if you don't have control over the JS/HTML side, I'm not sure if you can do that. Not sure why you'd need, anyway - JS calls are synchronous, as if they were running on the same thread, meaning the Flash Player will execute the JS code and only then return to the Flash Player... you don't have to wait for execution or anything.
Also, if you really need to control the page without touching the JS/HTML side, remember you can inject entire pieces of JS code via .call - it doesn't need to be a simple function call. You can create your entire functions from inside the SWF. For example,
var js:XML = <script><![CDATA[
// Javascript code...
]]></script>;
ExternalInterface.call(js);
Or, if you need the return data, you don't need a callback either - just do a simple call as in
// JS
function isNumberZero(__num) {
return __num == 0;
}
// AS
trace ("Is number zero = " + ExternalInterface.call("isNumberZero", 10));
Not sure if this helps at all. If not, it'd be good to have more information on what exactly you're trying to do.