简体   繁体   English

如何在JavaScript中访问Rails视图变量?

[英]How can I access a rails view variable in javascript?

I am a rails newbie and I just want to extract a rails object and attribute (@tracks.audio) using javascript. 我是Rails新手,我只想使用JavaScript提取Rails对象和属性(@ tracks.audio)。 I want to apply audio files dynamically from the db instead of using the hard coded version seen on commented lines 1,2,3 我想从数据库动态应用音频文件,而不是使用在注释行1,2,3上看到的硬编码版本

Here is the tracks.js.erb 这是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();
}

You can always use the 'gon' gem. 您可以随时使用“ gon”宝石。 Found here: https://github.com/gazay/gon . 在这里找到: https : //github.com/gazay/gon With this you are able to pass your rails variables to your JS. 这样,您就可以将rails变量传递给JS。

Gemfile 宝石文件

gem 'gon'

application.html.erb application.html.erb

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

your_controller.rb 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

Now 'gon.new_variable' is available in your JS file. 现在,“ gon.new_variable”在您的JS文件中可用。

There are many ways to do this: 有很多方法可以做到这一点:

  • Setting window variables 设置窗口变量
  • Passing data attributes to an object 将数据属性传递给对象
  • The Gon gem (mentioned in another answer) Gon宝石(在另一个答案中提到)
  • Making a JSON endpoint and calling it from Javascript (basically an API). 创建一个JSON端点并从Javascript(基本上是API)调用它。

Some of the solutions I mentioned are explained in this video: 我在视频中介绍了我提到的一些解决方案:

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

Watch it and choose the option that suits your needs, keep in mind there are also other ways to do this that I didn't mention. 注意并选择适合您需求的选项,请记住,还有其他我没有提到的方法。

There are many ways to do this. 有很多方法可以做到这一点。 Usually we use: 通常我们使用:

var variable_a = '<%= my_fav_variable %>'

or 要么

var variable_b = '<%= raw %>'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM