Tooltipster 在生成的内容中不起作用
Posted
技术标签:
【中文标题】Tooltipster 在生成的内容中不起作用【英文标题】:Tooltipster does not work in a generated content 【发布时间】:2014-09-26 23:49:27 【问题描述】:我在my website 上安装了 Tooltipster,但它不适用于动态添加的内容。
您可以在“SORT GAMES BY YOUR CHOICE (NEWEST GAMES BY DEFAULT)”框中看到它,当我选择按“最新优先”、“最受欢迎”等排序时...生成内容时,Tooltipster没有看到那个内容。不知何故,我必须告诉 Tooltipster 该内容。
这里是 Tooltipster 代码:
<head></head>
<link rel="stylesheet" type="text/css" href="http://www.heroplaysonline.com/css/tooltipster.css" />
<script type="text/javascript" src="http://www.heroplaysonline.com/js/jquery.tooltipster.min.js"></script>
<script>
$(document).ready(function()
$('.tooltip').tooltipster(
position: 'bottom-left',
contentAshtml: 'true',
animation: 'grow',
theme: '.my-custom-theme'
);
);
</script>
这是生成内容的脚本:
jQuery(document).ready(function($)
$.fn.vAlign = function()
return this.each(function(i)
var ah = $(this).height();
var ph = $(this).parent().height();
var mh = Math.ceil((ph-ah) / 2);
$(this).css('margin-top', mh);
);
;
$('#sortable-game-box-order select').change(function()
var sorturl = $(this).attr("value");
var loaderheight = $('#sortable-game-box-inner-content').height();
$('#sortable-game-box-loader').css('height', loaderheight+13);
$('#sortable-game-box-loader-content').css('height', loaderheight+13);
$('#sortable-game-box-loader-content img').vAlign();
$('#sortable-game-box-list').hide();
$('#sortable-game-box-loader').show();
$('#sortable-game-box-inner').load(sorturl + ' #sortable-game-box-inner-content', function()
$('#sortable-game-box-loader').hide();
$('#sortable-game-box-list').show();
);
);
);
这是 js 的代码,内容是动态生成的,tooltipster 可以工作,但我无法为自己转换。
(function($)'use strict';Date.now=Date.now||function()return+new Date();;$.ias=function(options)
var opts=$.extend(,$.ias.defaults,options);var util=new $.ias.util();var paging=new $.ias.paging(opts.scrollContainer);var hist=(opts.history?new $.ias.history():false);var _self=this;function call_tooltip()
$('.tooltip_cls').tooltipster(animation:'grow',theme:'.my-custom-theme');
function init()
call_tooltip();var pageNum;paging.onChangePage(function(pageNum,scrollOffset,pageUrl)if(hist)hist.setPage(pageNum,pageUrl);
opts.onPageChange.call(this,pageNum,pageUrl,scrollOffset););reset();if(hist&&hist.havePage())stop_scroll();pageNum=hist.getPage();util.forceScrollTop(function()var curTreshold;if(pageNum>1)paginateToPage(pageNum);curTreshold=get_scroll_treshold(true);$('html, body').scrollTop(curTreshold);
elsereset(););
return _self;
init();function reset()
hide_pagination();opts.scrollContainer.scroll(scroll_handler);call_tooltip();
function scroll_handler()
var curScrOffset,scrTreshold;curScrOffset=util.getCurrentScrollOffset(opts.scrollContainer);scrTreshold=get_scroll_treshold();if(curScrOffset>=scrTreshold)if(get_current_page()>=opts.triggerPageTreshold)stop_scroll();show_trigger(function()paginate(curScrOffset););
elsepaginate(curScrOffset);
function stop_scroll()
opts.scrollContainer.unbind('scroll',scroll_handler);
function hide_pagination()
$(opts.pagination).hide();
function get_scroll_treshold(pure)
var el,treshold;el=$(opts.container).find(opts.item).last();if(el.size()===0)return 0;
treshold=el.offset().top+ el.height();if(!pure)treshold+=opts.tresholdMargin;
return treshold;
function paginate(curScrOffset,onCompleteHandler)
var urlNextPage;urlNextPage=$(opts.next).attr('href');if(!urlNextPage)if(opts.noneleft)$(opts.container).find(opts.item).last().after(opts.noneleft);
return stop_scroll();
if(opts.beforePageChange&&$.isFunction(opts.beforePageChange))if(opts.beforePageChange(curScrOffset,urlNextPage)===false)return;
paging.pushPages(curScrOffset,urlNextPage);stop_scroll();show_loader();loadItems(urlNextPage,function(data,items)var result=opts.onLoadItems.call(this,items),curLastItem;if(result!==false)$(items).hide();curLastItem=$(opts.container).find(opts.item).last();curLastItem.after(items);$(items).fadeIn();
urlNextPage=$(opts.next,data).attr('href');$(opts.pagination).replaceWith($(opts.pagination,data));remove_loader();hide_pagination();if(urlNextPage)reset();
elsestop_scroll();
opts.onRenderComplete.call(this,items);if(onCompleteHandler)onCompleteHandler.call(this););
function loadItems(url,onCompleteHandler,delay)
var items=[],container,startTime=Date.now(),diffTime,self;delay=delay||opts.loaderDelay;$.get(url,null,function(data)container=$(opts.container,data).eq(0);if(0===container.length)container=$(data).filter(opts.container).eq(0);
if(container)container.find(opts.item).each(function()items.push(this););
if(onCompleteHandler)self=this;diffTime=Date.now()- startTime;if(diffTime<delay)setTimeout(function()onCompleteHandler.call(self,data,items);,delay- diffTime);elseonCompleteHandler.call(self,data,items);,'html');
function paginateToPage(pageNum)
var curTreshold=get_scroll_treshold(true);if(curTreshold>0)paginate(curTreshold,function()stop_scroll();if((paging.getCurPageNum(curTreshold)+ 1)<pageNum)paginateToPage(pageNum);$('html,body').animate('scrollTop':curTreshold,400,'swing');
else$('html,body').animate('scrollTop':curTreshold,1000,'swing');reset(););
function get_current_page()
var curScrOffset=util.getCurrentScrollOffset(opts.scrollContainer);return paging.getCurPageNum(curScrOffset);
function get_loader()
var loader=$('.ias_loader');if(loader.size()===0)loader=$('<div class="ias_loader">'+ opts.loader+'</div>');loader.hide();
return loader;
function show_loader()
var loader=get_loader(),el;if(opts.customLoaderProc!==false)opts.customLoaderProc(loader);elseel=$(opts.container).find(opts.item).last();el.after(loader);loader.fadeIn();
function remove_loader()
var loader=get_loader();loader.remove();
function get_trigger(callback)
var trigger=$('.ias_trigger');if(trigger.size()===0)trigger=$('<div class="ias_trigger"><a href="all.html">'+ opts.trigger+'</a></div>');trigger.hide();
return trigger;
function show_trigger(callback)
var trigger=get_trigger(callback),el;el=$(opts.container).find(opts.item).last();el.after(trigger);trigger.fadeIn();
function remove_trigger()
var trigger=get_trigger();trigger.remove();;$.ias.defaults=container:'#container',scrollContainer:$(window),item:'.item',pagination:'#pagination',next:'.next',noneleft:false,loader:'<img src="images/loader.gif"/>',loaderDelay:600,triggerPageTreshold:4,trigger:'Load more items',tresholdMargin:0,history:true,onPageChange:function(),beforePageChange:function(),onLoadItems:function(),onRenderComplete:function(),customLoaderProc:false;$.ias.util=function()
var wndIsLoaded=false;var forceScrollTopIsCompleted=false;var self=this;function init()
$(window).load(function()wndIsLoaded=true;);
init();this.forceScrollTop=function(onCompleteHandler)
$('html,body').scrollTop(0);if(!forceScrollTopIsCompleted)if(!wndIsLoaded)setTimeout(function()self.forceScrollTop(onCompleteHandler);,1);elseonCompleteHandler.call();forceScrollTopIsCompleted=true;;this.getCurrentScrollOffset=function(container)
var scrTop,wndHeight;if(container.get(0)===window)scrTop=container.scrollTop();elsescrTop=container.offset().top;
wndHeight=container.height();return scrTop+ wndHeight;;;$.ias.paging=function()
var pagebreaks=[[0,document.location.toString()]];var changePageHandler=function();var lastPageNum=1;var util=new $.ias.util();function init()
$(window).scroll(scroll_handler);
init();function scroll_handler()
var curScrOffset,curPageNum,curPagebreak,scrOffset,urlPage;curScrOffset=util.getCurrentScrollOffset($(window));curPageNum=getCurPageNum(curScrOffset);curPagebreak=getCurPagebreak(curScrOffset);if(lastPageNum!==curPageNum)scrOffset=curPagebreak[0];urlPage=curPagebreak[1];changePageHandler.call(,curPageNum,scrOffset,urlPage);
lastPageNum=curPageNum;
function getCurPageNum(scrollOffset)
for(var i=(pagebreaks.length- 1);i>0;i--)if(scrollOffset>pagebreaks[i][0])return i+ 1;
return 1;
this.getCurPageNum=function(scrollOffset)
scrollOffset=scrollOffset||util.getCurrentScrollOffset($(window));return getCurPageNum(scrollOffset);;function getCurPagebreak(scrollOffset)
for(var i=(pagebreaks.length- 1);i>=0;i--)if(scrollOffset>pagebreaks[i][0])return pagebreaks[i];
return null;
this.onChangePage=function(fn)
changePageHandler=fn;;this.pushPages=function(scrollOffset,urlNextPage)
pagebreaks.push([scrollOffset,urlNextPage]);;;$.ias.history=function()
var isPushed=false;var isHtml5=false;function init()
isHtml5=!!(window.history&&history.pushState&&history.replaceState);isHtml5=false;
init();this.setPage=function(pageNum,pageUrl)
this.updateState(page:pageNum,'',pageUrl);;this.havePage=function()
return(this.getState()!==false);;this.getPage=function()
var stateObj;if(this.havePage())stateObj=this.getState();return stateObj.page;
return 1;;this.getState=function()
var haveState,stateObj,pageNum;if(isHtml5)stateObj=history.state;if(stateObj&&stateObj.ias)return stateObj.ias;
else
return false;;this.updateState=function(stateObj,title,url)
if(isPushed)this.replaceState(stateObj,title,url);
elsethis.pushState(stateObj,title,url);;this.pushState=function(stateObj,title,url)
var hash;if(isHtml5)history.pushState(ias:stateObj,title,url);
else
isPushed=true;;this.replaceState=function(stateObj,title,url)
if(isHtml5)history.replaceState(ias:stateObj,title,url);
elsethis.pushState(stateObj,title,url);;;)(jQuery);
我已经为此工作了两天,但无法修复它,因为我对编码一无所知。我只能进行实验,删除一些代码等,但我认为解决方案不止于此。
任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:danemacmillan,你是对的。 我添加了以下代码,现在 tooltipster 也适用于动态生成的内容。
<script type="text/javascript">
$('body').on('mouseover mouseenter', '.tooltip', function()
$(this).tooltipster(
contentAsHTML: 'true',
animation: 'grow',
theme: '.my-custom-theme',
position: 'top-left'
);
$(this).tooltipster('show');
);
</script>
我仍然不相信它,但它确实有效! :D
【讨论】:
【参考方案2】:您遇到的问题至少可以通过多种方式解决。最好的解决方案是减少编写所需的代码量,甚至可以提高应用程序的性能和可维护性。
这是一个会咬你一次的问题,但很少会再次出现。这对于 JavaScript 新手来说很常见,所以请记住这一点。
当文档“准备好”时触发 Tooltipster。当文档完全构建并准备好使其节点成为目标时,它就已准备就绪 [1]。问问自己,“文件多久准备一次?”答案当然是每次页面刷新一次。如果文档在每次页面刷新时只能就绪一次,这意味着附加到事件的匿名函数(作为页面重新刷新,或“就绪”)只会被触发一次。 匿名工具提示器功能只会被触发一次,所有已知和当前可用的匹配节点。工具提示器不知道在文档准备好后添加到文档中的节点。
知道了这一点,至少可以从几个角度来解决这个问题:
每次更改文档时都会触发匿名工具提示器功能。文档部分中附加了 tooltipster 功能的所有节点很可能已经被删除,因为重新排列文档中的节点往往是破坏性的,除非小心。这种方法还可以,但远非理想,而且肯定不是高性能或最可维护的。
让父节点将事件触发委托给其子节点。 这是应该做的。这意味着父级将侦听以前每个单独的子级会执行的事件。父母可能永远不会改变或被操纵,但它的内容(孩子)会。附加到父节点是一种更健壮和可维护的方法;此外,它在浏览器中的执行速度要快得多,这意味着最终用户会喜欢更快的实现。附加到父节点的单个事件可以处理发生在子节点上的所有事情。
jQuery 使事件委托变得非常简单。再说一次,普通的旧 JavaScript 也是如此。不过,您使用的是前者。 Read about event delegation on jQuery。在您阅读之前不要替换您网站上的代码。这大概就是需要写的内容了;它尚未经过测试,因此可能需要进行调整:
$(document).ready(function()
$('#sortable-game-box-list').on('mouseover mouseout', '.tooltip', function(e)
$(e.target).tooltipster(
position: 'bottom-left',
contentAsHTML: 'true',
animation: 'grow',
theme: '.my-custom-theme'
);
);
);
如前所述,请记住这一点。这将是 JavaScript 开发中经常遇到的问题,至少在经验占主导地位之前是这样。
[1] 顺便说一句,这与加载文档时不同,这意味着除了所有节点都处于活动状态之外,还加载了文档拉入的所有资产;资产是外部脚本、图像以及同步拉入的任何其他内容。
【讨论】:
感谢您的回复。我很担心,因为尽管你给了我这么详细的答案,但仍然无法解决问题。我尝试使用你在 head/head 脚本和脚本中给我的代码,这会生成没有运气的内容。我喜欢第二种方法,但认为,在生成内容后,工具提示器不会听任何东西,所以第一种选择对我来说似乎更真实。我不明白如何通过那个生成内容的脚本来触发匿名工具提示器功能,你能告诉我吗? 在每个鼠标事件上重新初始化元素上的工具提示器?!这听起来不是特别有效。【参考方案3】:为我工作。对我来说,我不需要在 mouseover、mouseleave 上创建事件...
<script type="text/javascript">
$('.tooltip1')
.tooltipster(
....some options
)
.tooltipster('content', 'some result from api');
</script>
【讨论】:
以上是关于Tooltipster 在生成的内容中不起作用的主要内容,如果未能解决你的问题,请参考以下文章