257 lines
7.9 KiB
JavaScript
257 lines
7.9 KiB
JavaScript
/**
|
|
*
|
|
* SoundManager 2 Demo: Play MP3 links "in-place"
|
|
* ----------------------------------------------
|
|
*
|
|
* http://schillmania.com/projects/soundmanager2/
|
|
*
|
|
* A simple demo making MP3s playable "inline"
|
|
* and easily styled/customizable via CSS.
|
|
*
|
|
* Requires SoundManager 2 Javascript API.
|
|
*
|
|
*/
|
|
|
|
function InlinePlayer() {
|
|
var self = this;
|
|
var pl = this;
|
|
var sm = soundManager; // soundManager instance
|
|
var isIE = (navigator.userAgent.match(/msie/i));
|
|
this.playableClass = 'inline-playable'; // CSS class for forcing a link to be playable (eg. doesn't have .MP3 in it)
|
|
this.excludeClass = 'inline-exclude'; // CSS class for ignoring MP3 links
|
|
this.links = [];
|
|
this.sounds = [];
|
|
this.soundsByURL = [];
|
|
this.indexByURL = [];
|
|
this.lastSound = null;
|
|
this.soundCount = 0;
|
|
|
|
this.config = {
|
|
playNext: false, // stop after one sound, or play through list until end
|
|
autoPlay: false // start playing the first sound right away
|
|
}
|
|
|
|
this.css = {
|
|
// CSS class names appended to link during various states
|
|
sDefault: 'sm2_link', // default state
|
|
sLoading: 'sm2_loading',
|
|
sPlaying: 'sm2_playing',
|
|
sPaused: 'sm2_paused'
|
|
}
|
|
|
|
this.addEventHandler = (typeof window.addEventListener !== 'undefined' ? function(o, evtName, evtHandler) {
|
|
return o.addEventListener(evtName,evtHandler,false);
|
|
} : function(o, evtName, evtHandler) {
|
|
o.attachEvent('on'+evtName,evtHandler);
|
|
});
|
|
|
|
this.removeEventHandler = (typeof window.removeEventListener !== 'undefined' ? function(o, evtName, evtHandler) {
|
|
return o.removeEventListener(evtName,evtHandler,false);
|
|
} : function(o, evtName, evtHandler) {
|
|
return o.detachEvent('on'+evtName,evtHandler);
|
|
});
|
|
|
|
this.classContains = function(o,cStr) {
|
|
return (typeof(o.className)!='undefined'?o.className.match(new RegExp('(\\s|^)'+cStr+'(\\s|$)')):false);
|
|
}
|
|
|
|
this.addClass = function(o,cStr) {
|
|
if (!o || !cStr || self.classContains(o,cStr)) return false;
|
|
o.className = (o.className?o.className+' ':'')+cStr;
|
|
}
|
|
|
|
this.removeClass = function(o,cStr) {
|
|
if (!o || !cStr || !self.classContains(o,cStr)) return false;
|
|
o.className = o.className.replace(new RegExp('( '+cStr+')|('+cStr+')','g'),'');
|
|
}
|
|
|
|
this.getSoundByURL = function(sURL) {
|
|
return (typeof self.soundsByURL[sURL] != 'undefined'?self.soundsByURL[sURL]:null);
|
|
}
|
|
|
|
this.isChildOfNode = function(o,sNodeName) {
|
|
if (!o || !o.parentNode) {
|
|
return false;
|
|
}
|
|
sNodeName = sNodeName.toLowerCase();
|
|
do {
|
|
o = o.parentNode;
|
|
} while (o && o.parentNode && o.nodeName.toLowerCase() != sNodeName);
|
|
return (o.nodeName.toLowerCase() == sNodeName?o:null);
|
|
}
|
|
|
|
this.events = {
|
|
|
|
// handlers for sound events as they're started/stopped/played
|
|
|
|
play: function() {
|
|
pl.removeClass(this._data.oLink,this._data.className);
|
|
this._data.className = pl.css.sPlaying;
|
|
pl.addClass(this._data.oLink,this._data.className);
|
|
},
|
|
|
|
stop: function() {
|
|
pl.removeClass(this._data.oLink,this._data.className);
|
|
this._data.className = '';
|
|
},
|
|
|
|
pause: function() {
|
|
pl.removeClass(this._data.oLink,this._data.className);
|
|
this._data.className = pl.css.sPaused;
|
|
pl.addClass(this._data.oLink,this._data.className);
|
|
},
|
|
|
|
resume: function() {
|
|
pl.removeClass(this._data.oLink,this._data.className);
|
|
this._data.className = pl.css.sPlaying;
|
|
pl.addClass(this._data.oLink,this._data.className);
|
|
},
|
|
|
|
finish: function() {
|
|
pl.removeClass(this._data.oLink,this._data.className);
|
|
this._data.className = '';
|
|
if (pl.config.playNext) {
|
|
var nextLink = (pl.indexByURL[this._data.oLink.href]+1);
|
|
if (nextLink<pl.links.length) {
|
|
pl.handleClick({'target':pl.links[nextLink]});
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
this.stopEvent = function(e) {
|
|
if (typeof e != 'undefined' && typeof e.preventDefault != 'undefined') {
|
|
e.preventDefault();
|
|
} else if (typeof event != 'undefined' && typeof event.returnValue != 'undefined') {
|
|
event.returnValue = false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
this.getTheDamnLink = (isIE)?function(e) {
|
|
// I really didn't want to have to do this.
|
|
return (e && e.target?e.target:window.event.srcElement);
|
|
}:function(e) {
|
|
return e.target;
|
|
}
|
|
|
|
this.handleClick = function(e) {
|
|
// a sound link was clicked
|
|
if (typeof e.button != 'undefined' && e.button>1) {
|
|
// ignore right-click
|
|
return true;
|
|
}
|
|
var o = self.getTheDamnLink(e);
|
|
if (o.nodeName.toLowerCase() != 'a') {
|
|
o = self.isChildOfNode(o,'a');
|
|
if (!o) return true;
|
|
}
|
|
var sURL = o.getAttribute('href');
|
|
if (!o.href || (!sm.canPlayLink(o) && !self.classContains(o,self.playableClass)) || self.classContains(o,self.excludeClass)) {
|
|
return true; // pass-thru for non-MP3/non-links
|
|
}
|
|
var soundURL = (o.href);
|
|
var thisSound = self.getSoundByURL(soundURL);
|
|
if (thisSound) {
|
|
// already exists
|
|
if (thisSound == self.lastSound) {
|
|
// and was playing (or paused)
|
|
thisSound.togglePause();
|
|
} else {
|
|
// different sound
|
|
sm._writeDebug('sound different than last sound: '+self.lastSound.id);
|
|
if (self.lastSound) {
|
|
self.stopSound(self.lastSound);
|
|
}
|
|
thisSound.togglePause(); // start playing current
|
|
}
|
|
} else {
|
|
// stop last sound
|
|
if (self.lastSound) {
|
|
self.stopSound(self.lastSound);
|
|
}
|
|
// create sound
|
|
thisSound = sm.createSound({
|
|
id:'inlineMP3Sound'+(self.soundCount++),
|
|
url:soundURL,
|
|
onplay:self.events.play,
|
|
onstop:self.events.stop,
|
|
onpause:self.events.pause,
|
|
onresume:self.events.resume,
|
|
onfinish:self.events.finish,
|
|
type:(o.type||null)
|
|
});
|
|
// tack on some custom data
|
|
thisSound._data = {
|
|
oLink: o, // DOM node for reference within SM2 object event handlers
|
|
className: self.css.sPlaying
|
|
};
|
|
self.soundsByURL[soundURL] = thisSound;
|
|
self.sounds.push(thisSound);
|
|
thisSound.play();
|
|
}
|
|
|
|
self.lastSound = thisSound; // reference for next call
|
|
|
|
if (typeof e != 'undefined' && typeof e.preventDefault != 'undefined') {
|
|
e.preventDefault();
|
|
} else {
|
|
event.returnValue = false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
this.stopSound = function(oSound) {
|
|
soundManager.stop(oSound.id);
|
|
soundManager.unload(oSound.id);
|
|
}
|
|
|
|
this.init = function() {
|
|
sm._writeDebug('inlinePlayer.init()');
|
|
var oLinks = document.getElementsByTagName('a');
|
|
// grab all links, look for .mp3
|
|
var foundItems = 0;
|
|
for (var i=0, j=oLinks.length; i<j; i++) {
|
|
if ((sm.canPlayLink(oLinks[i]) || self.classContains(oLinks[i],self.playableClass)) && !self.classContains(oLinks[i],self.excludeClass)) {
|
|
self.addClass(oLinks[i],self.css.sDefault); // add default CSS decoration
|
|
self.links[foundItems] = (oLinks[i]);
|
|
self.indexByURL[oLinks[i].href] = foundItems; // hack for indexing
|
|
foundItems++;
|
|
}
|
|
}
|
|
if (foundItems>0) {
|
|
self.addEventHandler(document,'click',self.handleClick);
|
|
if (self.config.autoPlay) {
|
|
self.handleClick({target:self.links[0],preventDefault:function(){}});
|
|
}
|
|
}
|
|
sm._writeDebug('inlinePlayer.init(): Found '+foundItems+' relevant items.');
|
|
}
|
|
|
|
this.init();
|
|
|
|
}
|
|
|
|
var inlinePlayer = null;
|
|
|
|
soundManager.setup({
|
|
// disable or enable debug output
|
|
debugMode: true,
|
|
// use HTML5 audio for MP3/MP4, if available
|
|
preferFlash: false,
|
|
useFlashBlock: true,
|
|
// path to directory containing SM2 SWF
|
|
url: '../../swf/',
|
|
// optional: enable MPEG-4/AAC support (requires flash 9)
|
|
flashVersion: 9
|
|
});
|
|
|
|
// ----
|
|
|
|
soundManager.onready(function() {
|
|
// soundManager.createSound() etc. may now be called
|
|
inlinePlayer = new InlinePlayer();
|
|
});
|
|
|