对于学习练习,我将sinatra / backbone应用程序转换为Rails环境。我让它在Chrome和Firefox上工作,但它不适用于Safari。事实证明,原始应用http://backbone-hangman.heroku.com也无法在Safari上运行。当你点击"新游戏"它似乎没有发生事件。 Safari控制台没有显示任何错误(虽然我没有使用Safari的开发人员工具,因为我从未使用它们)。
由于此处提供了应用的实时版本http://backbone-hangman.heroku.com我不会发布大量代码,但这是在点击#new_game上设置事件的视图代码,触发startNewGame函数。 Safari中没有任何事情发生。原文的源代码在https://github.com/trivektor/Backbone-Hangman
我搜索了一下,发现一些提到Safari对事件的处理方式有所不同,但无法找到解决方案。可以推荐什么吗?
$(function() {
window.OptionsView = Backbone.View.extend({
el: $("#options"),
initialize: function() {
this.model.bind("gameStartedEvent", this.removeGetAnswerButton, this);
this.model.bind("guessCheckedEvent", this.showGetAnswerButton, this);
},
events: {
'click #new_game': 'startNewGame',
'click #show_answer': 'showAnswer'
},
startNewGame: function() {
this.model.new();
},
removeGetAnswerButton: function() {
$("#show_answer").remove();
},
showGetAnswerButton: function(response) {
console.log("showGetAnswerButton");
console.log(response);
var threshold = this.model.get("threshold");
console.log(threshold);
if (response.incorrect_guesses == this.model.get("threshold")) {
$(this.el).append('<input type="button" id="show_answer" class="action_button" value="Show answer" />');
}
},
showAnswer: function() {
this.model.get_answer();
}
})
})
更新
根据OP下面的评论之一,我发布了更多代码。这是实例化对象的hangman.js
var game = new Game
var options_view = new OptionsView({model: game});
var characters_view = new CharactersView({model: game});
var hint_view = new HintView({model: game});
var word_view = new WordView({model: game});
var hangman_view = new HangmanView({model: game});
var answer_view = new AnswerView({model: game});
var stage_view = new StageView({model: game});
视图和模型像这样附加到窗口
window.AnswerView = Backbone.View.extend({ ...
更新 除了在整个网站上加载的Backbone,jQuery和Underscore之外,还为Rails系统中的这个特定应用程序加载了以下文件。
答案 0 :(得分:2)
This is jQuery + Safari issue (document.ready)
您可以在body标签内移动脚本,并在每个文件中删除$(function(){ /**/ })
包装。
我还添加了requirejs支持并制作了pull request
首先抱歉我的英语:)
我们应该在页面底部嵌入js(以避免Safari错误)
= javascript_include_tag "javascript/require.js", :"data-main" => "javascript/config"
此处javascript/config
是requirejs config的路径。
"deps" : ["hangman"]
这意味着应用程序将以hangman.js
我们不需要$(function() {
包装器,因为从主体和文档初始化的脚本已经“准备好”
define([
'models/game',
'views/answerView',
/* ... */
],
function(Game, OptionsView, /* ... */) {
// ...
}
这里我们加载我们的模块(第一个数组元素将在第一个函数参数中可用,依此类推)
我们只需将$(function() {
替换为define(['backbone'], function(Backbone) {
在第一行我们加载骨干模块。当它被取出时,它将在匿名函数(第一个参数 - Backbone)中可用
接下来我们应该返回视图以避免undefined
模块值(public/javascript/hangman.js
文件应该初始化很多视图。它无法初始化undefined
它应该初始化Backbone.View
那个我们应该回来)
要了解更多信息,请阅读requirejs文档。 我建议你从this article
开始答案 1 :(得分:0)
试试这个。
var OptionsView = Backbone.View.extend({
el: $("#options"),
initialize: function() {
this.model.bind("gameStartedEvent", this.removeGetAnswerButton, this);
this.model.bind("guessCheckedEvent", this.showGetAnswerButton, this);
},
events: {
'click #new_game': 'startNewGame',
'click #show_answer': 'showAnswer'
},
startNewGame: function() {
this.model.new();
},
removeGetAnswerButton: function() {
$("#show_answer").remove();
},
showGetAnswerButton: function(response) {
console.log("showGetAnswerButton");
console.log(response);
var threshold = this.model.get("threshold");
console.log(threshold);
if (response.incorrect_guesses == this.model.get("threshold")) {
$(this.el).append('<input type="button" id="show_answer" class="action_button" value="Show answer" />');
}
},
showAnswer: function() {
this.model.get_answer();
}
});
您的代码不需要准备好文档(它不是直接操作DOM,它只是声明一个对象);
确保game.js在您的所有声明之后完成。
看起来Safari在向全局对象添加变量时遇到了问题。在全局上下文中使用var可确保window.OptionsView存在。您可能希望将来考虑使用require.js来管理所有这些全局对象问题。