如何在javascript中访问rails视图变量?

时间:2016-03-09 04:15:53

标签: javascript ruby-on-rails

我是铁杆新手,我只想使用javascript提取rails对象和属性(@ tracks.audio)。我想动态地从db应用音频文件,而不是使用在注释行1,2,3

上看到的硬编码版本

这是tracks.js.erb

    // Event listener for DOM
document.addEventListener("DOMContentLoaded", theDOMHasLoaded, false);

// array of audio files (stored in a folder called music)
var files = ["<% @tracks.audio %>" , // this code doesn't work!
      "chooseyourweapon.mp3", // 1
      "interlude.mp3", // 2
      "scriptures.mp3" // 3
      ];

///////////////////////////////////////////////
// Find and store audio info
///////////////////////////////////////////////

// array for AudioObjects
var audioList = [];
// components and the index for their AudioObject
var componentDict = {};
// store AudioObject that is currently playing
var playingAudio = null;
// store playhead id if one is being dragged
var onplayhead = null;

/* AudioObject Constructor */
function AudioObject(audio, duration) {
  this.audio = audio;
  this.id = audio.id;
  this.duration = duration;
}
/* bindAudioPlayer
 * Store audioplayer components in correct AudioObject
 * num identifes correct audioplayer
 */
AudioObject.prototype.bindAudioPlayer = function (num) {
  this.audioplayer = document.getElementById("audioplayer-" + num);
  this.playbutton = document.getElementById("playbutton-" + num);
  this.timeline = document.getElementById("timeline-" + num);
  this.playhead = document.getElementById("playhead-" + num);
  this.timelineWidth = this.timeline.offsetWidth - this.playhead.offsetWidth
}

/* addEventListeners() */
AudioObject.prototype.addEventListeners = function () {
  this.audio.addEventListener("timeupdate", AudioObject.prototype.timeUpdate, false);
  this.audio.addEventListener("durationchange", AudioObject.prototype.durationChange, false);
  this.timeline.addEventListener("click", AudioObject.prototype.timelineClick, false);
  this.playbutton.addEventListener("click", AudioObject.prototype.pressPlay, false);
  // Makes playhead draggable 
  this.playhead.addEventListener('mousedown', AudioObject.prototype.mouseDown, false);
  window.addEventListener('mouseup', mouseUp, false);
}

/* populateAudioList */
function populateAudioList() {
  var audioElements = document.getElementsByClassName("audio");
  for (i = 0; i < audioElements.length; i++) {
    audioList.push(
      new AudioObject(audioElements[i], 0)
    );
    audioList[i].bindAudioPlayer(i);
    audioList[i].addEventListeners();
  }
}

/* populateComponentDictionary() 
 * {key=element id : value=index of audioList} */
function populateComponentDictionary() {
  for (i = 0; i < audioList.length; i++) {
    componentDict[audioList[i].audio.id] = i;
    componentDict[audioList[i].playbutton.id] = i;
    componentDict[audioList[i].timeline.id] = i;
    componentDict[audioList[i].playhead.id] = i;
  }
}

///////////////////////////////////////////////
// Update Audio Player
///////////////////////////////////////////////

/* durationChange
 * set duration for AudioObject */
AudioObject.prototype.durationChange = function () {
  var ao = audioList[getAudioListIndex(this.id)];
  ao.duration = this.duration;
}

/* pressPlay() 
 * call play() for correct AudioObject
 */
AudioObject.prototype.pressPlay = function () {
  var index = getAudioListIndex(this.id);
  audioList[index].play();
}

/* play() 
 * play or pause selected audio, if there is a song playing pause it
 */
AudioObject.prototype.play = function () {
  if (this == playingAudio) {
    playingAudio = null;
    this.audio.pause();
    changeClass(this.playbutton, "playbutton play");
  }
  // else check if playing audio exists and pause it, then start this
  else {
    if (playingAudio != null) {
      playingAudio.audio.pause();
      changeClass(playingAudio.playbutton, "playbutton play");
    }
    this.audio.play();
    playingAudio = this;
    changeClass(this.playbutton, "playbutton pause");
  }
}

/* timelineClick()
 * get timeline's AudioObject
 */
AudioObject.prototype.timelineClick = function (event) {
  var ao = audioList[getAudioListIndex(this.id)];
  ao.audio.currentTime = ao.audio.duration * clickPercent(event, ao.timeline, ao.timelineWidth);
}

/* mouseDown */
AudioObject.prototype.mouseDown = function (event) {
  onplayhead = this.id;
  var ao = audioList[getAudioListIndex(this.id)];
  window.addEventListener('mousemove', AudioObject.prototype.moveplayhead, true);
  ao.audio.removeEventListener('timeupdate', AudioObject.prototype.timeUpdate, false);
}

/* mouseUp EventListener
 * getting input from all mouse clicks */
function mouseUp(e) {
  if (onplayhead != null) {
    var ao = audioList[getAudioListIndex(onplayhead)];
    window.removeEventListener('mousemove', AudioObject.prototype.moveplayhead, true);
    // change current time
    ao.audio.currentTime = ao.audio.duration * clickPercent(e, ao.timeline, ao.timelineWidth);
    ao.audio.addEventListener('timeupdate', AudioObject.prototype.timeUpdate, false);
  }
  onplayhead = null;
}

/* mousemove EventListener
 * Moves playhead as user drags */
AudioObject.prototype.moveplayhead = function (e) {
  var ao = audioList[getAudioListIndex(onplayhead)];
  var newMargLeft = e.pageX - ao.timeline.offsetLeft;
  if (newMargLeft >= 0 && newMargLeft <= ao.timelineWidth) {
    document.getElementById(onplayhead).style.marginLeft = newMargLeft + "px";
  }
  if (newMargLeft < 0) {
    playhead.style.marginLeft = "0px";
  }
  if (newMargLeft > ao.timelineWidth) {
    playhead.style.marginLeft = ao.timelineWidth + "px";
  }
}

/* timeUpdate 
 * Synchronizes playhead position with current point in audio 
 * this is the html audio element
 */
AudioObject.prototype.timeUpdate = function () {
  // audio element's AudioObject
  var ao = audioList[getAudioListIndex(this.id)];
  var playPercent = ao.timelineWidth * (ao.audio.currentTime / ao.duration);
  ao.playhead.style.marginLeft = playPercent + "px";
  // If song is over
  if (ao.audio.currentTime == ao.duration) {
    changeClass(ao.playbutton, "playbutton play");
    ao.audio.currentTime = 0;
    ao.audio.pause();
    playingAudio = null;
  }
}

///////////////////////////////////////////////
// Utility Methods
///////////////////////////////////////////////

/* changeClass 
 * overwrites element's class names */
function changeClass(element, newClasses) {
  element.className = newClasses;
}

/* getAudioListIndex
 * Given an element's id, find the index in audioList for the correct AudioObject */
function getAudioListIndex(id) {
  return componentDict[id];
}

/* clickPercent()
 * returns click as decimal (.77) of the total timelineWidth */
function clickPercent(e, timeline, timelineWidth) {
  return (e.pageX - timeline.offsetLeft) / timelineWidth;
}

///////////////////////////////////////////////
// GENERATE HTML FOR AUDIO ELEMENTS AND PLAYERS
///////////////////////////////////////////////

/* createAudioElements
 * create audio elements for each file in files */
function createAudioElements() {
  for (f in files) {
    var audioString = "<audio id=\"audio-" + f + "\" class=\"audio\" preload=\"true\"><source src=\"http://www.alexkatz.me/codepen/music/" + files[f] + "\"></audio>";
    $("#audio-players").append(audioString);
  }
}

/* createAudioPlayers
 * create audio players for each file in files */
function createAudioPlayers() {
  for (f in files) {
    var playerString = "<div id=\"audioplayer-" + f + "\" class=\"audioplayer\"><button id=\"playbutton-" + f + "\" class=\"play playbutton\"></button><div id=\"timeline-" + f + "\" class=\"timeline\"><div id=\"playhead-" + f + "\" class=\"playhead\"></div></div></div>";
    $("#audio-players").append(playerString);
  }
}

/* theDOMHasLoaded()
 * Execute when DOM is loaded */
function theDOMHasLoaded(e) {
  // Generate HTML for audio elements and audio players
  createAudioElements();
  createAudioPlayers();

  // Populate Audio List
  populateAudioList();
  populateComponentDictionary();
}

3 个答案:

答案 0 :(得分:1)

您可以随时使用'gon'宝石。在这里找到:https://github.com/gazay/gon。通过这种方式,您可以将rails变量传递给JS。

<强>的Gemfile

gem 'gon'

<强> application.html.erb

<head>    
  <%= include gon %>
</head>

<强> your_controller.rb

class YourController < ApplicationController
  def index
    # Define your variable and now you can pass it in JS
    @variable = YourModel.all
    gon.new_variable = @variable
  end
end

现在,您的JS文件中提供了“gon.new_variable”。

答案 1 :(得分:0)

有很多方法可以做到这一点:

  • 设置窗口变量
  • 将数据属性传递给对象
  • Gon gem(在另一个答案中提到)
  • 制作JSON端点并从Javascript(基本上是API)调用它。

我在视频中解释了我提到的一些解决方案:

http://railscasts.com/episodes/324-passing-data-to-javascript

观看并选择适合您需求的选项,请记住还有其他方法可以提及我没有提及。

答案 2 :(得分:0)

有很多方法可以做到这一点。通常我们使用:

var variable_a = '<%= my_fav_variable %>'

var variable_b = '<%= raw %>'