简体   繁体   English

工具提示:[data-tooltip-content] 作为指向动态 HTML 的指针

[英]Tooltipster: [data-tooltip-content] as pointer to dynamic HTML

THE ISSUE : Using Tooltipster.JS with FullCalendar and / or dynamically rendered content问题:将Tooltipster.JSFullCalendar和/或动态呈现的内容一起使用

I've been scratching my head and chewing over this for quite a while now and I'm no close to where I was when I started.我一直在挠头和咀嚼这个很长一段时间,而且我离我开始时的状态还差得很远。 I've read and re-read the Tooltipster docs but I simply can't seem to use 'data-tooltip-content' as a pointer to the #idTooltipsterElement .我已经阅读并重新阅读了 Tooltipster 文档,但我似乎无法使用'data-tooltip-content'作为指向#idTooltipsterElement的指针。 It simply displays the value of 'data-tooltip-content' even though the docs clearly state:即使文档明确说明,它也只是显示“data-tooltip-content”的

Tooltipster Documentation states: Tooltipster 文档说明:

5. Use HTML inside your tooltips 5. 在工具提示中使用 HTML

Tooltipster allows you to use any HTML markup inside your tooltips. Tooltipster 允许您在工具提示中使用任何 HTML 标记。 It means that you can insert things like images and text formatting tags.这意味着您可以插入图像和文本格式标签之类的内容。

Instead of a title attribute, use a data-tooltip-content attribute to provide a selector that corresponds to the HTML element of your page that should be used as content.使用 data-tooltip-content 属性代替标题属性来提供与应用作内容的页面 HTML 元素相对应的选择器。 This is your HTML:这是你的 HTML:

 <span class="tooltip" data-tooltip-content="#tooltip_content">This span has a tooltip with HTML when you hover over it!</span> <div class="tooltip_templates"> <span id="tooltip_content"> <img src="myimage.png" /> <strong>This is the content of my tooltip!</strong> </span> </div>

In your CSS file, add .tooltip_templates { display: none; }在您的 CSS 文件中,添加.tooltip_templates { display: none; } .tooltip_templates { display: none; } so that the content does not get displayed outside of the tooltip. .tooltip_templates { display: none; }使得内容不会被显示的提示之外。

When we moved from Tippy.js to Tooltipster.js I was having other issues which thankfully are not present in Tootipster, but I found the former was far easier to set up even though it has nowhere near the amount of functionality nor documentation as the later.当我们从Tippy.js 迁移Tooltipster.js 时,我遇到了其他问题,幸好 Tootipster 不存在这些问题,但我发现前者更容易设置,即使它的功能和文档数量远不及后者.

However: I previously just used 'data-tooltip-content' to put my entire HTML elements inside it and oddly enough I noticed that this also works with Tooltipster as well even though their documentations seems to prefer the above approach.但是:我以前只是使用'data-tooltip-content'将我的整个 HTML 元素放入其中,奇怪的是我注意到这也适用于 Tooltipster ,即使他们的文档似乎更喜欢上述方法。 Now normally I would simply keep the old approach which I'm already familiar with, but unfortunately this bring with it a whole host of potential challenges relating to post event render changes (we are likely to implement) in FullCalendar which we use extensively on our pages, as well as formatting / styling difficulties which I've experienced already.现在通常我会简单地保留我已经熟悉的旧方法,但不幸的是,这带来了一系列与 FullCalendar 中的事件后渲染更改(我们可能会实施)相关的潜在挑战,我们在我们的页面,以及我已经经历过的格式/样式困难

I am reasonably certain the preferred solution described on the Tooltipster documented would be ideal for our implementation, but I simply can't work out how to get it to work in our fullCalendar environment which is broken down in the following program flow:我有理由确定 Tooltipster 文档中描述的首选解决方案将是我们实现的理想选择,但我根本无法弄清楚如何让它在我们的fullCalendar环境中工作,环境在以下程序流中分解:

  1. eventRender : pull events from your event source and render each entry for the chosen month / period. eventRender :从事件源中提取事件并呈现所选月份/期间的每个条目。 This is where the initial Toolstipster gets created and assigned a unique id这是创建初始 Toolstipster 并为其分配唯一 ID 的地方

  2. eventAfterAllRender : this basically runs after the eventRender and this is where we do our post render tidy up eg check for invalid image links etc and replace remove any image icons/references as well as change or disable/remove the tooltip if no longer necessary. eventAfterAllRender :这基本上在 eventRender 之后运行,这是我们整理后期渲染的地方,例如检查无效的图像链接等并替换删除任何图像图标/引用以及更改或禁用/删除工具提示(如果不再需要)。 If required we replace the tooltip content here otherwise we set the Tooltipster content to whatever data was passed along form the eventRender process.如果需要,我们在此处替换工具提示内容,否则我们将 Tooltipster 内容设置为从 eventRender 进程传递的任何数据。

  3. eventMouseover : this section holds the event hover method which is responsible for displaying the Tooltipster tooltip. eventMouseover :此部分包含负责显示 Tooltipster 工具提示的事件悬停方法。

I created a sample fiddle using a striped down version of our code and a couple of test events instead of using an external data source, but the result is the same when I use this code in our own environment.我使用我们代码的精简版本和几个测试事件而不是使用外部数据源创建了一个示例小提琴,但是当我在我们自己的环境中使用此代码时,结果是一样的。 I've included the following to reflect our environment: Bootstrap 4.4.0 - FullCalendar 3.10.1 - Tooltipster 4.2.7我已经包含以下内容来反映我们的环境: Bootstrap 4.4.0 - FullCalendar 3.10.1 - Tooltipster 4.2.7

If you hover over one of the events the tooltip just displays the value of the section pointer eg #tt_event1 (the id of the element it points to) instead of what is set in the content section如果您将鼠标悬停在其中一个事件上,工具提示只会显示部分指针的值,例如#tt_event1 (它指向的元素的 id)而不是内容部分中设置的值

eg <div class="tooltip_templates"><span id="tt_event1" class="tooltip_content"><img src="https://hackernoon.com/hn-images/1*cmqZiJz1TuUedRoeI3g_Iw.jpeg" width="450" height="auto"><p style="text-align:left;"><span class="flag-icon flag-icon-uk"></span><strong class="title">Tips for Writing Cleaner Code</strong><br>optional desctiptive text can go here</p></span></div>例如<div class="tooltip_templates"><span id="tt_event1" class="tooltip_content"><img src="https://hackernoon.com/hn-images/1*cmqZiJz1TuUedRoeI3g_Iw.jpeg" width="450" height="auto"><p style="text-align:left;"><span class="flag-icon flag-icon-uk"></span><strong class="title">Tips for Writing Cleaner Code</strong><br>optional desctiptive text can go here</p></span></div>

 $(document).ready(function() { $('#calendar').fullCalendar({ defaultView: 'month', header: '', defaultDate: '2020-03-01', events: [{ id: 'event1', className: 'UK', title: 'Tips for Writing Cleaner Code', description: 'I decided to write an article that will be useful for beginners to understand their mistakes and to put together some practices. /n source: hackernoon.com/tips-for-writing-cleaner-better-code-e36ffeb55526', start: '2020-03-02', end: '2020-03-02' }, { id: 'event2', className: 'NL', title: 'Modern Style of Javascript with Arrow Functions', description: 'The complete explanation of Arrow functions in Javascript, and how it helps developers to write flexible and consistent code. /n source: hackernoon.com/modern-style-of-javascript-with-arrow-functions-lg1x3474', start: '2020-03-04', end: '2020-03-11' } ], eventRender: function(event, element, view) { window.dataE = window.dataE || []; element.attr( 'id', event.id ); var /* Vars */ desc = (event.description), url='', urlEvent1 = "https://hackernoon.com/hn-images/1*cmqZiJz1TuUedRoeI3g_Iw.jpeg", urlEvent2 = "https://images.unsplash.com/photo-1527427337751-fdca2f128ce5?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjEwMDk2Mn0", tipRef="tip_content_"+event.id, idTip="#"+tipRef /* End Vars */; // passing 2 extra image params manually - usually from seperate data routine if (event.title == 'Tips for Writing Cleaner Code') { url = urlEvent1; } else { url = urlEvent2; } var tt_ref = '#tt_'+event.id; var className = ''+event.className; var cc = className.toLowerCase(); var tt = '<div class="tooltip_templates"><span id="tt_' + event.id + '" class="tooltip_content"><img src="' + url + '" width="450" height="auto"><p style="text-align:left;"><span class="flag-icon flag-icon-' + cc + '"></span><strong class="title">' + event.title + '</strong><br>optional desctiptive text can go here</p></span></div>'; element.attr( 'data-tooltip-content', tt_ref ); // the tooltip pointer element.attr( 'data-tt-tooltipser' ); element.attr( 'data-tt-tooltipser', tt ); element.attr( 'tt_title' ); element.attr( 'tt_title', event.title ); element.addClass('tt_tooltip tt_group'); var eID = '#'+event.id; // Tooltipster if (!element.hasClass('tt_added')) { $(eID).tooltipster(); $(eID).tooltipster({ //content: tipContent, //contentCloning: true, trigger: 'hover', //multiple: true, animation: 'fade', arrow: true, delay: 300, maxWidth: 600, contentAsHTML: true, debug: true }); element.addClass('tt_added'); } // create array of event.IDs for use in [eventAfterAllRender] if (Array.isArray(dataE)){ var json = JSON.stringify(event.id), item = dataE.find(el => JSON.stringify(el) === json); if (typeof item !== 'undefined'){ return false; } else { dataE.push(event.id); } } }, eventAfterAllRender: function(event, element){ // get events from dataE array created during [eventRender] var count = 0; for (var i=0; i<dataE.length; i++) { var id = dataE[i], eID = '#'+id ; // now obtain the tooltip & tooltipster variables for each event var tipTooltipRef = $(eID).attr('data-tooltip-content'); var tipTooltipsterContent = $(eID).attr('data-tt-tooltipser'); console.log("tipTooltipRef:", tipTooltipRef); console.log("tipTooltipsterContent:", tipTooltipsterContent); console.log("$(eID)", $(eID)); // append the tooltipster content aquired via tooltipster var $(eID).append(tipTooltipsterContent); $(eID).tooltipster(); // set the content pointer $(eID).tooltipster('content', tipTooltipRef ); //TOOLTIPSTER: update any necessary Tooltip content $('.fc-event').mouseenter(function() { if (tipTooltipRef == '' || tipTooltipRef == 'undefined'){ $(eID).tooltipster('content', 'Invalid image link 😔'); // OR simply: $(this).tooltipster('disable'); } else { var t = $(eID).attr('tt_title'), tt_Title = '<div class="ttTitle">'+t+'</div>' ; var tt_element = $(eID).find('.tooltipster-content'); tt_element.append(tt_Title); $(eID).tooltipster('option','contentAsHTML','true'); $(eID).tooltipster('content', tipTooltipRef); if (!$(eID).hasClass('tt_added')) { $(eID).tooltipster(); $(eID).tooltipster({ content: tipTooltipRef, //contentCloning: true, trigger: 'hover', //multiple: true, animation: 'fade', arrow: true, delay: 300, maxWidth: 600, contentAsHTML: true, //debug: true }); // bind on start events (triggered on mouseenter) $(eID).on('start', function(event) { if ($(event.instance.elementOrigin()).hasClass('tt_group')){ var instances = $.tooltipster.instances('.tt_group'), open = false, duration; $.each(instances, function (i, instance) { if (instance !== event.instance) { // if another instance is already open if (instance.status().open){ open = true; // get the current animationDuration duration = instance.option('animationDuration'); // close the tooltip without animation instance.option('animationDuration', 0); instance.close(); // restore the animationDuration to its normal value instance.option('animationDuration', duration); } } }); // if another instance was open if (open) { duration = event.instance.option('animationDuration'); // open the tooltip without animation event.instance.option('animationDuration', 0); event.instance.open(); // restore the animationDuration to its normal value event.instance.option('animationDuration', duration); // now that we have opened the tooltip, //the hover trigger must be stopped event.stop(); } } }); $(eID).addClass('tt_added'); } } }); } }, eventMouseover: function(view, event, element){ //TOOLTIPSTER: update any necessary Tooltip content var tipContent = $(this).attr('data-ttipster'); var id = event.id //$(this).attr('id'); var eID = '#'+id; var tipID = '#tt_'+id; if (tipContent == '' || tipContent == 'undefined'){ $(eID).tooltipster('content', 'Invalid image 🔗 detected: unable to display at present 😔'); $(eID).tooltipster('disable'); // or $(this).tooltipster('destroy'); } else { // TOOLTIPSTER: Not really req now as tipContent is set @ evenRender //$(eID).tooltipster('option','contentAsHTML','true'); $(eID).tooltipster('option','multiple','true'); $(eID).tooltipster({ functionInit: function(instance, helper){ var content = $(helper.origin).find(tipID).detach(); instance.content(content); } }); if (!$(this).hasClass('tt_added')) { $(eID).tooltipster(); $(eID).tooltipster({ content: tipContent, //contentCloning: true, trigger: 'hover', //multiple: true, animation: 'fade', arrow: true, delay: 300, //[300, 100] maxWidth: 600, contentAsHTML: true, debug: true }); // bind on start events (triggered on mouseenter) $(this).on('start', function(event) { if ($(event.instance.elementOrigin()).hasClass('tt_group')) { var instances = $.tooltipster.instances('.tt_group'), open = false, duration; $.each(instances, function (i, instance) { if (instance !== event.instance) { // if another instance is already open if (instance.status().open){ open = true; // get the current animationDuration duration = instance.option('animationDuration'); // close the tooltip without animation instance.option('animationDuration', 0); instance.close(); // restore the animationDuration to its normal value instance.option('animationDuration', duration); } } }); // if another instance was open if (open) { duration = event.instance.option('animationDuration'); // open the tooltip without animation event.instance.option('animationDuration', 0); event.instance.open(); // restore the animationDuration to its normal value event.instance.option('animationDuration', duration); // now that we have opened the tooltip, //the hover trigger must be stopped event.stop(); } } }); $(this).addClass('tt_added'); } } }, eventClick: function(event, element, view) { var e = (event.description); if (e != null){ var chr = e.length; // event click coded goes here alert(e); } } }); });
 /* tooltipster.js */ .tooltip_templates { display: none; } .tooltipster-content{ /*display: flex; flex-direction: column;*/ } .ttTitle { } /*! suit-flex-embed v1.4.0 | MIT License | github.com/suitcss */ .FlexEmbed { display: block; overflow: hidden; position: relative; } .FlexEmbed:before { content: ""; display: block; width: 100%; } .FlexEmbed--16by9:before { padding-bottom: 56.25%; } .FlexEmbed--4by3:before { padding-bottom: 75%; } .FlexEmbed--1by1:before { padding-bottom: 100%; } .CoverImage { background-position: 50%; background-repeat: no-repeat; background-size: cover; margin: 0 auto 1em; max-height: 600px; max-width: 600px; } .CoverImageX2 { background-color: #808080; background-position: 50%; background-repeat: no-repeat; background-size: 100% 100%; /*cover; contain;*/ margin: 0 auto 1em; max-height: 2400px; max-width: 1200px; }
 <!-- Bootstrap --> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.0/css/bootstrap.min.css" integrity="sha384-SI27wrMjH3ZZ89r4o+fGIJtnzkAnFs3E4qz9DIYioCQ5l9Rd/7UAa8DHcaL8jkWt" crossorigin="anonymous" /> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.0/js/bootstrap.min.js" integrity="sha384-3qaqj0lc6sV/qpzrc1N5DC6i1VRn/HyX4qdPaiEFbn54VjQBEU341pvjz7Dv3n6P" crossorigin="anonymous"></script> <!-- FulCalendar --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.1/fullcalendar.min.css" integrity="sha256-tXJP+v7nTXzBaEuLtVup1zxWFRV2jyVemY+Ir6/CTQU=" crossorigin="anonymous" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js" integrity="sha256-4iQZ6BVL4qNKlQ27TExEhBN1HFPvAvAMbFavKKosSWQ=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.1/fullcalendar.min.js" integrity="sha256-O04jvi1wzlLxXK6xi8spqNTjX8XuHsEOfaBRbbfUbJI=" crossorigin="anonymous"></script> <!-- Tooltipster --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tooltipster@4.2.7/dist/css/tooltipster.main.min.css" integrity="sha256-xlmCQ8IjIIx7gqrIAb5x5kEU30jJJm0/DEmrjgLow/E=" crossorigin="anonymous" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tooltipster@4.2.7/dist/css/tooltipster.bundle.min.css" integrity="sha256-Qc4lCfqZWYaHF5hgEOFrYzSIX9Rrxk0NPHRac+08QeQ=" crossorigin="anonymous" /> <script src="https://cdn.jsdelivr.net/npm/tooltipster@4.2.7/dist/js/tooltipster.main.min.js" integrity="sha256-9gPC19rdxygnD5cXHFodzczLKeucNZ/dgzLhkKvNtQM=" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/tooltipster@4.2.7/dist/js/tooltipster.bundle.min.js" integrity="sha256-NOU7KrY2aTI4PxDegqYUIknk9qfxVCS0E4JfE9aMwaA=" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/tooltipster@4.2.7/dist/js/plugins/tooltipster/SVG/tooltipster-SVG.min.js" integrity="sha256-b9JNfGq08bjI5FVdN3ZhjWBSRsOyF6ucACQwlvgVEU4=" crossorigin="anonymous"></script> <div id='calendar'></div>

Alternatively if you prefer a fiddle I made earlier: https://jsfiddle.net/magicmb/3manqpho/或者,如果您更喜欢我之前制作的小提琴: https : //jsfiddle.net/magicmb/3manqpho/


OPTIONAL: Additionally bonus question可选:额外的奖金问题

Another potential issue with our Tooltipster.JS implementation and perhaps I may have to create a separate SO case for this but I will mention it on here quickly anyway as I'm struggling to create a working fiddle for it.我们的 Tooltipster.JS 实现的另一个潜在问题,也许我可能需要为此创建一个单独的 SO 案例,但无论如何我都会在这里快速提及它,因为我正在努力为其创建一个工作小提琴。 What I was trying to do with my second event was to demonstrate another slightly odd Tooltipster behaviour:我试图用我的第二个事件做的是展示另一个稍微奇怪的 Tooltipster 行为:

Tooltipster seems to have difficulty with events that span several days and different rows in FullCalendar. Tooltipster 似乎难以处理FullCalendar中跨越几天不同行的事件。 They only seem to work if hovering on the first part of the event ie the bit in row1 and not when hovering over the second part in row2 .它们似乎只在悬停在事件的第一部分时起作用,即在row1 中的位,而不是在悬停在row2的第二部分上时。

Now unfortunately I haven't been able to show this on my test fiddle.现在不幸的是,我无法在我的测试小提琴上展示这一点。 Reason being is that it may very well be necessary to create separate events for each day (elements in FullCalendar), even though my single event seems to go to the end of the first row for some reason but not onto the next one.原因是很可能有必要为每一天创建单独的事件(FullCalendar 中的元素),即使我的单个事件似乎出于某种原因进入了第一行的末尾,但没有进入下一个。 Hence I haven't been able to show the quirky behaviour by creating an event that spans two weeks with a single start and single end date like I've done in my test case.因此,我无法像我在测试用例中所做的那样,通过创建一个跨越两周、具有单个开始日期和单个结束日期的事件来展示这种古怪的行为。

Our own system uses external data sources and this was never apparent.我们自己的系统使用外部数据源,而这一点从不明显。 Also it just works with our previous Tooltip.js implementation and initially I also thought it worked with Tooltipster, but now I'm not convinced.此外,它只适用于我们之前的 Tooltip.js 实现,最初我也认为它适用于 Tooltipster,但现在我不相信。 Perhaps this is just an issue with the later versions of Tooltipster [ EDIT : Actually due to previously using data-tooltip-content to store entire tooltip] or perhaps they work in a slightly different way from previous releases.也许这只是 Tooltipster [编辑:实际上是由于以前使用data-tooltip-content来存储整个工具提示] 的更高版本的一个问题,或者它们的工作方式与以前的版本略有不同。 In any case if any of you know something about this do feel free to mention it in addition to the main issue above which is getting the HTML tooltip to work using pointers inside data-tooltip-content .在任何情况下,如果你们中的任何人对此有所了解,除了上面的主要问题(使用data-tooltip-content指针使HTML 工具提示工作)之外,请随时提及它。

After quite a while contemplating and trying out various things as well as referencing Tootltipster & FullCalendar Docs and numerous Github issues etc I figured out my issues.经过一段时间的考虑和尝试各种事情以及参考 Tootltipster 和 FullCalendar Docs 以及许多 Github 问题等,我发现了我的问题。

Key step:关键步骤:

All the tooltips need to be created as part of the FullCalendar [eventRender] process and we do not trigger anything via [eventMouseover] .所有工具提示都需要作为 FullCalendar [eventRender]过程的一部分创建,我们不会通过 [eventMouseover] 触发任何内容 Also instead of binding the Tooltipster tooltip to event.id you need to associate it with tooltipster class or in my case the .tt_tooltip class due to the "tooltip" name conflict with Bootstrap .另外,不是将 Tooltipster 工具提示绑定到event.id您需要将它与tooltipster 类或在我的情况下与.tt_tooltip相关联,因为“工具提示”名称与 Bootstrap 冲突

Another important thing to note is that it only seems we are initialising each of the Tooltipster tooltips during [eventRender] as well as setting the options, the FullCalendar documentation states:另一个需要注意的重要事情是,我们似乎只是[eventRender]期间初始化每个 Tooltipster 工具提示以及设置选项, FullCalendar 文档指出:

eventRender

Triggered while an event is being rendered. A hook for modifying its DOM.

    function( event, element, view ) { }

event is the Event Object that is attempting to be rendered.

element is a newly created jQuery element that will be used for rendering.

Additional important step:额外的重要步骤:

We need to carry out a generic Tooltipster tooltip initiate towards the end of doc.ready for all previously created tooltips using the tt_tooltip class: $('.tt_tooltip').tooltipster();我们需要在doc.ready结束时使用tt_tooltip类为所有先前创建的工具提示执行通用Tooltipster 工具提示启动$('.tt_tooltip').tooltipster();

EDIT: As per my additional comment below this is just an example and in my test / live environment I had to call $('.tt_tooltip').tooltipster();编辑:根据我下面的附加评论,这只是一个示例,在我的测试/实时环境中,我不得不调用$('.tt_tooltip').tooltipster(); at the end of [ eventAfterAllRender: ] instead of doc.ready !在 [ eventAfterAllRender: ] 的末尾而不是doc.ready

Here's the corrected code sample:这是更正后的代码示例:

 $(document).ready(function() { $('#calendar').fullCalendar({ defaultView: 'month', header: '', defaultDate: '2020-03-01', events: [{ id: 'event1', className: 'GB', title: 'Tips for Writing Cleaner Code', description: 'I decided to write an article that will be useful for beginners to understand their mistakes and to put together some practices. /n source: hackernoon.com/tips-for-writing-cleaner-better-code-e36ffeb55526', start: '2020-03-02', end: '2020-03-02' }, { id: 'event2', className: 'NL', title: 'Modern Style of Javascript with Arrow Functions', description: 'The complete explanation of Arrow functions in Javascript, and how it helps developers to write flexible and consistent code. /n source: hackernoon.com/modern-style-of-javascript-with-arrow-functions-lg1x3474', start: '2020-03-04', end: '2020-03-11' } ], eventRender: function(event, element, view) { window.dataE = window.dataE || []; element.attr( 'id', event.id ); var eExist = false; // create array of event.IDs for use in [eventAfterAllRender] if (Array.isArray(dataE)){ var json = JSON.stringify(event.id), item = dataE.find(el => JSON.stringify(el) === json); if (typeof item !== 'undefined'){ return false; } else { dataE.push(event.id); eExist = true; } } var /* Vars */ desc = (event.description), url='', urlEvent1 = "https://hackernoon.com/hn-images/1*cmqZiJz1TuUedRoeI3g_Iw.jpeg", urlEvent2 = "https://images.unsplash.com/photo-1527427337751-fdca2f128ce5?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjEwMDk2Mn0", tipRef="tip_content_"+event.id, idTip="#"+tipRef /* End Vars */; // passing 2 extra image params manually - usually from seperate data routine if (event.title == 'Tips for Writing Cleaner Code') { url = urlEvent1; } else { url = urlEvent2; } var tt_ref = '#tt_'+event.id; //var tt_ref = 'tt_'+event.id; var className = ''+event.className; var cc = className.toLowerCase(); var tt = '<div class="tooltip_templates"><span id="tt_' + event.id + '" class="tooltip_content"><img src="' + url + '" width="350" height="auto"><p style="text-align:left;"><span class="flag-icon flag-icon-' + cc + '"></span> <span class="tt_title"><strong>' + event.title + '</strong></span><br><span class="tt_desc">optional desctiptive text can go here</span></p></span></div>'; element.attr( 'data-tooltip-content', tt_ref ); // the tooltip ref selector (pointer) element.attr( 'data-tt-tooltipster' ); element.attr( 'data-tt-tooltipster', tt ); // tootipster content stored for [AfterEventRender] element.attr( 'tt_title' ); element.attr( 'tt_title', event.title ); element.addClass('tt_tooltip'); // add the tooltipster class (using 'tt_tooltip' due to Bootstrap 'tooltip' conflict ) element.append(tt); // append tooltipster content to each fullCalendar element // Tooltipster - as per Tooltipster Doc use 'tooltip' class (in our case 'tt_tooltip' due to Bootstrap conflict) $('.tt_tooltip').tooltipster(); $('.tt_tooltip').tooltipster({ content: tt_ref, contentCloning: true, trigger: 'hover', multiple: true, animation: 'fade', arrow: true, delay: 300, maxWidth: 600, contentAsHTML: true, debug: true }); }, eventAfterAllRender: function(event, element){ // get events from dataE array created during [eventRender] var count = 0; for (var i=0; i<dataE.length; i++) { var id = dataE[i], eID = '#'+id ; // obtain the tooltip is selector & tooltipster data each event var tipTooltipRef = $('.fc-body').find(eID).closest('.tt_tooltip').attr('data-tooltip-content'); var tipTooltipsterContent = $('.fc-body').find(eID).closest('.tt_tooltip').attr('data-tt-tooltipster'); console.log("tipTooltipRef:", tipTooltipRef); console.log("tipTooltipsterContent:", tipTooltipsterContent); // update / disable Tooltipster content if necessary if (tipTooltipRef == '' || tipTooltipRef == 'undefined'){ $('.fc-body').find(eID).closest('.tt_tooltip').tooltipster('content', 'Invalid image link 😔'); } } }, eventMouseover: function(view, event, element){ //Not requried for Tooltipster Tooltips - handled by Tooltipster option (trigger: 'hover') }, eventClick: function(event, element, view) { var e = (event.description); if (e != null){ var chr = e.length; // event click coded goes here alert(e); } } //end: fullCalendar }); // Even though tooltips are created during [eventRender] the generic class gets initiated here. $('.tt_tooltip').tooltipster(); //{contentCloning: true} //end: doc.ready });
 /* tooltipster.js */ .tooltip_templates { display: none; } .tooltipster-content{ /*display: flex; flex-direction: column;*/ } .ttTitle { } /*! suit-flex-embed v1.4.0 | MIT License | github.com/suitcss */ .FlexEmbed { display: block; overflow: hidden; position: relative; } .FlexEmbed:before { content: ""; display: block; width: 100%; } .FlexEmbed--16by9:before { padding-bottom: 56.25%; } .FlexEmbed--4by3:before { padding-bottom: 75%; } .FlexEmbed--1by1:before { padding-bottom: 100%; } .CoverImage { background-position: 50%; background-repeat: no-repeat; background-size: cover; margin: 0 auto 1em; max-height: 600px; max-width: 600px; } .CoverImageX2 { background-color: #808080; background-position: 50%; background-repeat: no-repeat; background-size: 100% 100%; /*cover; contain;*/ margin: 0 auto 1em; max-height: 2400px; max-width: 1200px; }
 <!-- Bootstrap --> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.0/css/bootstrap.min.css" integrity="sha384-SI27wrMjH3ZZ89r4o+fGIJtnzkAnFs3E4qz9DIYioCQ5l9Rd/7UAa8DHcaL8jkWt" crossorigin="anonymous" /> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.0/js/bootstrap.min.js" integrity="sha384-3qaqj0lc6sV/qpzrc1N5DC6i1VRn/HyX4qdPaiEFbn54VjQBEU341pvjz7Dv3n6P" crossorigin="anonymous"></script> <!-- FulCalendar --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.1/fullcalendar.min.css" integrity="sha256-tXJP+v7nTXzBaEuLtVup1zxWFRV2jyVemY+Ir6/CTQU=" crossorigin="anonymous" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js" integrity="sha256-4iQZ6BVL4qNKlQ27TExEhBN1HFPvAvAMbFavKKosSWQ=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.1/fullcalendar.min.js" integrity="sha256-O04jvi1wzlLxXK6xi8spqNTjX8XuHsEOfaBRbbfUbJI=" crossorigin="anonymous"></script> <!-- Tooltipster --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tooltipster@4.2.7/dist/css/tooltipster.main.min.css" integrity="sha256-xlmCQ8IjIIx7gqrIAb5x5kEU30jJJm0/DEmrjgLow/E=" crossorigin="anonymous" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tooltipster@4.2.7/dist/css/tooltipster.bundle.min.css" integrity="sha256-Qc4lCfqZWYaHF5hgEOFrYzSIX9Rrxk0NPHRac+08QeQ=" crossorigin="anonymous" /> <script src="https://cdn.jsdelivr.net/npm/tooltipster@4.2.7/dist/js/tooltipster.main.min.js" integrity="sha256-9gPC19rdxygnD5cXHFodzczLKeucNZ/dgzLhkKvNtQM=" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/tooltipster@4.2.7/dist/js/tooltipster.bundle.min.js" integrity="sha256-NOU7KrY2aTI4PxDegqYUIknk9qfxVCS0E4JfE9aMwaA=" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/tooltipster@4.2.7/dist/js/plugins/tooltipster/SVG/tooltipster-SVG.min.js" integrity="sha256-b9JNfGq08bjI5FVdN3ZhjWBSRsOyF6ucACQwlvgVEU4=" crossorigin="anonymous"></script> <div id='calendar'></div>

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

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