homepage Welcome to WebmasterWorld Guest from 54.167.41.199
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Home / Forums Index / Code, Content, and Presentation / Flash and Shockwave
Forum Library, Charter, Moderator: open

Flash and Shockwave Forum

    
Get nodeValue (JavaScript) of XHTML element from Flash?
I want to redirect with Flash based on URL in XHTML.
JAB Creations




msg:3983752
 12:52 am on Sep 4, 2009 (gmt 0)

I have music on my site though it's becoming a pain to manually update the URL's to redirect to inside of every FLA file, save, export, upload, repeat...for over a hundred songs!

I know enough about Flash to get around and that Flash scripting is somewhat similar to JavaScript. I know that if Flash was not involved I'd want to get the URL from this...

<div id="url_example">http://www.example.com

...I'd have to use this...

alert(document.getElementById('url_example').firstChild.nodeValue);

At the end of each track there is a keyframe and then a redirect like this...
getURL("example.php", "mplayer", "GET");

So how do I get the URL from the XHTML element, assign it to a variable, and then use the variable inside of the existing redirect?

- John

 

rocknbil




msg:3983791
 2:20 am on Sep 4, 2009 (gmt 0)

...manually update the URL's to redirect to inside of every FLA file, save, export, upload, repeat...

It sounds to me like it's not XHTML you want, it's XML. And yes, this is going to make your life tremendously easy - all you have to do is update the XML file.

Without getting into a full blown tutorial, let's take one of my simple projects - a slide show - as an example.

The XML file looks something like this:


<?xml version="1.0" encoding="ISO-8859-1"?>
<imageData>
<image src="/url-to/image1.jpg" url="http://www.example.com/1/" caption="caption 1"/>
<image src="/url-to/image2.jpg" url="http://www.example.com/2/" caption="caption 2"/>
</imageData>

And so on. Truth be known, this XML file comes from an admin area that uploads the images and saves URL and caption to a DB, then outputs the XML file so it's all client-managed. But for the purpose of demo, let's say you manually create it.

The children are labled image. The attributes of the children are src, url, and caption. These are read into Flash and stored in arrays, like so, in the first frame of the Flash (using only Flash 2.0, no less:)


var xmlSource = "/full-url-to/flash-playlist.xml";
var xmlLoaded:Boolean = (xmlLoaded==true)?true:false;
xmlObject.load(xmlSource);
xmlObject.onLoad = function () {
var imageData:Array =this.firstChild.childNodes;
for (i = 0; i < imageData.length; i++){
images[i]=imageData[i].attributes.src;
urls[i]=imageData[i].attributes.url;
captions[i]=imageData[i].attributes.caption;
}
xmlLoaded = true;
}

(xmlLoaded is for other functions in the program, that is, stay on this frame with preloader until xmlLoaded==true.)

So now I have the arrays images, urls, and captions that are used to step through the slide show, loading each into their respective object on the stage. I've used xmlObject to build slide shows, video playlists, music playlists, and it can be used to load just about anything without ever recompiling the .swf.

Additionally, it makes for a very compact program - the entire .fla is only 4 frames long, and two of those are dedicated to staying off the "play" frame until the data is loaded.

I think this is what you're after . . . isn't it? :-)

EDIT: and a small P.S. If there is only one player on each page, and that player only needs to accept one or two parameters (music filename and URL,) another approach would be to pass just those values to the Flash as variables (previously using "flashvars.") For example, if the Flash contains

var filename = 'music.mpg';
var url = 'http://www.example.com';

You could use SWFobject to pass those values to the Flash:


<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript">
var flashObj = new SWFObject('your.swf', 'my-music', '330', '290', '6', '#ffffff');
flashObj.addParam("wmode", "transparent");
flashObj.addVariable("filename", "music.mpg");
flashObj.addVariable("url", 'http://www.example.com');

window.onload = function() {
if (document.getElementById('flash-placeholder')) {
flashObj.write('flash-placeholder');
}
};
</script>

JAB Creations




msg:3984025
 2:35 pm on Sep 4, 2009 (gmt 0)

Thanks for the tutorial! I don't know squat about Flash action scripting...nor what frames I should actually create? I modified the element names and URL's a little and put the script in the first frame.

I loaded the page with the Flash .swf object already embedded however looking at my Apache access log it never requested the playlist.xml file in the same directory (file names are case sensitive). I then set the file path to absolute though I was pretty sure since I didn't see any request for an XML file whatsoever in the first place that it wouldn't make any request (and it didn't). So I'm not sure how Flash is supposed to trigger when it's initially loaded. For clarification I'm not talking about JavaScript in the XHTML but the Flash .swf object itself.

Also what frames do I need to create? My existing/old Flash music player's first frame has a sound (internal MP3 inside the library) and it just starts playing. It then hits a keyframe (which without it would automatically execute the last frame's script), and then the little script that I posted in my initial post. From what I sort of understand is that xmlObject.onLoad is an anonymous function loading during the onload event?

What are the other frames for specifically? I would like to simply show the image associated with the song while it's playing. I know how to sort of work with the time line and I know how to put script in to a given frame...and that a keyframe prevents Flash from executing the next "set?" of script until that frame or sequence of frames is finished playing. Will I be setting the sound property in the second or third frame? That is what I'm guessing right now though I pretty much just explained the bulk of my understanding of Flash. It's strange, like I'm standing in a perfectly lit room where I can see everything and then I'm sticking my arms in to a cloud of blackness and somewhere there just beyond my reach is what I'm trying to find blindly with my hands.

I have Flash 8.0. Your help is greatly appreciated! If I can get this to work it'll save me huge amounts of time! :)

- John

music.fla (frame 1)
var xmlSource = "playlist.xml";
var xmlLoaded:Boolean = (xmlLoaded==true)?true:false;
xmlObject.load(xmlSource);
xmlObject.onLoad = function ()
{
var trackData:Array =this.firstChild.childNodes;
for (i = 0; i < trackData.length; i++)
{
images[i]=trackData[i].attributes.src;
urls[i]=trackData[i].attributes.url;
captions[i]=trackData[i].attributes.caption;
}
xmlLoaded = true;
}

playlist.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<trackData>
<image caption="caption 1" src="jab_02.jpg" url="jab_02.mp3" />
<image caption="caption 2" src="jab_12.gif" url="jab_12.mp3" />
</trackData>

rocknbil




msg:3984138
 5:17 pm on Sep 4, 2009 (gmt 0)

Well, there is a large chunk of code missing from this, and the code I have handy is an image slide show and will do you no good - I was just demonstrating how XML data is imported to Flash. You have no code there that actually plays the sounds.

You see no requests in the logs -I THINK - because it's not requested from a browser, the Flash object requests the playlist so I don't think it gets logged.

The best advice I can give is to dig through the help files for XMLObject and Sound() . . . . there are tutorials in there that will allow you to work it all out.

What you will need is a sound() object in which you can load external data. If it is a playlist, you will need to loop through them, loading each into the sound object. You should be able to do something like

frame 1: load functions, assign them to objects, load XML, store in array
frame2: if xml loaded, go to and play frame 4, else go to and play frame 1
frame 3 increment loop
frame 4 loop coding and play coding, when this clip/image/sound is done go to and play 3 (which goes right to 4 and steps through loop)

ActionScript is NOT Javascript, but it's pretty close.

You should be able to develop, and test, your player locally - that is, using the same directory, develop something that works. Add a text box to your player, then when it loads, spit the loaded XML values into the textbox, it will tell you if the XML is being loaded and parsed properly. Then loop through them, and once that is working assign the data to the sound object.

Sorry without all the details, a formal RFP and a budget, can't offer up more than that ATM . . . .

rocknbil




msg:3984802
 6:52 pm on Sep 5, 2009 (gmt 0)

[bangs head on desk]

I have Flash 8.0.

An important part I forgot. When you go to publish your .swf, be sure to check the ActionScript publish settings and set them for ActionScript 2.0. If you're using features unsupported by a given version sometimes it won't error or warn you, it just won't do anything. Also true of the Flash publish version, but anything after v 6 should support xmlObject.

JAB Creations




msg:3984834
 8:29 pm on Sep 5, 2009 (gmt 0)

Instead of reinventing the wheel from scratch I figured since I'm returning to script-kiddying code like back in the day I might as well work with something that already has something that already works more or less. I spent a lot of time looking at existing implementations of MP3 players and came across by John Bezanis posted over at bezzmedia. It requested the XML file and works perfectly fine with the seek bar and timer which are the only features I care about that are visible in the Flash object itself at 480px width by 20 pixels in height. So now I'm trying to figure out how to have JavaScript control the Flash object.

So I have two general goals...the first is functional and the second one is about aesthetics.

So I've setup JavaScript to play and pause (stop) the Flash object in the old version of my music player. However I'm having trouble figuring out the minimal working code I need to have JavaScript call any function inside of the Flash file.

Here is my JavaScript that works with the old version of my music player...

function music_player(action)
{
var mplayer = parent.frame_mplayer.document.getElementById('mplayer');

if (mplayer)
{
if (action=='pause')
{
parent.frame_mplayer.document.getElementById('mplayer').StopPlay();
mplayer.className='pause';
}
else if (action=='play')
{
parent.frame_mplayer.document.getElementById('mplayer').Play();
mplayer.className='play';
}
}
}

The pause function (Flash/stop) doesn't work with this (I presume it's a generic function that Flash would understand)...and the play function resets the seek bar...which there is no point...it should resume at the position on the seek bar it's paused at. I have been spending some time making guesses at how to tweak and mess with the code...it doesn't feel altogether alien though it doesn't feel all that familiar either. Plus I'm a minimalist with code...and most people throw in tons of unnecessary stuff.

So apparently Flash doesn't simply let JavaScript access just any function it wants unless inside the ActionScript you manually allow JavaScript to access those functions...this is the basic idea the sites I've been reading are giving me. However their code is excessive and absolutely inconsistent.

So here is an example that doesn't work though it at least seems to be aimed in the direction I think the answer I'm looking for is...

import flash.external.ExternalInterface;
ExternalInterface.addCallback("loadnextsong", this, getFlashInfo);

I'm not sure what the second and third parameter are for, if they're necessary, etc. On the same page from JavaScript I'd like to simply be able to trigger the function like (or similar to)...

document.getElementById('mplayer').loadnextsong();

So I'm sure there are a few corrections I'll need. Don't worry about standards versus IE as far as JavaScript is concerned, that bit I have working fine already. :)

Here is the ActionScript inside of the Flash file...

stop();
var songs:Array = new Array();
var curtrack:Number = 0;
var playingsong:Sound = new Sound();
if (_root.playlist == undefined _root.playlist == "") {
_root.playlist = "mplayer/playlist.xml";
}
var playlistXml:XML = new XML();
playlistXml.ignoreWhite = true;
playlistXml.load(_root.playlist);
playlistXml.onLoad = function() {
loadSongs();
loadplaylistbox();
loadSong(curtrack);
if (_root.autostart == "false") {
toggleplaypause();
}
};
function loadSongs() {
for (songIndex=0; songIndex<playlistXml.childNodes[0].childNodes[0].childNodes.length; songIndex++) {
var songdata:Object = new Object();
for (songNode=0; songNode<playlistXml.childNodes[0].childNodes[0].childNodes[songIndex].childNodes.length; songNode++) {
switch(playlistXml.childNodes[0].childNodes[0].childNodes[songIndex].childNodes[songNode].nodeName){
case "creator":
songdata.artist = playlistXml.childNodes[0].childNodes[0].childNodes[songIndex].childNodes[songNode].childNodes[0].nodeValue;
break;
case "title":
songdata.title = playlistXml.childNodes[0].childNodes[0].childNodes[songIndex].childNodes[songNode].childNodes[0].nodeValue;
break;
case "location":
songdata.location = playlistXml.childNodes[0].childNodes[0].childNodes[songIndex].childNodes[songNode].childNodes[0].nodeValue;
break;
}
}
songs[songIndex] = songdata;
}
}
function loadSong(track) {
playingsong = new Sound();
playingsong.loadSound(songs[track].location, true);
playingsong.start(0);
updatevolume();
playingsong.onSoundComplete = function() {
loadSong((curtrack+1)%(songs.length));
};
playpause.gotoAndStop(1);
playpause.playpausebutton.onPress = function() {
toggleplaypause();
};
songdisplay.text = songs[track].artist+" - "+songs[track].title;
eval("playlistbox.playlistitemcontainer.playlistitem"+curtrack+".playlistitemhighlight")._alpha = 4;
eval("playlistbox.playlistitemcontainer.playlistitem"+track+".playlistitemhighlight")._alpha = 20;
curtrack = track;
}
function loadplaylistbox() {
for (songIndex=0; songIndex<playlistXml.childNodes[0].childNodes[0].childNodes.length; songIndex++) {
playlistbox.playlistitemcontainer.attachMovie("playlistitem", "playlistitem"+songIndex, playlistbox.playlistitemcontainer.getNextHighestDepth(), {_x:0, _y:15*songIndex});
eval("playlistbox.playlistitemcontainer.playlistitem"+songIndex+".playlistitemtext").text = songs[songIndex].artist+" - "+songs[songIndex].title;
eval("playlistbox.playlistitemcontainer.playlistitem"+songIndex).songindex = songIndex;
}
}
playpause.playpausebutton.onPress = function() {
toggleplaypause();
};
function toggleplaypause() {
if (playpause._currentframe == 1) {
playpause.gotoAndStop(2);
playpause.curpos = playingsong.position;
playingsong.stop();
} else {
playpause.gotoAndStop(1);
playingsong.start(playpause.curpos/1000, 0);
}
playpause.playpausebutton.onPress = function() {
toggleplaypause();
};
}
onEnterFrame = function () {
if (songdisplay.movingright) {
songdisplay.hscroll -= 10;
if (songdisplay.hscroll<=0) {
songdisplay.movingright = false;
}
} else {
songdisplay.hscroll += 10;
if (songdisplay.hscroll>=songdisplay.maxhscroll) {
songdisplay.movingright = true;
}
}
if (!draggingslider) {
progressslider._x = (playingsong.position/playingsong.duration)*400+0;
if (progressslider._x == 0) {
progressslider._x = 8;
}
}
if (draggingplaylistscroller) {
updateplaylistscroll();
}
if (draggingvolmeslider) {
updatevolume();
}
tempsongtime = "";
if (Math.floor(playingsong.position/60000) == 0) {
tempsongtime += "0";
} else {
tempsongtime += Math.floor(playingsong.position/60000);
}
tempsongtime += ":";
if (Math.floor((playingsong.position/1000)%60)<10) {
tempsongtime += "0";
}
tempsongtime += Math.floor((playingsong.position/1000)%60);
tempsongtime += "/";
if (Math.floor(playingsong.duration/60000) == 0) {
tempsongtime += "0";
} else {
tempsongtime += Math.floor(playingsong.duration/60000);
}
tempsongtime += ":";
if (Math.floor((playingsong.duration/1000)%60)<10) {
tempsongtime += "0";
}
tempsongtime += Math.floor((playingsong.duration/1000)%60);
songtime.text = tempsongtime;
//trace(Math.floor(playingsong.position/60000));
//if(Math.floor(playingsong.position/1000)%60)
//songtime.text=Math.floor(playingsong.position/1000)%60+"/"+Math.floor(playingsong.duration/1000)%60;
};
progressslider.onPress = function() {
draggingslider = true;
progressslider.startDrag(true, 8, progressslider._y, 243, progressslider._y);
};
progressslider.onRelease = progressslider.onReleaseOutside=function () {
progressslider.stopDrag();
playingsong.start(((progressslider._x-8)/400)*playingsong.duration/1000, 0);
playpause.gotoAndStop(1);
playpause.playpausebutton.onPress = function() {
toggleplaypause();
};
draggingslider = false;
};
progressbar.onPress = function() {
playingsong.start(((_xmouse-8)/400)*playingsong.duration/1000, 0);
playpause.gotoAndStop(1);
playpause.playpausebutton.onPress = function() {
toggleplaypause();
};
};
volumebar.onPress = function() {
draggingvolmeslider = true;
volumebar.volumeslider.startDrag(true, 0, volumebar.volumeslider._y, 47, volumebar.volumeslider._y);
};
volumebar.onRelease = volumebar.onReleaseOutside=function () {
draggingvolmeslider = false;
volumebar.volumeslider.stopDrag();
updatevolume();
};
function updatevolume() {
playingsong.setVolume((volumebar.volumeslider._x/47)*100);
}
previoussong.onPress = function() {
loadprevioussong();
};
function loadprevioussong() {
var loadtrack = (curtrack-1)%(songs.length);
if (loadtrack<0) {
loadtrack = songs.length-1;
}
loadSong(loadtrack);
}
nextsong.onPress = function() {
loadnextsong();
};
function loadnextsong() {
var loadtrack = (curtrack+1)%(songs.length);
loadSong(loadtrack);
}
playlistscroller.onPress = function() {
draggingplaylistscroller = true;
playlistscroller.startDrag(true, 283, 70, 283, 171);
};
playlistscroller.onRelease = playlistscroller.onReleaseOutside=function () {
draggingplaylistscroller = false;
playlistscroller.stopDrag();
};
playlistscrollup.onPress = function() {
playlistscroller._y = Math.max(70, playlistscroller._y-10);
updateplaylistscroll();
};
playlistscrolldown.onPress = function() {
playlistscroller._y = Math.min(171, playlistscroller._y+10);
updateplaylistscroll();
};
var mouseListener:Object = new Object();
mouseListener.onMouseWheel = function(delta:Number) {
playlistscroller._y = Math.min(171, Math.max(70, playlistscroller._y-delta));
updateplaylistscroll();
};
Mouse.addListener(mouseListener);
playlistscrollbar.onPress = function() {
playlistscroller._y = Math.min(171, Math.max(70, _ymouse));
updateplaylistscroll();
};
function updateplaylistscroll() {
playlistbox.playlistitemcontainer._y = -((playlistscroller._y-70)/101)*(playlistbox.playlistitemcontainer._height-149);
}
function visitswfspot() {
getURL("http://www.swfspot.com", "_blank");
}
var myMenu = new ContextMenu();
var menubezz = new ContextMenuItem("SWF Spot Mp3 Player", visitswfspot);
myMenu.customItems.push(menubezz);
var menuplaypause = new ContextMenuItem("Play / Pause", toggleplaypause);
menuplaypause.separatorBefore = true;
myMenu.customItems.push(menuplaypause);
var menuprevioustrack = new ContextMenuItem("Previous Song", loadprevioussong);
myMenu.customItems.push(menuprevioustrack);
var menunexttrack = new ContextMenuItem("Next Song", loadnextsong);
myMenu.customItems.push(menunexttrack);
myMenu.hideBuiltInItems();
_root.menu = myMenu;

...as far as aesthetics are concerned I want to figure out how to have Flash use images based on the page's CSS or a <param element though I'd rather get the functionality working first.

So right now this new MP3 player works with the seek bar and timer and I'm guessing away at the JavaScript to Flash function calling. Also I've made sure the Flash object is published as you said earlier. Thanks for your help!

- John

JAB Creations




msg:3984849
 9:19 pm on Sep 5, 2009 (gmt 0)

I had some critical success! :)

So I found a cached page of a Flash 8 documentation that was actually helpful even if indirectly! However they did some less then intelligent things such as calling functions methods...uh hello?! This is why I think developers should be doing minimalism instead of designers! Any way I digress, here is the flow of code...

So I have the XHTML Flash object...
<object data="mplayer/42-mp3player.swf?autostart=true&#38;playlist=mplayer/playlist.xml" id="mplayer" style="height: 12px; width: 457px;" type="application/x-shockwave-flash">
<param name="movie" value="mplayer/42-mp3player.swf?autostart=true&#38;playlist=playlist.xml" />
<param name="loop" value="false" />
<param name="play" value="true" />
<param name="quality" value="high" />
<a href="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" rel="external" style="height: 32px; width: 32px;" tabindex="3" title="Install Flash Plugin"><img alt="Install Flash Plugin" src="images/interface-plugin-flash.gif" style="height: 32px; width: 32px;" title="Install Flash Plugin" /></a>
</object>

...and the XHTML anchor that executes the JavaScript...
<a href="javascript: music_player('next');">next track example</a>

...that calls a JavaScript function...
function music_player(action)
{
var mplayer = parent.frame_mplayer.document.getElementById('mplayer');

if (mplayer)
{
if (action=='next')
{
parent.frame_mplayer.document.getElementById('mplayer').Next();
}
}
}

...which then sends the signal to the Flash object...
import flash.external.*;
ExternalInterface.addCallback("Next", null, loadnextsong);

So that is the minimal code!

Whatever "ExternalInterface.addCallback" is called it has three parameters. The first is what you want to call the new method that JavaScript will use. I created the method named "Next". I'm not sure what the second parameter does though null doesn't trigger any errors thankfully! Lastly the third parameter is the function we want to execute (inside of the Flash object since this code is placed along with it obviously).

So! AWESOME!

I'm going to implement the rest of the functions and maybe clean up the ActionScript a little...however I still have to figure out how have Flash use dynamic images from either XHTML param elements or the stylesheet itself. If I can get the style sheet that would be great since my site is designed to supprt multiple themes and I'd really like to make it easy to customize the music player's seek bar as well as the color for the timer.

That's really all I can think of at the moment. I'm really excited that I figured this out!

- John

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / Flash and Shockwave
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved