I'm looking for a way to "inject" some events into a flash movie running on a browser. I know about ActionScript's ExternalInterface.addCallback function, however I'm trying to achieve this with any "random" flash from the web. Eg. send a "SPACE" keyboard event to a youtube video.
You can't do this to any random swf on any website because of security limitations. You need to have access to the DOM, which can only be done by Javascript Injections, unless you are the one with the swf embedded in the site, with allowScriptAccess="always" in the html template. MySpace, for example, allows you to add any random swf to the html page, but you can't do that javascript stuff because they force allowScriptAccess to always be false (among other things) to prevent any javascript/dom access.
If this is just for you to make your own life easier while browsing, you can use Firebug for Firefox. Check out this JQuerify Bookmarklet and Video, Hacking Digg with Firebug and JQuery. It shows you how to dynamically modify the webpage your on using javascript, and save those commands as shortcuts! Super cool.
So you could save a JQuerify command like:
$("#youtube_player").play();
...or whatever the api is for starting a youtube video in their html page, if that's even possible.
Hope that helps,
Lance
I tried creating a (WebKit) DOM event and sending it to the Flash OBJECT element. I also tried all of the child nodes of that element to be sure.
function fireEvent(target) {
var evt = document.createEvent("Events");
evt.initEvent("keypress", true, true);
evt.view = window;
evt.altKey = false;
evt.ctrlKey = false;
evt.shiftKey = false;
evt.metaKey = false;
evt.keyCode = 32;
evt.charCode = ' ';
target.dispatchEvent(evt);
}
It didn't work. My answer is: no. You can't do this, at least not from Javascript.
If you really want to do it, I think you'll have to create an application with an embedded browser control (WebKit, Gecko, etc.). Then you could call the plugin API directly to synthesize the user input events. This is how Boxee appears to works, for example.
Unless Flash is configured to listen for the events you're trying to send it, my guess is that what you want to do isn't possible. But, as my wife will surely tell you, I'm wrong a lot.
Related
I am doing something like this:
var samePath = "http://www.example.com";
function iframeLoaded(){
console.log( iframe.contentDocument.innerHTML );
iframe.src = samePath;
}
iframe.onload = loaded;
Unfortunately, this is really slow: the loading process waits that everything attached to the iframe has actually loaded.
Now:
I cannot use DOMContentLoaded, because once I've set iframe.src, it takes "a little while" for Chrome to create a new iframe.contentDocument object, and I cannot reliably attach events to it (unless I start polling... which would be even worse).
I cannot use DOMFrameContentLoaded because Chrome doesn't fire it (ugh): https://bugs.webkit.org/show_bug.cgi?id=33604 It's a bug, but nobody has tackled it for nearly a year
I cannot use Object.defineProperty() on iframe.contentWindow.document (javascript won't allow it)
I don't think polling for iframe.contentWindow.document is a sane way to go about it (is it?)
So... what is there a way I didn't think about that I could/should follow?
The only other way I thought about is to make an AJAX call and then do document.write() on the iframe. But then, all links to Javascript, CSS etc. will be broken -- unless you can point out a way to make it work without using RegExp...?
NOTE: Please ignore ANY comments about iframe security etc., as that is not the point of this question. Also, I am not able to change the viewed page...
I'm trying to make an extension for google chrome. It will automatically click on the speaker icon in the google dictionary's result to make it pronounces the word automatically.
http://www.google.com/dictionary?langpair=en|en&q=love&hl=en&aq=f
i'm using this code: document.getElementById("pronunciation").click()
however, i wonder why it doesn't work? actually tag does support the standard methods - as w3schools wrote: http://www.w3schools.com/jsref/dom_obj_object.asp
Can you suggest any method in order to make it works?
Since the object is flash, sending it a click event will not work unless Google built click support into the flash file -- which they apparently didn't.
However, the actual audio file is a parameter to the flash program, and linked to in a child node.
For the given example, it is: "http://www.gstatic.com/dictionary/static/sounds/de/0/love.mp3".
This can be obtained with:
var soundFile = document.querySelector ("#pronunciation a").href;
Then pass this file to a library, such as SoundManager 2, and your script can play it automatically (may your coworkers/family have mercy on your soul. :) ).
The play icon is a flash player.
Most likely the onclick event isn't on the stage (i don't know if that would even work with a click on the object) but on a element inside the flash.
So, I have web page that uses javascript to let a user select different audio files to listen to (using this player: http://www.macloo.com/examples/audio_player/) which works great in every browser except for any version of IE. After the audio starts playing I can't figure out a programmatic way to make the audio stop playing after the user clicks on another item to listen to. I don't have access to the source of the swf so I'm trying to use javascript to do this. I went so far as to replace the entire body of the page - $("body").html("blank") - but it still played the audio loaded into the swf in it's entirety.
Is there any way I can completely remove a swf from a page (sound and all) just using javascript?
You could try
location.href = location.href;
That will completely reload the page.
Have you tried?
$('object').remove();
Well, you may need to use External-interface and call flash method from javascript and that flash method will remove the swf file. If you are using Action-Script 3 with Flash Player 10 then you can use unloadAndStop() method. This method will unload your swf and will remove all its events and sounds etc. it is better to use unloadAndStop() method than unload() method.
And if you want to hide flash from server-page , you have many ways , call page refresh with a variable passed in query string , based on that variable value , you can hide/show your swf file. If you do want to do it with JavaScript then take your swf in Div and hide that Div..
Well, I tried all of the solutions proposed and they didn't work across all browsers for me. :( What I ended up doing is loading up the flash content in an iframe - when I changed the src of that it would completely and reliably kill the audio that was playing. I think this might have been because the audio appeared to be streaming? Ugh, anyway - iframe time!
Here's our goal: in a website, show a nice menu "à la" iPhone in Flash and when we click on a menu, show a part of the site "under" the Flash menu.
Two options:
create a page with the
Flash menu that has an iFrame and
with Flash, open the menu in that
iFrame;
create one page with a div
on its bottom, with Flash, launch a
JavaScript (if you have any better idea please tell me !) function that downloads via AJAX the desired menu.
My #1 objective is to have only one page. Ideally it would embed the Flash object and launch a JavaScript function.
PS: I hate iFrames. iFrames are evil to me.
Don't hesitate to correct my question to make it proper English !
Thanks,
Olivier
Yes, this is very possible using ExternalInterface in the Flash document. That link explains the whole process.
A bigger question is that it sounds like you are using Flash to duplicate an iPhone animation and I imagine (unless you are doing the "Flip" animation) that it could easily be reproduced with normal JavaScript animation, possibly with a library like jQuery or MooTools to help normalize browser differences. You can even do the 3D animations in Safari 4.
An older method that is sometimes still useful is the getURL method. A good writeup of the differences is here: http://www.psyked.co.uk/actionscript/actionscript-geturl-vs-externalinterface-when-why.htm. In general, ExternalInterface is preferred, but sometimes you want to interact with the page with a function that not defined.
Usage:
getURL("javascript:myFunction(arguments);");
As Doug said, you may be able to use a JS library to recreate the iPhone animations. This would have the added benefit of your menu being navigable for search engines if this is a concern.
An alternative to Doug's suggestion is the old 'fscommand()' function. In your Flash code, you put "fscommand('name', 'value');" replacing name and value with whatever information you want to fire out to the web page.
On the web page, you need to have a JavaScript function which listens to the 'FSCommand' event of the Flash object, like this (IE sample, see docs for other browsers):
function OnFSCommand(name, value)
{
// whatever you need to do with name & value
}
var swf = document.getElementById(name-of-my-Flash-object);
swf.attachEvent("FSCommand", OnFSCommand); // IE-only - see docs for other browsers
Last week we released Omniture's analytics code onto a large volume of web sites after tinkering and testing for the last week or so.
On almost all of our site templates, it works just fine. In a few scattered, unpredictable situations, there is a crippling, browser-crashing experience that may turn away some users.
We're not able to see a relationship between the crashing templates at this time, and while there are many ways to troubleshoot, the one that's confuddling us is related to event listeners.
The sites crash when any anchor on these templates is clicked. There isn't any inline JS, and while we firebug'ed our way through the attributes of the HTML, we couldn't find a discernable loop or issue that would cause this. (while we troubleshoot, you can experience this for yourself here [warning! clicking any link in the page will cause your browser to crash!])
How do you determine if an object has a listener or not? How do you determine what will fire when event is triggered?
FYI, I'd love to set breakpoints, but
between Omnitures miserably obfuscated code and repeated browser
crashes, I'd like to research more
thoroughly how I can approach this.
I did an "inspect element" on a link in that page with firebug, and in the DOM tab it says there is an onclick function (anonymous), and also some other function called "s_onclick_0".
I coaxed firebug placing a watch like
alert(document.links[0].onclick)
to alert me the onclick function that omniture (i guess) attaches to links:
function anonymous(e) {
var s = s_c_il[0], b = s.eh(this, "onclick");
s.lnk = s.co(this);
s.t();
s.lnk = 0;
if (b) {
return this[b](e);
}
return true;
}
Maybe in the same way you can see what it is really running after all that obfuscation.
DOM doesn't provide any means to introspecting through the events listeners' collections associated with a node.
The only situation where listener can be identified is when it was added through setting a property or an attribute on the element - check on onxxx property or attribute.
There have been a talk recently on WebAPI group at W3 on whether to add this functionality. Specialists seem to be against that. I share their arguments.
A set of recommendations to the implementers of on-page analytics:
Use document-level event capturing only, this is in almost every case (besides change/submit events) sufficient
Do not execute computation-intensive code (as well as any IO operations) in the handlers, rather postpone execution with a timeout
If this two simple rules are taken into account, I bet your browser will survive
I have some experience with Omniture and looking at your s_code.js, you have several things going on in the "Link Tracking" area, for example:
/* Link Tracking Config */
s.trackDownloadLinks=true
s.trackExternalLinks=true
s.trackInlineStats=true
s.linkDownloadFileTypes="exe,zip,wav,mp3,mov,mpg,avi,wmv,pdf,doc,docx,xls,xlsx,ppt,pptx"
s.linkInternalFilters="javascript:,gatehousemedia.com"
s.linkLeaveQueryString=false
s.linkTrackVars="None"
s.linkTrackEvents="None"
I would consult with the people at Omniture and verify that your link tracking configuration is set up correctly.
Specifically, this template and the links inside seem to belong to morningsun.net and yet morningsun.net is not in the s.linkInternalFilters setting. If you are using the same s_code.js file for multiple domains, you can use javascript to set the configuration values for things like this (basing on the document.location.hostname for instance).
I don't personally have experience with the link tracking configuration or I would give you more detail on how to configure it :)
While traveling home I came to a solution that allows for introspection of event handlers on element added with AddEventListener. Run code before the inclusion of your analytics code. The code was not verified if works, but the idea, I guess is clear. It won't work in IE, however you can apply similar technique (of rewriting the API member) there as well.
(function(){
var fAddEventListener = HTMLElement.prototype.addEventListener;
HTMLElement.prototype.addEventListener = function() {
if (!this._listeners)
this._listeners = [];
this._listeners.push(arguments);
fAddEventListener.apply(this, arguments);
}
})();