Developed by Caleb Jacob under the MIT license http://opensource.org/licenses/MIT
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
;(function($,window,document){
varpluginName="tooltipster",
defaults={
animation:'fade',
arrow:true,
arrowColor:'',
autoClose:true,
content:null,
contentAsHTML:false,
contentCloning:true,
debug:true,
delay:200,
minWidth:0,
maxWidth:null,
functionInit:function(origin,content){},
functionBefore:function(origin,continueTooltip){
continueTooltip();
},
functionReady:function(origin,tooltip){},
functionAfter:function(origin){},
icon:'(?)',
iconCloning:true,
iconDesktop:false,
iconTouch:false,
iconTheme:'tooltipster-icon',
interactive:false,
interactiveTolerance:350,
multiple:false,
offsetX:0,
offsetY:0,
onlyOne:false,
position:'top',
positionTracker:false,
speed:350,
timer:0,
theme:'tooltipster-default',
touchDevices:true,
trigger:'hover',
updateAnimation:true
};
functionPlugin(element,options){
// list of instance variables
this.bodyOverflowX;
// stack of custom callbacks provided as parameters to API methods
this.callbacks={
hide:[],
show:[]
};
this.checkInterval=null;
// this will be the user content shown in the tooltip. A capital "C" is used because there is also a method called content()
this.Content;
// this is the original element which is being applied the tooltipster plugin
this.$el=$(element);
// this will be the element which triggers the appearance of the tooltip on hover/click/custom events.
// it will be the same as this.$el if icons are not used (see in the options), otherwise it will correspond to the created icon
this.$elProxy;
this.elProxyPosition;
this.enabled=true;
this.options=$.extend({},defaults,options);
this.mouseIsOverProxy=false;
// a unique namespace per instance, for easy selective unbinding
// disable the plugin on old browsers (including IE7 and lower)
if(document.querySelector){
// note : the content is null (empty) by default and can stay that way if the plugin remains initialized but not fed any content. The tooltip will just not appear.
// if content is provided in the options, its has precedence over the title attribute. Remark : an empty string is considered content, only 'null' represents the absence of content.
if(self.options.content!==null){
self._content_set(self.options.content);
}
else{
// the same remark as above applies : empty strings (like title="") are considered content and will be shown. Do not define any attribute at all if you want to initialize the plugin without content at start.
// strip the title off of the element to prevent the default tooltips from popping up
.removeAttr('title')
// to be able to find all instances on the page later (upon window events in particular)
.addClass('tooltipstered');
// detect if we're changing the tooltip origin to an icon
// note about this condition : if the device has touch capability and self.options.iconTouch is false, you'll have no icons event though you may consider your device as a desktop if it also has a mouse. Not sure why someone would have this use case though.
// TODO : the tooltip should be automatically be given an absolute position to be near the origin. Otherwise, when the origin is floating or what, it's going to be nowhere near it and disturb the position flow of the page elements. It will imply that the icon also detects when its origin moves, to follow it : not trivial.
// Until it's done, the icon feature does not really make sense since the user still has most of the work to do by himself
// if the icon provided is in the form of a string
// (deep) clone the object if iconCloning == true, to make sure every instance has its own proxy. We use the icon without wrapping, no need to. We do not give it a class either, as the user will undoubtedly style the object on his own and since our css properties may conflict with his own
// for 'click' and 'hover' triggers : bind on events to open the tooltip. Closing is now handled in _showNow() because of its bindings.
// Notes about touch events :
// - mouseenter, mouseleave and clicks happen even on pure touch devices because they are emulated. deviceIsPureTouch() is a simple attempt to detect them.
// - on hybrid devices, we do not prevent touch gesture from opening tooltips. It would be too complex to differentiate real mouse events from emulated ones.
// - we check deviceIsPureTouch() at each event rather than prior to binding because the situation may change during browsing
// will check if our tooltip origin is removed while the tooltip is shown
self._interval_set();
// reposition on scroll (otherwise position:fixed element's tooltips will move away form their origin) and on resize (in case position can/has to be changed)
// clone if asked. Cloning the object makes sure that each instance has its own version of the content (in case a same object were provided for several instances)
// if we are not in the context of jQuery wrapped HTML element(s) :
// this happens when calling static methods in the form $.fn.tooltipster('methodName'), or when calling $(sel).tooltipster('methodName or options') where $(sel) does not match anything
if(this.length===0){
// if the first argument is a method name
if(typeofargs[0]==='string'){
varmethodIsStatic=true;
// list static methods here (usable by calling $.fn.tooltipster('methodName');)
switch(args[0]){
case'setDefaults':
// change default options for all future instances
$.extend(defaults,args[1]);
break;
default:
methodIsStatic=false;
break;
}
// $.fn.tooltipster('methodName') calls will return true
if(methodIsStatic)returntrue;
// $(sel).tooltipster('methodName') calls will return the list of objects event though it's empty because chaining should work on empty lists
elsereturnthis;
}
// the first argument is undefined or an object of options : we are initalizing but there is no element matched by selector
else{
// still chainable : same as above
returnthis;
}
}
// this happens when calling $(sel).tooltipster('methodName or options') where $(sel) matches one or more elements
else{
// method calls
if(typeofargs[0]==='string'){
varv='#*$~&';
this.each(function(){
// retrieve the namepaces of the tooltip(s) that exist on that element. We will interact with the first tooltip only.
varns=$(this).data('tooltipster-ns'),
// self represents the instance of the first tooltipster plugin associated to the current HTML object of the loop
self=ns?$(this).data(ns[0]):null;
// if the current element holds a tooltipster instance
/* This next selector defines the color of the border on the outside of the arrow. This will automatically match the color and size of the border set on the main tooltip styles. Set display: none; if you would like a border around the tooltip but no border around the arrow */
/* If you're using the icon option, use this next selector to style them */
.tooltipster-icon{
cursor:help;
margin-left:4px;
}
/* This is the base styling required to make all Tooltipsters work */
.tooltipster-base{
padding:0;
font-size:0;
line-height:0;
position:absolute;
left:0;
top:0;
z-index:9999999;
pointer-events:none;
width:auto;
overflow:visible;
}
.tooltipster-base.tooltipster-content{
overflow:hidden;
}
/* These next classes handle the styles for the little arrow attached to the tooltip. By default, the arrow will inherit the same colors and border as what is set on the main tooltip itself. */
/* CSS transition for when contenting is changing in a tooltip that is still open. The only properties that will NOT transition are: width, height, top, and left */