Forum Moderators: open

Message Too Old, No Replies

Merge getElementsByTagName (anchor) with function?

         

JAB Creations

2:55 am on Oct 24, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I need to have two different sounds play (onclick and onmousedown) on all anchors. There are two separate sound files that are loaded via Flash. I have pause and resume functions in JavaScript that interact with Flash nicely. Also I want to use getElementsByTagName to avoid having to modify anchor's HTML code or have to give every single anchor an id. So every anchor could look like <a href="#">example</a> and still have an onmouseover and onclick event with no additional attributes (that you would use on an individual basis or on all anchors creating load bloat).

Making a Flash Sound Stream
I currently have Flash 6.0 and this is just a quick tutorial for those who are fluent in JavaScript but either don't know or care much for Flash. If you have Flash you can find any wave file and import it first. Then click on the first frame. After clicking on frame 1 the properties window will give you a sound option. If you have already imported the wave file you should be able to choose it. Set the synch option to stream (event will make the user wait for the audio to play only after it has fully downloaded). Next go to File --> Publish Settings. Click on the Flash tab and change the stream's quality as you please. Next click on the HTML tab and uncheck loop (to save your sanity from looping away in about half a minute). Hit Ok, and then File and Publish. This should be all you need to do in order to create a Flash audio clip like the one I am testing with.

*Note - The JavaScript I am using here will not work if you insert a keyframe too early in the Flash file. I am however able to have it work with a keyframe towards the end of the flash file. This stumped me for a while when half my files worked and the other half did not.

JavaScript Flash Pause / Resume Script
XHTML and JavaScript

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
<script type="text/javascript">
function getFlashMovieObject()
{
if (navigator.appName.indexOf("Microsoft Internet")!=-1)
{
return window.sound;
}
else
{
return document.getElementById("sound");
}
}
function PauseFlashMovie()
{
var flashMovie=getFlashMovieObject();
flashMovie.StopPlay();
}
function PlayFlashMovie()
{
var flashMovie=getFlashMovieObject();
flashMovie.Play();
}
</script>
</head>

<body>

<div>
<object data="examplesound.swf" id="sound" style="height: 20px; width: 20px;" type="application/x-shockwave-flash">
<param name="loop" value="false" />
<param name="movie" value="examplesound.swf" />
</object>
<a accesskey="3" href="#" onclick="PlayFlashMovie();">Play</a>
<a accesskey="4" href="#" onclick="PauseFlashMovie();">Pause</a>
</div>

</body>
</html>

Anyway so I want to merge this script to be completely located in the head of the XHTML without any JavaScript events in the form of XHTML attributes merged with getElementsByTagName to achieve this. I want to have separate onmouseover and onclick events. Thanks for any help or suggestions!

- John

Fotiman

2:41 pm on Oct 24, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Hmmm... are you sure you want to be using XHTML? You probably only want HTML (see this thread: [webmasterworld.com...] but rather than get sidetracked, let's focus on the question at hand.

First, I would remove that browser sniffing in the getFlashMovieObject() function. There's no need, since getElementById should work for both IE and other browsers.

It would not be difficult to use getElementsByTagName to get the <a> links (or you could use document.links[]). But how are you going to know which of those links is for Play and which is for Pause if you don't give them an id?

[edited by: Fotiman at 2:55 pm (utc) on Oct. 24, 2006]

JAB Creations

6:27 pm on Oct 24, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



If given the choice of being forced to degrade to HTML or save humanity I would have to have a cup of hot coco to think it over.

There is no play and pause sound in the desired script. The desired script will have a onmouseover and a onclick event with a sound for each event.

- John

Fotiman

7:18 pm on Oct 24, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Oh, ok, I get it.

In that case, maybe something like this?



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
<script type="text/javascript">
function getFlashMovieObject()
{
return document.getElementById("sound");
}
function PauseFlashMovie()
{
var flashMovie=getFlashMovieObject();
if( flashMovie )
{
flashMovie.StopPlay();
}
}
function PlayFlashMovie()
{
var flashMovie=getFlashMovieObject();
if( flashMovie )
{
flashMovie.Play();
}
}
page = function() {
return {
init : function() {
// Attach events
var aList = document.getElementsByTagName("A");
for( var i = 0; i < aList.length; i++ )
{
aList[i].onmouseover = PlayFlashMovie;
aList[i].onclick = PauseFlashMovie;
}
}
};
}();
window.onload = page.init;
</script>
</head>
<body>
<div>
<object data="examplesound.swf" id="sound" style="height: 20px; width: 20px;" type="application/x-shockwave-flash">
<param name="loop" value="false" />
<param name="movie" value="examplesound.swf" />
</object>
<a accesskey="3" href="#">Foo</a>
<a accesskey="4" href="#">Bar</a>
</div>
</body>
</html>

Fotiman

8:19 pm on Oct 24, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Forgot to mention, that would match an named links as well I believe. As in:

<a name="foo">Foo</a>

So you might also need to check for an href attribute on the item, or use document.links[] (that doesn't include named items I don't think... but haven't verified that).

JAB Creations

9:56 pm on Oct 24, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Rock on Fotiman! Thanks for the help. I had to modify the script a little to get two different IDs for onmouseover and click events though it was not too difficult. And now for future generations. ;)

This example requires you to create click.swf and over.swf Flash files. *See below for troubleshooting.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
<script type="text/javascript">
function OverFlashMovie()
{
function getFlashMovieObject()
{
return document.getElementById("over");
}
var flashMovie=getFlashMovieObject();
if( flashMovie )
{
flashMovie.Play();
}
}

function ClickFlashMovie()
{
function getFlashMovieObject()
{
return document.getElementById("click");
}

var flashMovie=getFlashMovieObject();
if( flashMovie )
{
flashMovie.Play();
}
}

page = function() {
return {
init : function() {
// Attach events
var aList = document.getElementsByTagName("A");
for( var i = 0; i < aList.length; i++ )
{
aList[i].onmouseover = OverFlashMovie;
aList[i].onclick = ClickFlashMovie;
}
}
};
}();
window.onload = page.init;
</script>
</head>
<body>
<div>
<object data="click.swf" id="click" style="height: 20px; width: 20px;" type="application/x-shockwave-flash">
<param name="loop" value="false" />
<param name="movie" value="click.swf" />
<param name="play" value="false" />
</object>
<object data="over.swf" id="over" style="height: 20px; width: 20px;" type="application/x-shockwave-flash">
<param name="loop" value="false" />
<param name="movie" value="over.swf" />
<param name="play" value="false" />
</object>
<div style="float: left; padding: 0px 8px 0px 8px;"><a accesskey="3" href="#">Foo</a></div>
<div style="float: left; padding: 0px 8px 0px 8px;"><a accesskey="4" href="#">Bar</a></div>
</div>
</body>
</html>

*This page was tested in Firefox 2.0. If you do not hear sounds after creating the images insert a blank keyframe before the sound in your Flash file and another blank keyframe only about three or four frames after where the audio ends.

- John

[edited by: JAB_Creations at 9:57 pm (utc) on Oct. 24, 2006]

JAB Creations

9:58 pm on Oct 24, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Fotiman, in reply to name="" post I stick strictly to XHTML and use id attributes for bookmarks instead of name attribute (as it has been deprecated in XHTML 1.1 with the exception of input elements for some strange reason).

- John

JAB Creations

12:38 am on Oct 25, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



A very important note to anyone coding to the current standards (XHTML 1.). XHTML 1.1 [b]must[b/] be served as application/xhtml+xml (though application/xml or text/xml are technically acceptable). The script needs to be [b]case sensitive[b/]!

Change...

var aList = document.getElementsByTagName("A");

To...

var aList = document.getElementsByTagName("a");

The script is hampering another script so I may post yet another reply to this once the bugs are ironed out.

- John

JAB Creations

1:08 am on Oct 25, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Ok there is a problem with the script. What I believe to be the issue causing the sound script to override the other scripts are the following lines...

aList[i].onmouseover = OverFlashMovie;
aList[i].onclick = ClickFlashMovie;

Some anchors need to explicitly use onmouseover and onclick JavaScript event attributes. I attempted to use return true/false after both these lines and only either one (but never both) scripts would work.

The example below will display a gray background div with a little text when the script works correctly. However it does not at the moment. Thanks for your help so far Fotiman!

Here is all the working code so far...

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
<script type="text/javascript">
//<![CDATA[
//
// Mouse Event Sounds
//
function OverFlashMovie()
{
function getFlashMovieObject()
{
return document.getElementById("over");
}
var flashMovie=getFlashMovieObject();
if( flashMovie )
{
flashMovie.Play();
}
}

function ClickFlashMovie()
{
function getFlashMovieObject()
{
return document.getElementById("click");
}

var flashMovie=getFlashMovieObject();
if( flashMovie )
{
flashMovie.Play();
}
}

page = function() {
return {
init : function() {
// Attach events
var aList = document.getElementsByTagName("a");
for( var i = 0; i < aList.length; i++ )
{
aList[i].onmouseover = OverFlashMovie;
aList[i].onclick = ClickFlashMovie;
}
}
};
}();
window.onload = page.init;

//
// Change Layer
//

function change(id, newClass)
{
identity=document.getElementById(id);
identity.className=newClass;
}

//
// Persistent Hover
//
var myTimeout;

function timedchange(id, newClass)
{
myTimeout = window.setTimeout(function() {document.getElementById(id).className=newClass;}, 400);
}
//]]>
</script>
<style type="text/css">
div.hidden {
display: none;
}
div.promptshow {
background: #bbb;
display: block;
}
</style>
</head>
<body>
<div>

<object data="click.swf" id="click" style="height: 20px; width: 20px;" type="application/x-shockwave-flash">
<param name="loop" value="false" />
<param name="movie" value="click.swf" />
<param name="play" value="false" />
</object>
<object data="over.swf" id="over" style="height: 20px; width: 20px;" type="application/x-shockwave-flash">
<param name="loop" value="false" />
<param name="movie" value="over.swf" />
<param name="play" value="false" />
</object>
<div style="float: left; padding: 0px 8px 0px 8px;"><a accesskey="3" href="#">Foo</a></div>
<div style="float: left; padding: 0px 8px 0px 8px;"><a accesskey="4" href="#">Bar</a></div>

<a accesskey="v" class="block" href="#" onclick="change('hiddendiv', 'promptshow');" onkeypress="if (event.keyCode == 9) return true; else change('hiddendiv', 'promptshow');">Display the hidden div</a>

<div class="hidden" id="hiddendiv">I was hiding!</div>

</div>
</body>
</html>

- John

Fotiman

3:17 pm on Oct 25, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




Fotiman, in reply to name="" post I stick strictly to XHTML and use id attributes for bookmarks instead of name attribute (as it has been deprecated in XHTML 1.1 with the exception of input elements for some strange reason).

The name attribute was not removed from inputs because, for example, there might be several inputs (radio buttons or checkboxes) representing the same piece of data.

Fotiman

3:27 pm on Oct 25, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




A very important note to anyone coding to the current standards (XHTML 1.).

Note, a quote from Ian Hickson:
"XHTML delivered as text/xml is risky, so authors intending their work for public consumption should stick to HTML 4.01, and authors who wish to use XHTML should deliver their markup as application/xhtml+xml"

Therefore, *most* web developers should be using HTML 4.01 instead of XHTML, unless you have a specific reason not to. And if you are goign to use XHTML, then yes, be sure you are delivering it properly (and be aware that IE6 doesn't support it... not sure about IE7).

[edited by: Fotiman at 3:28 pm (utc) on Oct. 25, 2006]

Fotiman

4:10 pm on Oct 25, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




Ok there is a problem with the script. What I believe to be the issue causing the sound script to override the other scripts are the following lines...

aList[i].onmouseover = OverFlashMovie;
aList[i].onclick = ClickFlashMovie;

Yes, this is replacing those event handlers. If you want to append them instead, you could:

1. Look into the Yahoo UI Library's Event Utility. I can't give this enough praise... it's good stuff. In that case, you would include the appropriate library scripts (yahoo.js, event.js, and possibly dom.js), and you would do this instead of the assignment above:

YAHOO.util.Event.addListener(aList[i],'mouseover',OverFlashMovie);
YAHOO.util.Event.addListener(aList[i],'click',ClickFlashMovie);

2. Alternatively, you could just record the existing event handler, and append yours on (But the Yahoo method is much easier). Here's how you could do it yourself:



page = function() {
function addEvent(elm, evType, fn, useCapture) {
if (elm.addEventListener) {
elm.addEventListener(evType, fn, useCapture);
return true;
}
else if (elm.attachEvent) {
var r = elm.attachEvent('on' + evType, fn);
return r;
}
else {
elm['on' + evType] = fn;
}
}
return {
init : function() {
// Attach events
var aList = document.getElementsByTagName("a");
for( var i = 0; i < aList.length; i++ )
{
addEvent(aList[i],'mouseover',OverFlashMovie);
addEvent(aList[i],'click',ClickFlashMovie);
}
}
};
}();

[edited by: Fotiman at 4:21 pm (utc) on Oct. 25, 2006]

JAB Creations

11:53 pm on Oct 25, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Fotiman you rock hard! Thank you so much!

You obviously have not read many of my posts as those who do know I'm a complete standards Nazi.

Anyway for the one or two people who will find this thread after endless searching here is the full blown working example (be sure to serve as application/xhtml+xml via serverside and to have the two Flash objects along with the file to get it to work.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
<script type="text/javascript">
//<![CDATA[
//
//
// Mouse Event Sounds
//
function OverFlashMovie()
{
function getFlashMovieObject()
{
return document.getElementById("over");
}
var flashMovie=getFlashMovieObject();
if( flashMovie )
{
flashMovie.Play();
}
}

function ClickFlashMovie()
{
function getFlashMovieObject()
{
return document.getElementById("click");
}

var flashMovie=getFlashMovieObject();
if( flashMovie )
{
flashMovie.Play();
}
}

page = function() {
function addEvent(elm, evType, fn, useCapture) {
if (elm.addEventListener) {
elm.addEventListener(evType, fn, useCapture);
return true;
}
else if (elm.attachEvent) {
var r = elm.attachEvent('on' + evType, fn);
return r;
}
else {
elm['on' + evType] = fn;
}
}
return {
init : function() {
// Attach events
var aList = document.getElementsByTagName("a");
for( var i = 0; i < aList.length; i++ )
{
addEvent(aList[i],'mouseover',OverFlashMovie);
addEvent(aList[i],'click',ClickFlashMovie);
}
}
};
}();
window.onload = page.init;

//
// Change Layer
//

function change(id, newClass)
{
identity=document.getElementById(id);
identity.className=newClass;
}

//]]>
</script>
<style type="text/css">
div.hidden {
display: none;
}
div.promptshow {
background: #bbb;
display: block;
}
</style>
</head>
<body>
<div>

<object data="click.swf" id="click" style="height: 20px; width: 20px;" type="application/x-shockwave-flash">
<param name="loop" value="false" />
<param name="movie" value="click.swf" />
<param name="play" value="false" />
</object>
<object data="over.swf" id="over" style="height: 20px; width: 20px;" type="application/x-shockwave-flash">
<param name="loop" value="false" />
<param name="movie" value="over.swf" />
<param name="play" value="false" />
</object>
<div style="float: left; padding: 0px 8px 0px 8px;"><a accesskey="3" href="#">Foo</a></div>
<div style="float: left; padding: 0px 8px 0px 8px;"><a accesskey="4" href="#">Bar</a></div>

<a accesskey="v" class="block" href="#" onclick="change('hiddendiv', 'promptshow');" onkeypress="if (event.keyCode == 9) return true; else change('hiddendiv', 'promptshow');">Display the hidden div</a>

<div class="hidden" id="hiddendiv">I was hiding!</div>

</div>
</body>
</html>

- John

[edited by: JAB_Creations at 11:53 pm (utc) on Oct. 25, 2006]