UNPKG

metro4

Version:

The front-end framework for Build responsive, mobile-first projects on the web with the first front-end component library in Metro Style

466 lines (374 loc) 13.9 kB
var Audio = { init: function( options, elem ) { this.options = $.extend( {}, this.options, options ); this.elem = elem; this.element = $(elem); this.preloader = null; this.player = null; this.audio = elem; this.stream = null; this.volume = null; this.volumeBackup = 0; this.muted = false; this._setOptionsFromDOM(); this._create(); return this; }, options: { playlist: null, src: null, volume: .5, loop: false, autoplay: false, showLoop: true, showPlay: true, showStop: true, showMute: true, showFull: true, showStream: true, showVolume: true, showInfo: true, showPlaylist: true, showNext: true, showPrev: true, showFirst: true, showLast: true, showForward: true, showBackward: true, showShuffle: true, showRandom: true, loopIcon: "<span class='default-icon-loop'></span>", stopIcon: "<span class='default-icon-stop'></span>", playIcon: "<span class='default-icon-play'></span>", pauseIcon: "<span class='default-icon-pause'></span>", muteIcon: "<span class='default-icon-mute'></span>", volumeLowIcon: "<span class='default-icon-low-volume'></span>", volumeMediumIcon: "<span class='default-icon-medium-volume'></span>", volumeHighIcon: "<span class='default-icon-high-volume'></span>", playlistIcon: "<span class='default-icon-playlist'></span>", nextIcon: "<span class='default-icon-next'></span>", prevIcon: "<span class='default-icon-prev'></span>", firstIcon: "<span class='default-icon-first'></span>", lastIcon: "<span class='default-icon-last'></span>", forwardIcon: "<span class='default-icon-forward'></span>", backwardIcon: "<span class='default-icon-backward'></span>", shuffleIcon: "<span class='default-icon-shuffle'></span>", randomIcon: "<span class='default-icon-random'></span>", onPlay: Metro.noop, onPause: Metro.noop, onStop: Metro.noop, onEnd: Metro.noop, onMetadata: Metro.noop, onTime: Metro.noop, onAudioCreate: Metro.noop }, _setOptionsFromDOM: function(){ var that = this, element = this.element, o = this.options; $.each(element.data(), function(key, value){ if (key in o) { try { o[key] = JSON.parse(value); } catch (e) { o[key] = value; } } }); }, _create: function(){ var that = this, element = this.element, o = this.options, audio = this.audio; this._createPlayer(); this._createControls(); this._createEvents(); if (o.autoplay === true) { this.play(); } Utils.exec(o.onAudioCreate, [element, this.player], element[0]); }, _createPlayer: function(){ var that = this, element = this.element, o = this.options, audio = this.audio; var prev = element.prev(); var parent = element.parent(); var player = $("<div>").addClass("media-player audio-player " + element[0].className); if (prev.length === 0) { parent.prepend(player); } else { player.insertAfter(prev); } element.appendTo(player); $.each(['muted', 'autoplay', 'controls', 'height', 'width', 'loop', 'poster', 'preload'], function(){ element.removeAttr(this); }); element.attr("preload", "auto"); audio.volume = o.volume; if (o.src !== null) { this._setSource(o.src); } element[0].className = ""; this.player = player; }, _setSource: function(src){ var element = this.element; element.find("source").remove(); element.removeAttr("src"); if (Array.isArray(src)) { $.each(src, function(){ var item = this; if (item.src === undefined) return ; $("<source>").attr('src', item.src).attr('type', item.type !== undefined ? item.type : '').appendTo(element); }); } else { element.attr("src", src); } }, _createControls: function(){ var that = this, element = this.element, o = this.options, audio = this.elem, player = this.player; var controls = $("<div>").addClass("controls").addClass(o.clsControls).insertAfter(element); var stream = $("<div>").addClass("stream").appendTo(controls); var streamSlider = $("<input>").addClass("stream-slider ultra-thin cycle-marker").appendTo(stream); var preloader = $("<div>").addClass("load-audio").appendTo(stream); var volume = $("<div>").addClass("volume").appendTo(controls); var volumeSlider = $("<input>").addClass("volume-slider ultra-thin cycle-marker").appendTo(volume); var infoBox = $("<div>").addClass("info-box").appendTo(controls); if (o.showInfo !== true) { infoBox.hide(); } preloader.activity({ type: "metro", style: "color" }); preloader.hide(0); this.preloader = preloader; streamSlider.slider({ clsMarker: "bg-red", clsHint: "bg-cyan fg-white", clsComplete: "bg-cyan", hint: true, onStart: function(){ if (!audio.paused) audio.pause(); }, onStop: function(val){ if (audio.seekable.length > 0) { audio.currentTime = (that.duration * val / 100).toFixed(0); } if (audio.paused && audio.currentTime > 0) { audio.play(); } } }); this.stream = streamSlider; if (o.showStream !== true) { stream.hide(); } volumeSlider.slider({ clsMarker: "bg-red", clsHint: "bg-cyan fg-white", hint: true, value: o.volume * 100, onChangeValue: function(val){ audio.volume = val / 100; } }); this.volume = volumeSlider; if (o.showVolume !== true) { volume.hide(); } var loop, play, stop, mute, full; if (o.showLoop === true) loop = $("<button>").attr("type", "button").addClass("button square loop").html(o.loopIcon).appendTo(controls); if (o.showPlay === true) play = $("<button>").attr("type", "button").addClass("button square play").html(o.playIcon).appendTo(controls); if (o.showStop === true) stop = $("<button>").attr("type", "button").addClass("button square stop").html(o.stopIcon).appendTo(controls); if (o.showMute === true) mute = $("<button>").attr("type", "button").addClass("button square mute").html(o.muteIcon).appendTo(controls); if (o.loop === true) { loop.addClass("active"); element.attr("loop", "loop"); } this._setVolume(); if (o.muted) { that.volumeBackup = audio.volume; that.volume.data('slider').val(0); audio.volume = 0; } infoBox.html("00:00 / 00:00"); }, _createEvents: function(){ var that = this, element = this.element, o = this.options, audio = this.elem, player = this.player; element.on("loadstart", function(){ that.preloader.fadeIn(); }); element.on("loadedmetadata", function(){ that.duration = audio.duration.toFixed(0); that._setInfo(0, that.duration); Utils.exec(o.onMetadata, [audio, player], element[0]); }); element.on("canplay", function(){ that._setBuffer(); that.preloader.fadeOut(); }); element.on("progress", function(){ that._setBuffer(); }); element.on("timeupdate", function(){ var position = Math.round(audio.currentTime * 100 / that.duration); that._setInfo(audio.currentTime, that.duration); that.stream.data('slider').val(position); Utils.exec(o.onTime, [audio.currentTime, that.duration, audio, player], element[0]); }); element.on("waiting", function(){ that.preloader.fadeIn(); }); element.on("loadeddata", function(){ }); element.on("play", function(){ player.find(".play").html(o.pauseIcon); Utils.exec(o.onPlay, [audio, player], element[0]); }); element.on("pause", function(){ player.find(".play").html(o.playIcon); Utils.exec(o.onPause, [audio, player], element[0]); }); element.on("stop", function(){ that.stream.data('slider').val(0); Utils.exec(o.onStop, [audio, player], element[0]); }); element.on("ended", function(){ that.stream.data('slider').val(0); Utils.exec(o.onEnd, [audio, player], element[0]); }); element.on("volumechange", function(){ that._setVolume(); }); player.on(Metro.events.click, ".play", function(){ if (audio.paused) { that.play(); } else { that.pause(); } }); player.on(Metro.events.click, ".stop", function(){ that.stop(); }); player.on(Metro.events.click, ".mute", function(){ that._toggleMute(); }); player.on(Metro.events.click, ".loop", function(){ that._toggleLoop(); }); }, _toggleLoop: function(){ var loop = this.player.find(".loop"); if (loop.length === 0) return ; loop.toggleClass("active"); if (loop.hasClass("active")) { this.element.attr("loop", "loop"); } else { this.element.removeAttr("loop"); } }, _toggleMute: function(){ this.muted = !this.muted; if (this.muted === false) { this.audio.volume = this.volumeBackup; this.volume.data('slider').val(this.volumeBackup * 100); } else { this.volumeBackup = this.audio.volume; this.volume.data('slider').val(0); this.audio.volume = 0; } }, _setInfo: function(a, b){ this.player.find(".info-box").html(Utils.secondsToFormattedString(Math.round(a)) + " / " + Utils.secondsToFormattedString(Math.round(b))); }, _setBuffer: function(){ var buffer = this.audio.buffered.length ? Math.round(Math.floor(this.audio.buffered.end(0)) / Math.floor(this.audio.duration) * 100) : 0; this.stream.data('slider').buff(buffer); }, _setVolume: function(){ var audio = this.audio, player = this.player, o = this.options; var volumeButton = player.find(".mute"); var volume = audio.volume * 100; if (volume > 1 && volume < 30) { volumeButton.html(o.volumeLowIcon); } else if (volume >= 30 && volume < 60) { volumeButton.html(o.volumeMediumIcon); } else if (volume >= 60 && volume <= 100) { volumeButton.html(o.volumeHighIcon); } else { volumeButton.html(o.muteIcon); } }, play: function(src){ if (src !== undefined) { this._setSource(src); } if (this.element.attr("src") === undefined && this.element.find("source").length === 0) { return ; } this.audio.play(); }, pause: function(){ this.audio.pause(); }, resume: function(){ if (this.audio.paused) { this.play(); } }, stop: function(){ this.audio.pause(); this.audio.currentTime = 0; this.stream.data('slider').val(0); }, volume: function(v){ if (v === undefined) { return this.audio.volume; } if (v > 1) { v /= 100; } this.audio.volume = v; this.volume.data('slider').val(v*100); }, loop: function(){ this._toggleLoop(); }, mute: function(){ this._toggleMute(); }, changeSource: function(){ var src = JSON.parse(this.element.attr('data-src')); this.play(src); }, changeVolume: function(){ var volume = this.element.attr("data-volume"); this.volume(volume); }, changeAttribute: function(attributeName){ switch (attributeName) { case "data-src": this.changeSource(); break; case "data-volume": this.changeVolume(); break; } }, destroy: function(){ var element = this.element, player = this.player; element.off("loadstart"); element.off("loadedmetadata"); element.off("canplay"); element.off("progress"); element.off("timeupdate"); element.off("waiting"); element.off("loadeddata"); element.off("play"); element.off("pause"); element.off("stop"); element.off("ended"); element.off("volumechange"); player.off(Metro.events.click, ".play"); player.off(Metro.events.click, ".stop"); player.off(Metro.events.click, ".mute"); player.off(Metro.events.click, ".loop"); Metro.destroyPlugin(this.stream, "slider"); Metro.destroyPlugin(this.volume, "slider"); element.insertBefore(player); player.html("").remove(); } }; Metro.plugin('audio', Audio);