I wrote the following extension to the JQuery UI tooltip widget that allows the tooltip to have context on getting its content from a HTMLElement's html. However, I have the 'title' attribute hard coded but I would like to use whatever attribute is defined in options.items. For example if they want the tooltip to use alt
tag then the extention populates that attribute with the html content.
Also I am looking for the jquery ui way of correctly escaping the contentId
string concatenation
$(function() {
(function() {
var cache = {};
$.widget("custom.tooltipContent", $.ui.tooltip, {
_init: function() {
this._super();
this.options.content = function() {
return $(this).attr("title");
};
this.element.attr("title", function() {
var contentId = $(this).attr("data-tooltip-content");
if (!cache[contentId]) {
cache[contentId] = $("[data-tooltip-content-id=" + contentId + "]").remove().html();
}
return cache[contentId];
});
}
});
})();
});
http://jsfiddle.net/5d7sqx89/1/
Instead of title or items options I would suggest you to use a new option. You may call it itemsData. This in order to avoid to parse the content of items as a selector.
$("span").tooltipContent({
itemsData: "data-tooltip-content",
show: {
effect: "slideDown",
delay: 50
}
})
itemsData: selector of the data to be displayed according to your pattern:
data-tooltip-content --> data-tooltip-content-id
(function () {
$.widget("custom.tooltipContent", $.ui.tooltip, {
_init: function () {
this._super();
var _self = this;
var datasetName = 'tooltipContent';
// this in order to fire always content function...
_self.options.items = (_self.options.items.indexOf('[title]') != -1) ? '[data-tooltip-content]' : _self.options.items;
// normalize itemsData
_self.options.itemsData = _self.options.itemsData || "data-tooltip-content";
// get the html to be displayed later and save it into a data attribute
var contentSelector = "[" + _self.options.itemsData + "-id=" + _self.element.data(datasetName) + "]";
_self.element.data(datasetName, $(contentSelector).html());
this.options.content = function () {
return _self.element.data(datasetName);
};
}
});
})();
$("span").tooltipContent({
itemsData: "data-tooltip-content",
show: {
effect: "slideDown",
delay: 50
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>
<span id="test1" data-tooltip-content="x">Help 1</span>
<span id="test2" data-tooltip-content="x">Help 1</span>
<span id="test3" data-tooltip-content="y">Help 2</span>
<span id="test4" data-tooltip-content="y">Help 2</span>
<div style="display:none" data-tooltip-content-id="x">
Shared content for <b>help 1</b>
</div>
<div style="display:none" data-tooltip-content-id="y">
<table style="width:100%">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
</table>
</div>
Another approach can be based on how a bootstrap button open a modal. Now your data-tooltip-content attribute has to contain the selector of the data to be displayed:
<span id="test1" data-tooltip-content="#x">Help 1</span>
<span id="test2" data-tooltip-content="#x">Help 1</span>
<span id="test3" data-tooltip-content="#y">Help 2</span>
<span id="test4" data-tooltip-content="#y">Help 2</span>
<div id="x" style="display:none">
Shared content for <b>help 1</b>
</div>
<div id="y" style="display:none">
<table style="width:100%">
.......................
The code now is more easy.
(function () {
$.widget("custom.tooltipContent", $.ui.tooltip, {
_init: function () {
this._super();
var _self = this;
var datasetName = 'tooltipContent';
// this in order to fire always content function...
_self.options.items = (_self.options.items.indexOf('[title]') != -1) ? '[data-tooltip-content]' : _self.options.items;
// get the html to be displayed later and save it into a data attribute
var html = '';
if (_self.options.itemsData === undefined) {
html = _self.element.attr('title') || '';
} else {
html = $(_self.element.data(datasetName)).html();
}
_self.element.data(datasetName, html);
this.options.content = function () {
return _self.element.data(datasetName);
};
}
});
})();
$("span").tooltipContent({
items: "span[id^=test]", // optional
itemsData: "data-tooltip-content",
show: {
effect: "slideDown",
delay: 50
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>
<span id="test1" data-tooltip-content="#x">Help 1</span>
<span id="test2" data-tooltip-content="#x">Help 1</span>
<span id="test3" data-tooltip-content="#y">Help 2</span>
<span id="test4" data-tooltip-content="#y">Help 2</span>
<div id="x" style="display:none">
Shared content for <b>help 1</b>
</div>
<div id="y" style="display:none">
<table style="width:100%">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
</table>
</div>
I am not sure if this needs to be a widget. I would do the following:
$(function() {
$("span").tooltip({
items: "[data-tooltip-rel]",
content: function() {
var id = $(this).attr("data-tooltip-rel");
var cont = $("[data-tooltip-content-id='" + id + "']");
return cont.html();
}
});
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<span id="test" data-tooltip-rel="x">Help 1</span>
<span data-tooltip-rel="x">Help 1</span>
<span data-tooltip-rel="y">Help 2</span>
<span data-tooltip-rel="y">Help 2</span>
<div style="display:none" data-tooltip-content-id="x">
Shared content for <b>help 1</b>
</div>
<div style="display:none" data-tooltip-content-id="y">
<table style="width:100%">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
</table>
</div>
If you feel you need to custom widget, you could do this.
$(function() {
$.widget("custom.tooltipContent", $.ui.tooltip, {
options: {
items: "[data-tooltip-rel]",
content: function() {
return $("[data-tooltip-content-id='" + $(this).attr("data-tooltip-rel") + "']").html();
}
}
});
$("span").tooltipContent();
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<span id="test" data-tooltip-rel="x">Help 1</span>
<span data-tooltip-rel="x">Help 1</span>
<span data-tooltip-rel="y">Help 2</span>
<span data-tooltip-rel="y">Help 2</span>
<div style="display:none" data-tooltip-content-id="x">
Shared content for <b>help 1</b>
</div>
<div style="display:none" data-tooltip-content-id="y">
<table style="width:100%">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
</table>
</div>
Hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With