为什么这个JS会在一页上部分呈现而不是另一页?
我有一个posts.js
文件,如下所示:
var ready; ready = function() { var toggleSidebar = $(".togglesidebar"); var primary = $("#primary"); var secondary = $("#secondary"); toggleSidebar.on("click", function(){ if(primary.hasClass("col-sm-9")){ primary.removeClass("col-sm-9"); primary.addClass("col-sm-12"); secondary.css('display', 'none'); } else { primary.removeClass("col-sm-12"); primary.addClass("col-sm-9"); secondary.css('display', 'inline-block'); } }); }; var counter = function(event) { var fieldValue = $(this).val(); var wc = fieldValue.trim().replace(regex, ' ').split(' ').length; var regex = /\s+/gi; var $wcField; var maxWc; if ($(this)[0] === $('#post_title')[0]) { $wcField = $('#wordCountTitle'); maxWc = 7; } else { $wcField = $('#wordCountBody'); maxWc = 150; } $wcField.html(wc); $wcField.toggleClass('over-limit', wc > maxWc); }; $(document).ready(ready); $(document).on('ready page:load', function () { $('#post_title, #body-field').on('change keyup paste', counter); });
在我的application.html.erb
页面中,我有这个:
当我切换这个div,并显示_form
partial时,JS在这些字段中工作正常。
但是如果我去posts/new
或/posts/:id/edit
,它就不会。
即使我检查该页面的来源,我也看到包含在那里的post.js
可能是什么导致了这个?
编辑1
如果重要的话,我正在使用Turbolinks。
编辑2
我根据答案中的建议尝试了这个:
var ready; ready = function() { // This is the Sidebar toggle functionality var toggleSidebar = $(".togglesidebar"); var primary = $("#primary"); var secondary = $("#secondary"); $(document).on("click", ".togglesidebar", function(){ if(primary.hasClass("col-sm-9")){ primary.removeClass("col-sm-9"); primary.addClass("col-sm-12"); secondary.css('display', 'none'); } else { primary.removeClass("col-sm-12"); primary.addClass("col-sm-9"); secondary.css('display', 'inline-block'); } }); };
但这没效果。
我遇到问题的关键问题是“计数器”,即#wordCountTitle
和#wordCountBody
在my /posts/new
不起作用,即使它们在激活.toggleSidebar
时.toggleSidebar
posts/index
。
而不是直接绑定到需要仔细处理Turbolinks事件的元素的onclick,您可以在文档上使用事件处理程序,尝试更改直接事件
toggleSidebar.on("click", function(){
委派活动
$(document).on("click", ".togglesidebar", function(){
当您动态修改DOM时(如Turbolinks替换它),如果您使用直接事件,则需要重新分配它。
有关详细说明,请参阅http://api.jquery.com/on/#direct-and-delegated-events
与第一个函数相同的代表第二个函数。 此外,通过委派事件,“就绪”检查变得不必要。 考虑到这一点,您的代码将变为:
$(document).on("click", ".togglesidebar", function(){ var primary = $("#primary"); var secondary = $("#secondary"); if(primary.hasClass("col-sm-9")){ primary.removeClass("col-sm-9"); primary.addClass("col-sm-12"); secondary.css('display', 'none'); } else { primary.removeClass("col-sm-12"); primary.addClass("col-sm-9"); secondary.css('display', 'inline-block'); } }); $(document).on('change keyup paste', '#post_title, #body-field', function () { var fieldValue = $(this).val(); var wc = fieldValue.trim().replace(regex, ' ').split(' ').length; var regex = /\s+/gi; var $wcField; var maxWc; if ($(this)[0] === $('#post_title')[0]) { $wcField = $('#wordCountTitle'); maxWc = 7; } else { $wcField = $('#wordCountBody'); maxWc = 150; } $wcField.html(wc); $wcField.toggleClass('over-limit', wc > maxWc); });
我在我的一个项目上使用这样的东西,有同样的问题希望它有所帮助:
window.onLoad = function(callback) { $(document).ready(callback); $(document).on('page:load', callback); };
然后用onLoad包装我的函数,比如
onLoad(function() { counter() });
onLoad函数绑定ready事件和turbolink页面:load event
当你这样做
$("selector").on("click", function(){});
您实际上将选择器绑定到click事件。
如果你使用白色
$(document).on("click", "selector", function(){});
将click事件绑定到文档,在单击检查后单击的元素是否是您使用的选择器。 如果是,它执行该function。 因此,只要在动态元素上绑定事件,就应该使用第二种方法。
我希望能回答“为什么”的问题
很长一段时间我不使用jQuery,但是因为我到了这里:如果你有多个带选择器“.sidebar”的元素,我相信你需要使用“.each”将函数绑定到所有元素与dom上的选择器匹配。
有关参考,请访问http://api.jquery.com/each/
希望这有帮助,祝你好运。
我看了一下Turbolinks,它完成了我的想法:它在主页面上的容器内加载链接的HTML内容。 问题是,它加载的任何内容都与您在加载主页面时声明的任何事件和函数无关,因此实际上,在第一次单击之后,它刚加载的HTML上的选择器将不会将click事件归因于它(当你进行绑定时,它不在DOM上)。
可能的解决方案:我对.live()方法进行了一些研究,但是已被弃用,所以我建议这样做:
$(’body’)。on(’click’,’a.saveButton’,saveHandler)
看起来,更接近你需要的元素的绑定将确保无论Turbolinks在体内加载什么都将获得你声明的绑定。
这里有一个更详细的答案: Javascript事件绑定持久性
.live钩子的文档在这里: http : //api.jquery.com/live/#typefn
我过去常常在我的网页上使用相同的架构,我确实遇到了类似于你的问题。
希望能帮助到你。
它应该工作..确保:
- 什么都没有冲突。
- 你的HTML结构,也许你忘了把价值放在你的post中。
- 也许是错误的路径posts.js,用CTRL + U打开然后点击post.js什么显示你的代码,如果有的话就可以了。
我试着这样,没关系(虚拟):
$(document).on("click", ".togglesidebar", function(){ var primary = $("#primary"); var secondary = $("#secondary"); if(primary.hasClass("col-sm-9")){ primary.removeClass("col-sm-9"); primary.addClass("col-sm-12"); secondary.css('display', 'none'); } else { primary.removeClass("col-sm-12"); primary.addClass("col-sm-9"); secondary.css('display', 'inline-block'); } }); $(document).on('change keyup paste', '#post_title, #body-field', function () { var fieldValue = $(this).val(); var wc = fieldValue.trim().replace(regex, ' ').split(' ').length; console.log(wc); var regex = /\s+/gi; var $wcField; var maxWc; if ($(this)[0] === $('#post_title')[0]) { $wcField = $('#wordCountTitle'); maxWc = 7; } else { $wcField = $('#wordCountBody'); maxWc = 150; } $wcField.html(wc); $wcField.toggleClass('over-limit', wc > maxWc); });
老实说,涉及Turbolinks的Js问题,让它高效工作的最好方法是安装jquery rails gem,添加// require jquery-Turbolinks然后删除//需要在你的Js文件中使用turbolinks
确保您在jQuery选择器上传递的ID是唯一的。 如果在没有回发的情况下加载该页面/部分,则应该使用
//document or selector that does not get removed var primary = $(document).find('#primary'); var secondary = $(document).find('#secondary');
这个,有
$(document).click('eventName', 'contextSelector', function)
应该有助于解决问题。
如果动态创建#post_title
和#body-field
则需要更改:
$('#post_title, #body-field').on('change keyup paste', counter);
对此:
$(document).on('change keyup paste', '#post_title, #body-field', counter);
在定位加载页面时不存在的元素(可能是#post_title
和#body-field
)时,您需要将事件委托给页面加载时存在的元素(在本例中为document
本身)。
关于/posts/new
上的$('#wordCountTitle')
和$('#wordCountBody')
,您是否尝试在控制台中输入其中任何一个? /posts/new
的视图可能与您的索引不同,并且缺少这些ID(或者您使它们成为类或其他一些转置发生)。
我遇到了Turbolinks和jquery的各种问题,所以关于如何解决问题的一些建议:
-
使用
gem 'turbolinks'
来包含它。 按照说明操作,使用Ruby(gems)方式而不是PHP方式。 -
使用Turbolinks意味着
$(document).ready
在加载新的“页面”时不会触发。 解决方案是使用:$(document).on('page:load', ready)
以及$(document).ready(ready)
。page:load
事件是ready
事件的Turbolinks版本。 -
其他人已经建议但我在rails应用程序中发现它非常有价值:而不是直接将事件绑定到选择器
$("a").click(/* function */)
,绑定到文档意味着当Turbolinks加载时新页面,文件绑定在页面加载中幸存:$(document).on('click', 'a.particularAnchor', particularAnchorClicked)
考虑到您的特定代码,我会改变这个:
$('#post_title, #body-field').on('change keyup paste', counter);
至
$(document).on('change keyup paste', '#post_title, #body-field', counter);
在我看来,在你的counter
function中你已经混合了以下两行( regex
需要先定义)
var wc = fieldValue.trim().replace(regex, ' ').split(' ').length; var regex = /\s+/gi;