Extraordinary Tooltips User Guide - Salvatos/Kanka-Cookbook GitHub Wiki
This page contains comprehensive instructions and examples for my Extraordinary Tooltips plugin. This information is hosted here since the Marketplace can’t easily show code examples, which will be many. I recommend reading my article about using transclusion on Kanka before you start using this plugin. Once you’re familiar with the possibilities and limitations, feel free to jump to The Actual Code if you only want the instructions.
As discussed in the transclusion guide above, there are two sources of content that can be used for transclusion with this plugin: an attribute or an entity’s entry. Both have some limitations regarding the HTML they can contain or the way it’s displayed, which means you might use both for different types of content. Their differences are summarized in the table below.
There is also a third approach, which is to combine multiple sources in order to end up with all desired content in the tooltip. This significantly increases complexity and runs a higher risk of being patched out of Kanka, so most of the guide will focus on using a single source.
Feature/Limitation | Entries | Attributes | Combined (nightmare mode) |
---|---|---|---|
Entity mention and attribute mention parsing | Yes, since Kanka 1.33. However if your target entry also contains entry mentions, those will not be transcluded (i.e. only one level of transclusion depth is allowed) and the mention code will be shown instead. | Yes | Yes |
Full HTML support (subject to Kanka’s whitelist) | Yes | No - tables, details/summary (spoilers), iframes and external links are stripped from attributes. | Yes, if the elements disabled in attributes reside in entries. |
Amount of markup required | Two to three HTML tags and a mention tag are needed to create the tooltip. Trigger words in paragraphs (as opposed to occupying their own line) require more manipulation to force the paragraph to accept large amounts of content. The code editor must be used either way. Use of my Marketplace Toolbar for Summernote userscript is highly recommended to quickly insert the required markup for each type of transclusion. | ||
As above. For creating the transcluded content itself, this is the most convenient option. | Since attribute fields don’t have a visual editor, for extensive content and markup you will likely want to generate your transcluded HTML elsewhere, then paste it into the attribute. This also makes subsequent edits less convenient. | Transclusion code is the same, but managing attributes that transclude entries and vice-versa and keeping track of how everything fits together is a tall order. Best reserved to very specific content that will never change once set up. | |
Ease of styling | Classes can be added to the transclusion code to create various box types. The trigger can also be styled regardless of the source. | ||
The target entity’s tags are also listed in the mention and can be used to determine the tooltip’s inner styles instead of manually adding classes to the transclusion code, as will be described later on. | As above. Note that entry and attribute mentions use slightly different markup and classes. | The added layering of attributes in entries and entries in attributes may require additional CSS rules or more complex selectors. |
To better understand why this plugin is so complicated, let’s quickly look at the markup for Kanka’s mentions and the challenges they create for us. If you prefer to trust me and follow instructions blindly, feel free to jump straight to The Actual Code. The main point being that there are three types of mentions with different HTML structures, and this plugin attempts to handle them consistently and override some default behaviours.
Attribute mention markup:
<span class="attribute attribute-mention" ... data-toggle="tooltip" data-original-title="attribute name...">
Attribute value
</span>
Entity mention markup:
<a ... class="entity-mention" data-entity-tags="tag ids and names..." data-toggle="tooltip-ajax" ...>
Entity name
</a>
Or, when mentioning/transcluding an entry specifically with the [entity:1|field:entry]
syntax:
<div class="entity-mention mention-field-entry" data-entity-tags="tag ids and names...">
<a ... class="entity-mention-name block mb-2" data-toggle="tooltip-ajax" ...>
Entity name
</a>
<div class="mention-entry-content">
Entity content
</div>
</div>
Each type of mention has a different type of Kanka tooltip toggle – a short excerpt for entities, where only some HTML tags are rendered, or the attribute’s name for attributes. This plugin hides the native Kanka tooltip to avoid having two or more tooltips on-screen at once.
With that out of the way, here is the actual transclusion code you need to use for each source. Note that the code differs depending on where you use it: on its own line or as part of an inline or inline-block element like paragraphs and lists.
Source* | Standalone |
---|---|
Entity |
<span class="ExT-trigger">Trigger</span>
<div class="ExT-wrapper ExT-entry">
<span class="ExT-wrap">
[entity:1|field:entry]
</span>
</div> |
Attribute |
<span class="ExT-trigger">Trigger</span>
<div class="ExT-wrapper ExT-attribute">{attribute:1}</div> |
Inside paragraphs et al. | |
Entity |
<p class="ExT-inline">Text</p>
<span class="ExT-trigger">Trigger</span>
<div class="ExT-wrapper ExT-entry">
<span class="ExT-wrap">
[entity:1|field:entry]
</span>
</div>
<p class="ExT-inline">Text</p> |
Attribute |
<p class="ExT-inline">Text</p>
<span class="ExT-trigger">Trigger</span>
<div class="ExT-wrapper ExT-attribute">{attribute:1}</div>
<p class="ExT-inline">Text</p> |
*For combined sources, use the code for the "master" source that holds the rest of your content, e.g. the attribute that refers to entries, or the entry that refers to attributes.
Note that multiple mentions of the same type can be added to a single ExT, though the output may be broken if all sources aren’t structured and meant to be styled the same way. The same approach could be useful to display a succession of concise attributes and entries instead of having them transclude one another into a single mixed source, though there is currently no out-of-the-box support for combining entries and attributes.
For standalone entity mentions, as you can see, we need to use advanced mention syntax to specify field:entry
. For attributes, we can simply use the attribute’s universal ID (you can quickly get the mention code by clicking an attribute’s name in an entity’s Attributes subpage, as long as it doesn’t have an attribute template, or you can get the mention code by typing an opening bracket in Summernote on the source entity and part of the attribute’s name - e.g. "{attrib" - to invoke a dropdown that will convert it into a universal attribute mention such as {attribute:12345}
).
For mentions in paragraphs (and lists, etc.), you may have noticed that the trigger span and the container div are not actually in a paragraph, but lodged between two different paragraphs with the ExT-inline
class. The reason is fairly technical, but if you are curious: paragraphs are block-level elements (which always start on a new line and take up the full width available) by default, and can only contain phrasing content. In simpler terms, a paragraph cannot contain another paragraph, nor various other block-level elements – and that’s a problem if we want large amounts of text, pictures, tables, etc. in our tooltips.
As such, our workaround is to place our trigger and tooltip content between two paragraphs, and to use CSS to make all of these elements *inline*, i.e. force the trigger to come immediately after the first paragraph, and the second paragraph immediately after the trigger and tooltip content. This is all handled by the plugin and accounts for various situations, so all you need to do is follow the code structure as given, with the necessary classes on each element.
It’s worth noting that if your tooltip contains only phrasing content (see link above), or in other words if the entry you transclude has only simple text without paragraphs, you can safely use the simpler standalone syntax even in a paragraph.
My Marketplace Toolbar for Summernote makes the process of selecting the right markup for each use case easier and provides a visual example in real time:
This form is accessible via the HTML inserter dropdown by selecting "Extraordinary Tooltips Helper".
In the code samples above, the trigger is just a word in a span element. You can also place an entity mention in that span, for example to link to a different entity than the one you’re using for the tooltip. It could also be an image instead of a span, as long as it has the ExT-trigger
class and comes immediately before the tooltip’s container. Note however that the icon that is normally added next to span triggers will not appear next to images (because an image cannot have an ::after
pseudo-element attached to it).
The no-icon
class can be added to a trigger to disable the accompanying icon, and the icon can be customized using CSS custom properties:
:root {
--ExT-trigger-icon: " \f00e";
--ExT-trigger-icon-font: "FontAwesome";
}
The actual content that will be displayed in your tooltip is held in a div with the ExT-wrapper ExT-entry
or ExT-wrapper ExT-attribute
classes. Both combinations essentially work the same, but allow us to style the container differently since the markup of each type of mention differs slightly. Unlike paragraphs, divs can contain virtually any other HTML element, which gives us maximum freedom. This element should not be changed, but you can add other classes (and an ID) to it to design various styles for different types of content.
For entity mentions, the container is structured as follows:
<div class="ExT-wrapper ExT-entry">
<span class="ExT-wrap">
<div class="entity-mention mention-field-entry" data-entity-tags="tag ids and names...">
<a ... class="entity-mention-name block mb-2" data-toggle="tooltip-ajax" ...>
<!-- Entity name -->
</a>
<div class="mention-entry-content">
<!-- Entity content -->
</div>
</div>
</span>
</div>
For attribute mentions, the container is structured as follows:
<div class="ExT-wrapper ExT-attribute">
<span class="attribute attribute-mention"...>
<!-- attribute value -->
</span>
</div>
Note that ExT-wrap
is not added with attributes since those mentions are already wrapped in a span by Kanka. This second layer of wrapping on both types of tooltips makes it so that you can more easily do complex formatting on the outside of your tooltip, for example complex border designs on the outside with ExT-attribute
and inner padding or scrollbars with attribute-mention
.
Note that for entity mentions only, you can rely on the source entity’s tags to style the tooltip’s content thanks to the data-entity-tags
attribute. Thus, you can make use of an attribute selector to match a tag’s name:
.ExT-entry .mention-field-entry[data-entity-tags~="item-card"] .entity-mention-name {
/* Special rule for the tooltip title of entities tagged with "Item Card" */
}
However, this does not allow changing outer elements of the tooltip like ExT-wrapper
.
At this point, a few things should be said about the nature and capabilities of the tooltips as interactive, responsive elements. Normally, this type of feature relies on JavaScript fairly heavily for responding to mouse actions and intelligent and responsive positioning, as is the case for Kanka’s own tooltips. But since Kanka doesn’t allow custom JavaScript, we’re forced to make some safe but inflexible assumptions for positioning and toggling the display of our content. Namely, we are forced to either display it in the middle of the screen with fixed dimensions, superimposed over the rest of the page, or immediately under the trigger element, displacing the rest of the page’s content to make room for the "tooltip" and behaving more like a spoiler block.
As such, Extraordinary Tooltips offers two modes you can choose from by setting the corresponding class on the container:
-
Fixed mode – e.g.
ExT-wrapper fixed
– places the tooltip in the middle of the screen, superimposed; -
Affixed mode – e.g.
ExT-wrapper affixed
– places the tooltip directly under the trigger element.
In fixed mode, since there can be some distance between the trigger and the tooltip, the tooltip fades in and out over less than a second. This transition allows the user to move the pointer from the trigger to the tooltip without the latter immediately disappearing, which would prevent interaction with the content. However, this gives it a less "professional" feel, makes the connection between the trigger and tooltip less obvious and can often lead to the tooltip obscuring the trigger completely, which is problematic if your trigger is a link and hovering it makes it unclickable.
The examples below give a good overview of the appearance and downsides of each mode.
The default appearance of an Extraordinary Tooltip, with basic colors, borders and padding.
A simple box design to embed text and tables – here, an item’s description and stats are shown in much the same way as they would in a styled details/summary block. This affixed example demonstrates how the two wrappers allow us to have a scrollbar on the inside that does not interfere with box borders. It also shows that text can be interacted with without the tooltip closing. Because the trigger here is the only content in its list item, the simpler standalone code is used without any side effects.
Here, two mentions were put in the same tooltip. Because both entries are formatted the same, this yields an acceptable result without any extra markup or CSS. Notice how this large, fixed tooltip almost completely obscures the trigger next to the pointer. Since Kanka 1.33, the titles in tooltips are added automatically and link to the source entity, so this is only an issue if your trigger link points somewhere else.
Here, the trigger is a small icon in running text and the tooltip explains its meaning. Attributes work well for such small content, where a whole series can be maintained in the same entity, though entries are easier to refer to on the fly since Summernote offers suggestions as you start typing their entity name with the @
or [
syntax. This example shows another possible issue with fixed mode, where the tooltip is so far from the trigger that it looks unrelated. This is less noticeable with larger content.
A partial recreation of the Dungeon World Playbook character sheet from the Marketplace. Note that conditional logic and dynamic values are not available without Marketplace attribute templates, so this approach is only useful for standardized, static information.
An attribute-based NPC sheet for Unity RPG. The header color is based on a checkbox value for the NPC’s "elite" status, as standard for the system. The attribute’s markup contains this segment:
<div class="titlebar elite{elite}">
Accordingly, the CSS for the sheet expects two possible classes: elite0
(unchecked) or elite1
(checked). This sort of approach can be used to mimic simple if/else conditions based on checkboxes.
I hope these can inspire you to create your own, and even share them on the Marketplace. I’d love to see how far everyone can run with this!