Jump To …
360player.js flashblock.css mp3-player-button.js mpc.js page-player.js inlineplayer.js soundmanager2.js SoundManager2.as SoundManager2_AS3.as SoundManager2_SMSound_AS3.as

# inlineplayer.js |
--- | ---
¶ ## 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.sID);
            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
          });
¶ 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.sID);
        soundManager.unload(oSound.sID);
      }

      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.debugMode = true; // disable or enable debug output

    soundManager.preferFlash = false; // use HTML5 audio for MP3/MP4, if available
    soundManager.useFlashBlock = true;
    soundManager.url = '../../swf/'; // path to directory containing SM2 SWF
¶ optional: enable MPEG-4/AAC support (requires flash 9) |
    soundManager.flashVersion = 9;
¶ |
    soundManager.onready(function() {
¶ soundManager.createSound() etc. may now be called |
      inlinePlayer = new InlinePlayer();
    });