我的应用程序是一个使用骨干的rails 3应用程序.js和jw播放器,用于播放视频播放列表。视频index_view将所有视频加载到 jw 播放器的播放列表中。当我离开索引页面时,我的问题就来了,比如说单个视频的show_view。当我单击浏览器的后退按钮时,当 jw 播放器尝试再次加载时出现错误。
Uncaught TypeError: Object #<Object> has no method 'setup'
我相信问题是模板没有加载播放器用来实例化的 html 元素。这是我目前的理论。如果你看index_view.js.coffee
你会发现在render
方法中,我使用 JQuery $(document).read ->
方法来加载播放器。如果我删除它,播放器不会加载,我看到同样的错误。
Uncaught TypeError: Object #<Object> has no method 'setup'
只需在不存在的 CSS ID 上调用 jwplayer 即可重现此错误,即jwplayer('non-existant-id').setup(...)
会产生相同的错误。我对主干网很陌生,但我假设 JQuery document.ready 方法在初始加载索引页后不起作用。一旦我使用#
路由,DOM 永远不会重新加载,因此当我导航回索引页面时,ID "my-video"尚不存在,因此调用jwplayer('my-video')
会产生错误。有没有Backbone.ready
的方法? :)
所以这里有一些代码,如果你需要其他东西,我知道:
index.html.erb
视频的边栏视图
<div id="videos"></div>
<script type="text/javascript">
$(function() {
// Blog is the app name
window.router = new SeehearmeWebapp.Routers.VideosRouter({videos: <%= @videos.to_json.html_safe -%>, users: <%= @users.to_json.html_safe -%>, questions: <%= @questions.to_json.html_safe -%>});
Backbone.history.start();
});
</script>
videos_router.js.coffee
class SeehearmeWebapp.Routers.VideosRouter extends Backbone.Router
initialize: (options) ->
@videos = new SeehearmeWebapp.Collections.VideosCollection()
@videos.reset options.videos
@users = new SeehearmeWebapp.Collections.UsersCollection()
@users.reset options.users
@playlist = []
@questions = options.questions
for i in [0..@videos.length-1]
video = @videos.models[i]
versions = video.attributes.versions[6]
images = video.attributes.thumbnails[0]
question = @questions[parseInt(video.attributes.question_id)-1]
if !(question == undefined)
title = question.text
else
title = ""
if !(versions == undefined)
creator_id = video.attributes.creator_id.toString()
@playlist.push {file: versions.url, creator_id: creator_id, gender: @users.get(creator_id).attributes.gender, question: title , image: images.url}
routes:
"new" : "newVideo"
"index" : "index"
":id/edit" : "edit"
":id" : "show"
".*" : "index"
newVideo: ->
@view = new SeehearmeWebapp.Views.Videos.NewView(collection: @videos)
$("#videos").html(@view.render().el)
index: ->
@view = new SeehearmeWebapp.Views.Videos.IndexView(videos: @videos, users: @users, playlist: @playlist)
$("#videos").html(@view.render().el)
show: (id) ->
video = @videos.get(id)
@view = new SeehearmeWebapp.Views.Videos.ShowView(model: video)
$("#videos").html(@view.render().el)
edit: (id) ->
video = @videos.get(id)
@view = new SeehearmeWebapp.Views.Videos.EditView(model: video)
$("#videos").html(@view.render().el)
index_view.js.coffee
SeehearmeWebapp.Views.Videos ||= {}
class SeehearmeWebapp.Views.Videos.IndexView extends Backbone.View
template: JST["backbone/templates/videos/index"]
playerHeight = '360'
playerWidth = '640'
defaultVersion = 0
playlist = []
initialize: () ->
@options.videos.bind('reset', @addAll)
playlist = @options.playlist
addAll: () =>
@options.videos.each(@addOne)
addOne: (video) =>
view = new SeehearmeWebapp.Views.Videos.VideoView({model : video})
@$("tbody").append(view.render().el)
render: =>
$(@el).html(@template(videos: @options.videos.toJSON() ))
@addAll()
$(document).ready ->
player = jwplayer('my-video')
player.setup({playlist: playlist, width: playerWidth, height: playerHeight, skin: "/jwplayer/skins/six/six.xml"})
return this
index.jst.ejs
<div class="video-container">
<div class="row gender-toggle-row">
<div class="gender-toggle-label span1">Show Me: </div>
<div class="btn-group gender-dropdown-group">
<button class="btn btn-extra-large gender-dropdown gender-dropdown-display">Women and Men</button>
<button class="btn btn-extra-large dropdown-toggle gender-dropdown" data-toggle="dropdown">
<img src="assets/down-arrow.png" />
</button>
<ul class="dropdown-menu gender-dropdown-menu">
<li><a class="gender-toggle-element" href="#">Women</a></li>
<li><a class="gender-toggle-element" href="#">Men</a></li>
<li><a class="gender-toggle-element" href="#">Women and Men</a></li>
</ul>
</div>
</div>
<div class="cinema-ribbon-sides"></div>
<div class="cinema-ribbon"><h2 id="question-text" class="white centered-text">seehear.me</h2></div>
<div id='my-video'></div>
<div class="cinema-shadow"></div>
<div class="cinema-controls">
<a id="prev-video" class="cinema-prev"></a>
<a href="#/71" role="button" class="meet"><div class="meet-btn-text">meet her</div></a>
<a id="next-video" class="cinema-next"></a>
</div>
</div>
<br />
show_view.js.coffee
SeehearmeWebapp.Views.Videos ||= {}
class SeehearmeWebapp.Views.Videos.ShowView extends Backbone.View
template: JST["backbone/templates/videos/show"]
render: ->
$(@el).html(@template(@model.toJSON() ))
return this
show_view.js.coffee
<h1>THIS IS A VIDEO</h1>
<a href="#/">Back</a>
谢谢!
当您呈现主干视图并以这种方式将其添加到页面时:
$("#videos").html(@view.render().el)
您正在呈现到尚未添加到页面的 DOM 元素。 由于您尝试在 render()
中设置 jwplayer,jwplayer 可能找不到该元素。
如果先将视图添加到页面,然后呈现,则它可能会起作用。
$("#videos").html(@view.el)
@view.render()
现在,当您渲染模板时,它实际上在jwplayer尝试查找该元素之前就在页面上。