Soundcloud stratus播放器一次不会动态添加多个单独的曲目

时间:2014-04-24 05:43:14

标签: javascript jquery iframe soundcloud stratus

感谢其他人的问题,在DOM中点击时,我已经获得了AJAX链接来处理单个歌曲。我的问题是我需要找到一种方法来加载soundcloud上给定用户帐户下的所有曲目。我编辑了stratus.js文件,使其通过使用.delegate()来监听点击,但我无法弄清楚如何从soundcloud调用轨道列表并通过给定的iframe加载它。这是stratus.js文件。

(function() {
  var $;
  $ = jQuery;
  (function($){var g,d,j=1,a,b=this,f=!1,h="postMessage",e="addEventListener",c,i=b[h]&&!$.browser.opera;$[h]=function(k,l,m){if(!l){return}k=typeof k==="string"?k:$.param(k);m=m||parent;  if(i){m[h](k,l.replace(/([^:]+:\/\/[^\/]+).*/,"$1"))}else{if(l){m.location=l.replace(/#.*$/,"")+"#"+(+new Date)+(j++)+"&"+k}}};$.receiveMessage=c=function(l,m,k){if(i){if(l){a&&c();  a=function(n){if((typeof m==="string"&&n.origin!==m)||($.isFunction(m)&&m(n.origin)===f)){return f}l(n)}}if(b[e]){b[l?e:"removeEventListener"]("message",a,f)}  else{b[l?"attachEvent":"detachEvent"]("onmessage",a)}}else{g&&clearInterval(g);g=null;if(l){k=typeof m==="number"?m:typeof k==="number"?k:100;  g=setInterval(function(){var o=document.location.hash,n=/^#?\d+&/;if(o!==d&&n.test(o)){d=o;l({data:o.replace(n,"")})}},k)}}}})(jQuery);

  $.fn.stratus = function(settings) {
    return $.stratus(settings);
  };
  $.stratus = function(settings) {
    var root_url, src;
    root_url = settings.env === 'development' ? 'http://example.com:3000' : 'http://stratus.sc';
    $('head').append("<link rel='stylesheet' href='" + root_url + "/stratus.css' type='text/css'/>");
    if (settings.align === 'top') {
      $('head').append("<style>#stratus{ top: 0; }</style>");
    }
    if (settings.position === 'absolute') {
      $('head').append("<style>#stratus{ position: absolute; }</style>");
    }
    if (settings.offset) {
      $('head').append("<style>#stratus{ " + settings.align + ": " + settings.offset + "px !important; }</style>");
    }
    $('body').append("<div id='stratus'><iframe allowtransparency='true' frameborder='0' scrolling='0'></div>");
    src = root_url + '/player?' + $.param(settings, true) + '&link=' + encodeURIComponent(document.location.href);
    $('#stratus iframe').attr({
      src: src
    });
    $('#stratus iframe').load(function() {// /resolve?url=
      return $(this).css({
        visibility: 'visible'
      });
    });
    $('#stratus').show();
    $(document).delegate("a.stratus","click", function () {
      $.postMessage($(this).attr('href'), src, $('#stratus iframe')[0].contentWindow);
      return false;
    });

    return $.receiveMessage(function(e) {
      return $('#stratus').toggleClass('open');
    }, root_url);
  };
}).call(this);

我认为通过Soundcloud API进行调用是必要的,然后通过iframe运行用于添加单个轨道的用户数据。这是player.js文件,我不确定这篇文章是否必要,但它帮助我开始了解从可自定义的链接字段中添加曲目的初步情况:

console.log("Stratus loading...");
$(function() {
  var b, booleans, getScaledImageData, link, params, scApiUrl, source_origin, strtobool, timecode, _i, _len;
  window.Track = Backbone.Model.extend({
    initialize: function() {
      var that, track;
      that = this;
      track = this.attributes;
      track.timecode = timecode(track.duration);
      return soundManager.createSound({
        id: "sound_" + track.id,
        multiShot: false,
        url: track.stream_url + (/\?/.test(track.stream_url) ? '&' : '?') + 'consumer_key=' + Stratus.options.key,
        volume: Stratus.options.volume,
        whileplaying: function() {
          Stratus.$('.played').width((this.position / track.duration * 100) + '%');
          return Stratus.$('#player .duration').text(timecode(this.position) + ' / ' + timecode(track.duration));
        },
        whileloading: function() {
          return Stratus.$('.loaded').width((this.bytesLoaded / this.bytesTotal * 100) + '%');
        },
        onplay: function() {
          if (this.loaded) {
            return Stratus.$('.loaded').width('100%');
          }
        },
        onresume: function() {
          if (this.loaded) {
            return Stratus.$('.loaded').width('100%');
          }
        },
        onfinish: function() {
          return Stratus.nextTrack();
        }
      });
    },
    sound: function() {
      return "sound_" + this.id;
    },
    play: function() {
      return soundManager.play(this.sound());
    },
    pause: function() {
      return soundManager.pause(this.sound());
    },
    seek: function(relative) {
      return soundManager.setPosition(this.sound(), this.get('duration') * relative);
    },
    getWave: function(callback) {
      var that;
      that = this;
      return $.getJSON('http://wave64.heroku.com/w?callback=?', {
        url: this.get('waveform_url')
      }, function(data) {
        var waveform;
        waveform = new Image();
        waveform.src = data.data;
        return waveform.onload = function() {
          var waveform_data;
          waveform_data = getScaledImageData(waveform);
          that.set({
            'waveform_data': waveform_data
          });
          return callback();
        };
      });
    },
    comment: function(text) {
      return SC.post("/tracks/" + this.id + "/comments", {
        "comment[body]": text
      }, function() {
        Stratus.$('#comment input').val('');
        Stratus.toggleComment();
        return alert("Comment posted!");
      });
    },
    favorite: function() {
      if (Stratus.$('.love').hasClass('loved')) {
        return SC["delete"]("/me/favorites/" + this.id, function() {
          return Stratus.$('.love').removeClass('loved');
        });
      } else {
        return SC.put("/me/favorites/" + this.id, function() {
          return Stratus.$('.love').addClass('loved');
        });
      }
    },
    isFavorite: function() {
      return SC.get("/me/favorites/" + this.id, function(data) {
        if (!(data.errors != null)) {
          return Stratus.$('.love').addClass('loved');
        }
      });
    }
  });
  window.TrackList = Backbone.Collection.extend({
    model: Track,
    select: function(track) {
      this.stop();
      this.current = track;
      return this.trigger('player:select');
    },
    toggle: function(track) {
      if (track && this.current !== track) {
        this.select(track);
      }
      if (this.playing) {
        return this.pause();
      } else {
        return this.play();
      }
    },
    play: function(track) {
      if (track && this.current !== track) {
        this.select(track);
      }
      this.playing = true;
      this.current.play();
      return this.trigger('player:toggle');
    },
    pause: function() {
      this.playing = false;
      this.current.pause();
      return this.trigger('player:toggle');
    },
    stop: function() {
      this.playing = false;
      return soundManager.stopAll();
    },
    prev: function() {
      var i;
      i = this.indexOf(this.current) - 1;
      if (i > -1) {
        return this.at(i);
      } else {
        return this.last();
      }
    },
    next: function() {
      var i;
      i = this.indexOf(this.current) + 1;
      if (i < _.size(this)) {
        return this.at(i);
      } else {
        return this.first();
      }
    },
    random: function() {
      var i;
      i = Math.round(Math.random() * _.size(this));
      return this.at(i);
    }
  });
  window.Tracks = new TrackList();
  window.TrackView = Backbone.View.extend({
    tagName: "li",
    events: {
      "click": "toggleTrack"
    },
    render: function() {
      return $(this.el).html(ich.track(this.model.toJSON()));
    },
    toggleTrack: function() {
      return Tracks.toggle(this.model);
    }
  });
  window.AppView = Backbone.View.extend({
    el: $('#stratus'),
    defaults: {
      align: 'bottom',
      animate: 'slide',
      auto_play: false,
      buying: true,
      color: 'F60',
      download: true,
      env: 'production',
      key: 'ybtyKcnlhP3RKXpJ58fg',
      links: ['http://soundcloud.com/qotsa/sets/test'],
      random: false,
      redirect: 'http://stratus.sc/callback.html',
      user: true,
      stats: true,
      volume: 50
    },
    events: {
      "dblclick": "showDrawer",
      "click .prev": "prevTrack",
      "click .toggle": "toggleCurrent",
      "click .next": "nextTrack",
      "click #time": "seekTrack",
      "mousemove #time": "movePosition",
      "click .share": "toggleShare",
      "click .close.sharing": "toggleShare",
      "click .comment": "toggleComment",
      "click .close.commenting": "toggleComment",
      "keypress #add input": "commentTrack",
      "click .love": "favoriteTrack",
      "click #avatar": "logout",
      "click .popup": "popupPlayer"
    },
    initialize: function() {
      var options, that;
      console.log("Stratus initializing...");
      that = this;
      this.options = options = _.extend(this.defaults, this.options);
      Tracks.bind('add', this.add, this);
      Tracks.bind('player:select', this.render, this);
      Tracks.bind('player:toggle', this.toggle, this);
      SC.initialize({
        client_id: options.key,
        redirect_uri: options.redirect
      });
      return SC.whenStreamingReady(function() {
        return that.loadTracks(options.links, function() {
          Tracks.select(options.random ? Tracks.random() : Tracks.first());
          if (options.auto_play) {
            Tracks.play();
          }
          if (options.align === 'top') {
            options.top = true;
          }
          options.color = {
            base: tinycolor(options.color).toHexString(),
            light: tinycolor.lighten(options.color).toHexString(),
            dark: tinycolor.darken(options.color).toHexString()
          };
          $('head').append(ich.theme(options));
          if (SC.isConnected()) {
            that.updateUser();
          }
          return that.animate(function() {
            return that.resize();
          });
        });
      });
    },
    loadTracks: function(links, callback) {
      var index, loadURL;
      index = 0;
      loadURL = function(link) {
        var url;
        console.log("Loading " + link + "...");
        url = scApiUrl(link);
        return SC.get(url, function(data) {
          index += 1;
          if (data.tracks) {
            Tracks.add(data.tracks);
          } else if (data.username || data.creator) {
            links.push(data.uri + '/tracks');
          } else {
            Tracks.add(data);
          }
          if (links[index]) {
            return loadURL(links[index]);
          } else {
            return callback();
          }
        });
      };
      return loadURL(links[index]);
    },
    render: function() {
      var artwork, data, el, that, track;
      that = this;
      track = Tracks.current;
      data = Tracks.current.toJSON();
      el = this.$('#tracks .track_' + data.id);
      this.$('#player .track').html(ich.current(data));
      this.$('#buttons').html(ich.buttons(data));
      this.$('#stats').html(ich.stats(data));
      this.$('#share').html(ich.share(data));
      artwork = data.artwork_url ? data.artwork_url : data.user.avatar_url;
      this.$('#artwork img').attr({
        src: artwork.replace('-large', '-t300x300')
      });
      el.addClass('current').siblings().removeClass('current');
      if (track.has('waveform_data')) {
        this.updateWave(track);
      } else {
        track.getWave(function() {
          return that.updateWave(track);
        });
      }
      if (SC.isConnected()) {
        track.isFavorite();
      }
      return this.resize();
    },
    add: function(track) {
      var view;
      view = new TrackView({
        model: track,
        className: 'track track_' + track.id
      });
      return this.$("#tracks").append(view.render());
    },
    toggle: function() {
      return this.$('#player').toggleClass('playing', Tracks.playing);
    },
    toggleCurrent: function() {
      Tracks.toggle();
      return false;
    },
    prevTrack: function() {
      Tracks.play(Tracks.prev());
      return false;
    },
    nextTrack: function() {
      Tracks.play(Tracks.next());
      return false;
    },
    seekTrack: function(e) {
      var relative;
      if (!Tracks.playing) {
        Tracks.play();
      }
      relative = Math.min(this.$('.loaded').width(), (e.pageX - this.$('#time').offset().left) / this.$('#time').width());
      Tracks.current.seek(relative);
      return false;
    },
    movePosition: function(e) {
      return this.$('.position').css({
        "left": e.pageX - this.$('#time').offset().left
      });
    },
    updateWave: function(track) {
      var canvas, context;
      canvas = this.$('#waveform').get(0);
      context = canvas.getContext('2d');
      canvas.setAttribute('width', 180);
      canvas.setAttribute('height', 40);
      context.clearRect(0, 0, 180, 40);
      return context.putImageData(track.get('waveform_data'), 0, 0);
    },
    animate: function(callback) {
      if (this.options.popup) {
        this.$('#player, #drawer').fadeIn('slow');
      }
      switch (this.options.animate) {
        case 'slide':
          return this.$('#player').slideDown('slow', function() {
            return callback();
          });
        case 'fade':
          return this.$('#player').fadeIn('slow', function() {
            return callback();
          });
        default:
          return this.$('#player').show(0, function() {
            return callback();
          });
      }
    },
    resize: function() {
      this.$('#share').css({
        "margin-right": this.$('#buttons').width() - 30
      });
      return this.$('#comment').css({
        "margin-right": this.$('#buttons').width() - 60
      });
    },
    showDrawer: function() {
      this.$('#drawer').toggle();
      return $.postMessage(true, source_origin, parent);
    },
    popupPlayer: function() {
      Tracks.stop();
      this.toggle();
      return $.popupWindow($.url().attr('source') + '&popup=true', {
        height: 199,
        width: 800,
        location: false
      });
    },
    toggleShare: function() {
      this.$('#share').toggle();
      this.$('#share input').select();
      return false;
    },
    toggleComment: function() {
      var that;
      that = this;
      if (SC.isConnected()) {
        this.$('#comment').toggle();
        this.$('#comment input').select();
      } else {
        this.login(function() {
          return that.toggleComment();
        });
      }
      return false;
    },
    commentTrack: function(e) {
      var text;
      text = this.$('#comment input').val();
      if (e.keyCode === 13) {
        return Tracks.current.comment(text);
      }
    },
    favoriteTrack: function() {
      if (SC.isConnected()) {
        Tracks.current.favorite();
      } else {
        this.login(function() {
          return Tracks.current.favorite();
        });
      }
      return false;
    },
    login: function(callback) {
      var that;
      that = this;
      return SC.connect(function(user) {
        that.updateUser();
        return callback();
      });
    },
    updateUser: function() {
      var that;
      that = this;
      return SC.get("/me", function(user) {
        return that.$('#avatar').attr({
          src: user.avatar_url
        });
      });
    },
    logout: function() {
      SC.disconnect();
      return alert("Logged out.");
    }
  });
  link = decodeURIComponent($.url().param('link'));
  source_origin = $.url(link).attr('base');
  $.receiveMessage(function(e) {
    var result, url;
    url = e.data;
    result = Tracks.find(function(track) {
      return track.get('permalink_url') === url;
    });
    if (result) {
      return Tracks.toggle(result);
    } else {
      return SC.get("/resolve", {
        url: url
      }, function(track) {
        Tracks.add(track);
        return Tracks.play(Tracks.get(track.id));
      });
    }
  }, source_origin);
  scApiUrl = function(url) {
    if (/api\./.test(url)) {
      return url;
    } else {
      return "/resolve?url=" + url;
    }
  };
  timecode = function(ms) {
    return SC.Helper.millisecondsToHMS(ms);
  };
  strtobool = function(str) {
    switch (str) {
      case 'true':
        return true;
      case true:
        return true;
      default:
        return false;
    }
  };
  getScaledImageData = function(image) {
    var color, height, isImageData, lastIndex, orig, origCtx, origImageData, origWidth, populateScaledImagedData, precise, scaleX, scaleY, scaled, scaledCtx, scaledImageData, width, x, y;
    color = Stratus.$('#player').css('background-color');
    color = tinycolor(color).toRgb();
    precise = function(number, precision) {
      precision = Math.pow(10, precision || 0);
      return Math.round(number * precision) / precision;
    };
    populateScaledImagedData = function(x, y, srcImageData, indexOffset) {
      var alpha, index, indexScaled, isOpaque;
      indexOffset = indexOffset || 0;
      index = (Math.floor(y / scaleY) * origWidth + Math.floor(x / scaleX)) * 4;
      indexScaled = indexOffset + (y * width + x) * 4;
      alpha = srcImageData.data[index + 3];
      isOpaque = alpha === 255;
      scaledImageData.data[indexScaled] = isOpaque ? color['r'] : 0;
      scaledImageData.data[indexScaled + 1] = isOpaque ? color['g'] : 0;
      scaledImageData.data[indexScaled + 2] = isOpaque ? color['b'] : 0;
      scaledImageData.data[indexScaled + 3] = alpha;
      return indexScaled;
    };
    height = 40;
    width = 180;
    origWidth = image.width;
    scaleX = precise(width / image.width, 4);
    scaleY = precise(height / image.height, 4);
    try {
      isImageData = !(image instanceof Image);
    } catch (e) {
      isImageData = image.hasOwnProperty("data") && image.data.hasOwnProperty("length");
    }
    orig = document.createElement("canvas");
    orig.width = image.width;
    orig.height = image.height;
    origCtx = orig.getContext("2d");
    if (!isImageData) {
      origCtx.drawImage(image, 0, 0, image.width, image.height, 0, 0, image.width, image.height);
    } else {
      origCtx.putImageData(image, 0, 0);
    }
    origImageData = origCtx.getImageData(0, 0, image.width, image.height);
    scaled = document.createElement("canvas");
    scaled.width = width;
    scaled.height = height;
    scaledCtx = scaled.getContext("2d");
    scaledImageData = scaledCtx.getImageData(0, 0, width, height);
    y = 0;
    while (y < height) {
      x = 0;
      while (x < width) {
        lastIndex = populateScaledImagedData(x, y, origImageData, 0);
        x++;
      }
      y++;
    }
    return scaledImageData;
  };
  params = $.url().param();
  if (params.links) {
    params.links = decodeURIComponent(params.links);
    params.links = params.links.split(',');
  }
  if (params.redirect) {
    params.redirect = decodeURIComponent(params.redirect);
  }
  booleans = ['auto_play', 'buying', 'download', 'random', 'user', 'stats', 'popup'];
  for (_i = 0, _len = booleans.length; _i < _len; _i++) {
    b = booleans[_i];
    if (params[b]) {
      params[b] = strtobool(params[b]);
    }
  }
  return window.Stratus = new AppView(params);
});

我知道这是相当密集的,我为此道歉。只是抛出一个祈祷,我不会以负面的方式从根本上改变我的网站用户的体验。

1 个答案:

答案 0 :(得分:0)

我不了解层云播放器,但总的来说 - 如果你想要检索特定用户的曲目列表 - 假设你知道用户的id,你确实必须制作调用soundcloud API。你可以这样做:

  SC.initialize({
      client_id: "YOUR_CLIENT_ID",
      redirect_uri: "http://example.com/callback.html",
  });

/**
Once that's done you are all set and ready to call the SoundCloud API. 
**/

/**
Call to the SoundCloud API. 
Retrieves list of tracks, and displays a list with links to the tracks showing 'tracktitle' and 'track duration'
**/

  var userId = 39090345; // user_id of Prutsonic

  SC.get("/tracks", {
      user_id: userId,
      limit: 100
  }, function (tracks) {



      for (var i = 0; i < tracks.length; i++) {
          console.log(tracks[i].title);
      }

  });

你可以在这里试试我的小提琴:http://jsfiddle.net/tobiasbeuving/26pHX/5/

干杯, Ť