| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 | /** * Created by intelWorx on 19/11/2015. */(function () {  'use strict';  /**   * Main module, your application should depend on this   * @module {mdWavesurfer}   */  var app = angular.module('mdWavesurfer', ['ngMaterial']);  /**   * @ngdoc service   * @name $mdWavesurferUtils   *   * @description   *   * Utility service for this directive, exposes method:   *  - getLength(url), which returns a promise for the length of the audio specified by URL   *   * ```js   * app.directive('myFancyDirective', function(mdWavesurferUtils) {   *   return {   *     restrict: 'e',   *     link: function(scope, el, attrs) {   *       mdWavesurferUtils(attrs.url)   *       .then(function(l){   *        scope.length = l;   *       }, function(){   *          someErrorhandler()   *       })   *       ;   *     }   *   };   * });   * ```   */  app.factory('mdWavesurferUtils', ['$q', '$document', '$timeout',    function ($q, $document, $timeout) {      return {        getLength: function (object) {          var deferred = $q.defer();          var estimateLength = function (url) {            var audio = $document[0].createElement('audio');            audio.src = url;            audio.addEventListener('loadeddata', function listener() {              deferred.resolve(this.duration);              audio.removeEventListener('loadeddata', listener);              audio.src = 'data:audio/mpeg,0';//destroy loading.            });            audio.addEventListener('error', function (e) {              deferred.resolve(e.target.error);            });          };          if (typeof object === 'string') {            //this is a URL            estimateLength(object);          } else {            $timeout(function () {              deferred.reject(new DOMError("NotSupportedError", "Specified argument is not supported"));            });          }          return deferred.promise;        }      };    }  ]);  /**   * @ngdoc filter   * @name mdWavesurferTimeFormat   *   * Simple filter to convert value in seconds to MM:SS format   *   * @param Number duration in seconds   */  app.filter('mdWavesurferTimeFormat', function () {    return function (input) {      if (!input) {        return "00:00";      }      var minutes = Math.floor(input / 60);      var seconds = Math.ceil(input) % 60;      return (minutes < 10 ? '0' : '')        + minutes        + ":"        + (seconds < 10 ? '0' : '') + seconds;    };  });  app.controller('mdWavesurferAudioController', ['$attrs', '$element',    function (attributes, $element) {      var audio = this;      audio.tracks = [];      audio.selectedIndex = audio.selectedIndex || 0;      audio.currentTrack = null;      //adds to an audio track      audio.addTrack = function (trackScope) {        if (audio.tracks.indexOf(trackScope) < 0) {          audio.tracks.push(trackScope);        }        if (!audio.currentTrack) {          audio.currentTrack = audio.tracks[audio.selectedIndex];        }      };      //remove audio track      audio.removeTrack = function (trackScope) {        var idx = audio.tracks.indexOf(trackScope);        if (idx >= 0) {          audio.tracks.splice(idx, 1);        }      };      audio.playerProperties = {}      var nKey;      for (var attr in attributes) {        if (attr.match(/^player/)) {          nKey = attr.replace(/^player([A-Z])/, function (m, $1) {            return $1.toLowerCase();          });          audio.playerProperties[nKey] = attributes[attr];        }      }      var getPlayer = function(){        return $element.find('md-wavesurfer-player').controller('mdWavesurferPlayer');      };      var setAutoPlay = function (forcePlay) {        var controller = getPlayer();        if (controller && (forcePlay || controller.surfer.isPlaying())) {          controller.autoPlay = true;        }      };      audio.setTrack = function (idx, forcePlay) {        if (audio.tracks.length > idx) {          if (audio.selectedIndex === idx) {            var ctrl = getPlayer();            ctrl.surfer.playPause();          } else {            setAutoPlay(forcePlay);            audio.currentTrack = audio.tracks[idx];            audio.selectedIndex = idx;          }        }      };      audio.extraButtons = [{        icon: 'zmdi zmdi-skip-previous',        title: 'Previous',        action: function ($event) {          if (audio.selectedIndex > 0) {            audio.setTrack(audio.selectedIndex - 1);          }        },        class: ''      }, {        icon: 'zmdi zmdi-skip-next',        title: 'Next',        action: function ($event) {          if (audio.selectedIndex < audio.tracks.length - 1) {            audio.setTrack(audio.selectedIndex + 1);          }        },        class: ''      }];    }  ]);  /**   * @ngdoc directive   * @name md-wavesurfer-audio   *   * Directive for playing a set of audio files. This directive is analogous to `<audio>` HTML tag.   * The audio files, should be specified using the  `md-wavesurfer-source`   *   * WaveSurfer properties can be passed in using the prefix : player-* for attributes, e.g. `player-wave-color` is   * equivalent to WaveSurfer's waveColor option.   *   * Must be used as an element.   *   * @usage   * ```html   * <md-wavesurfer-audio player-wave-color="gray" player-progress-color="black" player-backend="MediaElement">   *   <md-wavesurfer-source src="source1" title="Title-1"></md-wavesurfer-source>   *   <md-wavesurfer-source src="source2" title="Title-2"></md-wavesurfer-source>   *   <md-wavesurfer-source src="source3" title="Title-3"></md-wavesurfer-source>   *   ...   *   <md-wavesurfer-source src="sourceN" title="Рассказы о сновидениях"></md-wavesurfer-source>   * </md-wavesurfer-audio>   * ```   *   * @param string player-* specifies WaveSurfer properties.   *   */  app.directive('mdWavesurferAudio', [    function () {      return {        restrict: 'E',        templateUrl: 'md-player-audio.partial.html',        transclude: true,        controller: 'mdWavesurferAudioController',        controllerAs: 'audio'      };    }  ]);  /**   * @ngdoc directive   *   * @name md-wavesurfer-source   *   * This directive is used within the `md-wavesurfer-audio` directive to specify an audio file source, it is   * synonymous to `<source>` tag in HTML   *   * The directive cannot be used as standalone.   *   * @usage   *   * ```html   *   <md-wavesurfer-source src="source3" title="Title-3" album-art="Album-Art-Url" duration=""></md-wavesurfer-source>   * ```   * @param String src the URL to the audio file, this is required.   * @param String title track title   * @param String album-art the album art URL   * @param Number duration the length of the audio file in seconds, will be auto-detected if not specified.   *   */  app.directive('mdWavesurferSource', ['mdWavesurferUtils',    function (mdWavesurferUtils) {      return {        restrict: 'E',        require: '^mdWavesurferAudio',        scope: {          src: '@',          albumArt: '@',          title: '@',          duration: '='        },        link: function (scope, element, attrs, audio) {          audio.addTrack(scope);          if (!scope.duration) {            mdWavesurferUtils.getLength(scope.src).then(function (dur) {              scope.duration = dur;            }, function (e) {              scope.duration = 0;              console.log('Failed to get audio length, reason: ', e.message);            });          }          element.on('$destroy', function () {            audio.removeTrack(audio);          });        }      };    }  ]);  app.controller('mdWavesurferPlayerController', ['$element', '$scope', '$attrs', '$interval', '$mdTheming',    function ($element, $scope, attributes, $interval, $mdTheme) {      var control = this, timeInterval;      control.themeClass = "md-" + $mdTheme.defaultTheme() + "-theme";      control.isReady = false;      control.surfer = null;      control.toggleMute = function () {        if (control.surfer) {          control.surfer.toggleMute();          control.isMute = !control.isMute;        }      };      var initWaveSurfer = function () {        control.isReady = false;        control.currentTime = 0;        if (!control.surfer) {          var options = {            container: $element[0].querySelector('.waveSurferWave')          }, defaults = {            scrollParent: true,            waveColor: 'violet',            progressColor: 'purple'          };          options = angular.extend(defaults, attributes, (control.properties || {}), options);          control.surfer = WaveSurfer.create(options);          control.surfer.on('ready', function () {            control.isReady = true;            if (control.autoPlay) {              control.surfer.play();            }            $scope.$apply();          });          control.surfer.on('pause', function () {            stopInterval();          });          control.surfer.on('finish', function () {            stopInterval();          });          control.surfer.on('play', function () {            startInterval();          });        }        control.title = control.title || control.src.split('/').pop();        control.surfer.load(control.src);      };      var startInterval = function () {        timeInterval = $interval(function () {          control.currentTime = control.isReady ? control.surfer.getCurrentTime() : 0;        }, 1000);      }, stopInterval = function () {        $interval.cancel(timeInterval);      };      initWaveSurfer();      $scope.$watch('control.src', function (src1, src2) {        if (src1 != src2) {          initWaveSurfer();        }      });      $element.on('$destroy', function () {        if (control.surfer) {          control.surfer.destroy();        }        stopInterval();      });      $scope.$watch(function () {        var div = $element[0].querySelector('.audioPlayerWrapper');        return div ? div.offsetWidth : 0;      }, function (width) {        if (width < 1) {          //hidden          control.surfer.pause();        }      });    }  ]);  /**   * @ngdoc directive   *   * @name md-wavesurfer-player   *   * @usage   * This directive can be used as a stand-alone directive to display Audio WaveSurfer with a few controls, by default   * this will only display play/pause, fast-forward, rewind and mute toggle buttons, however, you can add extra   * buttons using the `extra-buttons` parameters.   *   * ```html   *  <md-wavesurfer-player url="trackUrl" title="Track Title"   *         extra-buttons="extraButtons" properties="properties">   *  </md-wavesurfer-player>   * ```   *   * @param {string} url the URL of the audio file   * @param {string} title title of the audio track   * @param {object} properties an object specifying init options for WaveSurfer   * @param {boolean} auto-play specifies if the player should start as soon as it's loaded.   * @param {object[]} extra-buttons a list of extra buttons to add to the control panel   *    each button should be an object with the following properties:   *    {   *      title: "button title"   *      action: "call back to call when button is clicked, executed in parent scope",   *      icon: "md-font-icon parameter for the button"   *      class: "extra classes to add to the button."   *    }   *   * Every other attribute passed to this directive is assumed to a WaveSurver init parameter.   */  app.directive('mdWavesurferPlayer', function () {    return {      restrict: 'E',      templateUrl: 'md-player.partial.html',      scope: {        src: '@url',        title: '@',        extraButtons: '=',        toolbarClass: '@',        autoPlay: '=',        properties: '='      },      controller: 'mdWavesurferPlayerController',      controllerAs: 'control',      bindToController: true    };  });  ;})();
 |