301 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			301 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| ;(function ($, window, document, undefined) {
 | |
|   'use strict';
 | |
| 
 | |
|   Foundation.libs.tooltip = {
 | |
|     name : 'tooltip',
 | |
| 
 | |
|     version : '5.4.7',
 | |
| 
 | |
|     settings : {
 | |
|       additional_inheritable_classes : [],
 | |
|       tooltip_class : '.tooltip',
 | |
|       append_to: 'body',
 | |
|       touch_close_text: 'Tap To Close',
 | |
|       disable_for_touch: false,
 | |
|       hover_delay: 200,
 | |
|       show_on : 'all',
 | |
|       tip_template : function (selector, content) {
 | |
|         return '<span data-selector="' + selector + '" id="' + selector + '" class="'
 | |
|           + Foundation.libs.tooltip.settings.tooltip_class.substring(1)
 | |
|           + '" role="tooltip">' + content + '<span class="nub"></span></span>';
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     cache : {},
 | |
| 
 | |
|     init : function (scope, method, options) {
 | |
|       Foundation.inherit(this, 'random_str');
 | |
|       this.bindings(method, options);
 | |
|     },
 | |
| 
 | |
|     should_show: function (target, tip) {
 | |
|       var settings = $.extend({}, this.settings, this.data_options(target));
 | |
| 
 | |
|       if (settings.show_on === 'all') {
 | |
|         return true;
 | |
|       } else if (this.small() && settings.show_on === 'small') {
 | |
|         return true;
 | |
|       } else if (this.medium() && settings.show_on === 'medium') {
 | |
|         return true;
 | |
|       } else if (this.large() && settings.show_on === 'large') {
 | |
|         return true;
 | |
|       }
 | |
|       return false;
 | |
|     },
 | |
| 
 | |
|     medium : function () {
 | |
|       return matchMedia(Foundation.media_queries['medium']).matches;
 | |
|     },
 | |
| 
 | |
|     large : function () {
 | |
|       return matchMedia(Foundation.media_queries['large']).matches;
 | |
|     },
 | |
| 
 | |
|     events : function (instance) {
 | |
|       var self = this,
 | |
|           S = self.S;
 | |
| 
 | |
|       self.create(this.S(instance));
 | |
| 
 | |
|       $(this.scope)
 | |
|         .off('.tooltip')
 | |
|         .on('mouseenter.fndtn.tooltip mouseleave.fndtn.tooltip touchstart.fndtn.tooltip MSPointerDown.fndtn.tooltip',
 | |
|           '[' + this.attr_name() + ']', function (e) {
 | |
|           var $this = S(this),
 | |
|               settings = $.extend({}, self.settings, self.data_options($this)),
 | |
|               is_touch = false;
 | |
| 
 | |
|           if (Modernizr.touch && /touchstart|MSPointerDown/i.test(e.type) && S(e.target).is('a')) {
 | |
|             return false;
 | |
|           }
 | |
| 
 | |
|           if (/mouse/i.test(e.type) && self.ie_touch(e)) return false;
 | |
| 
 | |
|           if ($this.hasClass('open')) {
 | |
|             if (Modernizr.touch && /touchstart|MSPointerDown/i.test(e.type)) e.preventDefault();
 | |
|             self.hide($this);
 | |
|           } else {
 | |
|             if (settings.disable_for_touch && Modernizr.touch && /touchstart|MSPointerDown/i.test(e.type)) {
 | |
|               return;
 | |
|             } else if(!settings.disable_for_touch && Modernizr.touch && /touchstart|MSPointerDown/i.test(e.type)) {
 | |
|               e.preventDefault();
 | |
|               S(settings.tooltip_class + '.open').hide();
 | |
|               is_touch = true;
 | |
|             }
 | |
| 
 | |
|             if (/enter|over/i.test(e.type)) {
 | |
|               this.timer = setTimeout(function () {
 | |
|                 var tip = self.showTip($this);
 | |
|               }.bind(this), self.settings.hover_delay);
 | |
|             } else if (e.type === 'mouseout' || e.type === 'mouseleave') {
 | |
|               clearTimeout(this.timer);
 | |
|               self.hide($this);
 | |
|             } else {
 | |
|               self.showTip($this);
 | |
|             }
 | |
|           }
 | |
|         })
 | |
|         .on('mouseleave.fndtn.tooltip touchstart.fndtn.tooltip MSPointerDown.fndtn.tooltip', '[' + this.attr_name() + '].open', function (e) {
 | |
|           if (/mouse/i.test(e.type) && self.ie_touch(e)) return false;
 | |
| 
 | |
|           if($(this).data('tooltip-open-event-type') == 'touch' && e.type == 'mouseleave') {
 | |
|             return;
 | |
|           }
 | |
|           else if($(this).data('tooltip-open-event-type') == 'mouse' && /MSPointerDown|touchstart/i.test(e.type)) {
 | |
|             self.convert_to_touch($(this));
 | |
|           } else {
 | |
|             self.hide($(this));
 | |
|           }
 | |
|         })
 | |
|         .on('DOMNodeRemoved DOMAttrModified', '[' + this.attr_name() + ']:not(a)', function (e) {
 | |
|           self.hide(S(this));
 | |
|         });
 | |
|     },
 | |
| 
 | |
|     ie_touch : function (e) {
 | |
|       // How do I distinguish between IE11 and Windows Phone 8?????
 | |
|       return false;
 | |
|     },
 | |
| 
 | |
|     showTip : function ($target) {
 | |
|       var $tip = this.getTip($target);
 | |
|       if (this.should_show($target, $tip)){
 | |
|         return this.show($target);
 | |
|       }
 | |
|       return;
 | |
|     },
 | |
| 
 | |
|     getTip : function ($target) {
 | |
|       var selector = this.selector($target),
 | |
|           settings = $.extend({}, this.settings, this.data_options($target)),
 | |
|           tip = null;
 | |
| 
 | |
|       if (selector) {
 | |
|         tip = this.S('span[data-selector="' + selector + '"]' + settings.tooltip_class);
 | |
|       }
 | |
| 
 | |
|       return (typeof tip === 'object') ? tip : false;
 | |
|     },
 | |
| 
 | |
|     selector : function ($target) {
 | |
|       var id = $target.attr('id'),
 | |
|           dataSelector = $target.attr(this.attr_name()) || $target.attr('data-selector');
 | |
| 
 | |
|       if ((id && id.length < 1 || !id) && typeof dataSelector != 'string') {
 | |
|         dataSelector = this.random_str(6);
 | |
|         $target
 | |
|           .attr('data-selector', dataSelector)
 | |
|           .attr('aria-describedby', dataSelector);
 | |
|       }
 | |
| 
 | |
|       return (id && id.length > 0) ? id : dataSelector;
 | |
|     },
 | |
| 
 | |
|     create : function ($target) {
 | |
|       var self = this,
 | |
|           settings = $.extend({}, this.settings, this.data_options($target)),
 | |
|           tip_template = this.settings.tip_template;
 | |
| 
 | |
|       if (typeof settings.tip_template === 'string' && window.hasOwnProperty(settings.tip_template)) {
 | |
|         tip_template = window[settings.tip_template];
 | |
|       }
 | |
| 
 | |
|       var $tip = $(tip_template(this.selector($target), $('<div></div>').html($target.attr('title')).html())),
 | |
|           classes = this.inheritable_classes($target);
 | |
| 
 | |
|       $tip.addClass(classes).appendTo(settings.append_to);
 | |
| 
 | |
|       if (Modernizr.touch) {
 | |
|         $tip.append('<span class="tap-to-close">'+settings.touch_close_text+'</span>');
 | |
|         $tip.on('touchstart.fndtn.tooltip MSPointerDown.fndtn.tooltip', function(e) {
 | |
|           self.hide($target);
 | |
|         });
 | |
|       }
 | |
| 
 | |
|       $target.removeAttr('title').attr('title','');
 | |
|     },
 | |
| 
 | |
|     reposition : function (target, tip, classes) {
 | |
|       var width, nub, nubHeight, nubWidth, column, objPos;
 | |
| 
 | |
|       tip.css('visibility', 'hidden').show();
 | |
| 
 | |
|       width = target.data('width');
 | |
|       nub = tip.children('.nub');
 | |
|       nubHeight = nub.outerHeight();
 | |
|       nubWidth = nub.outerHeight();
 | |
| 
 | |
|       if (this.small()) {
 | |
|         tip.css({'width' : '100%' });
 | |
|       } else {
 | |
|         tip.css({'width' : (width) ? width : 'auto'});
 | |
|       }
 | |
| 
 | |
|       objPos = function (obj, top, right, bottom, left, width) {
 | |
|         return obj.css({
 | |
|           'top' : (top) ? top : 'auto',
 | |
|           'bottom' : (bottom) ? bottom : 'auto',
 | |
|           'left' : (left) ? left : 'auto',
 | |
|           'right' : (right) ? right : 'auto'
 | |
|         }).end();
 | |
|       };
 | |
| 
 | |
|       objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', target.offset().left);
 | |
| 
 | |
|       if (this.small()) {
 | |
|         objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', 12.5, $(this.scope).width());
 | |
|         tip.addClass('tip-override');
 | |
|         objPos(nub, -nubHeight, 'auto', 'auto', target.offset().left);
 | |
|       } else {
 | |
|         var left = target.offset().left;
 | |
|         if (Foundation.rtl) {
 | |
|           nub.addClass('rtl');
 | |
|           left = target.offset().left + target.outerWidth() - tip.outerWidth();
 | |
|         }
 | |
|         objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', left);
 | |
|         tip.removeClass('tip-override');
 | |
|         if (classes && classes.indexOf('tip-top') > -1) {
 | |
|           if (Foundation.rtl) nub.addClass('rtl');
 | |
|           objPos(tip, (target.offset().top - tip.outerHeight()), 'auto', 'auto', left)
 | |
|             .removeClass('tip-override');
 | |
|         } else if (classes && classes.indexOf('tip-left') > -1) {
 | |
|           objPos(tip, (target.offset().top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)), 'auto', 'auto', (target.offset().left - tip.outerWidth() - nubHeight))
 | |
|             .removeClass('tip-override');
 | |
|           nub.removeClass('rtl');
 | |
|         } else if (classes && classes.indexOf('tip-right') > -1) {
 | |
|           objPos(tip, (target.offset().top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)), 'auto', 'auto', (target.offset().left + target.outerWidth() + nubHeight))
 | |
|             .removeClass('tip-override');
 | |
|           nub.removeClass('rtl');
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       tip.css('visibility', 'visible').hide();
 | |
|     },
 | |
| 
 | |
|     small : function () {
 | |
|       return matchMedia(Foundation.media_queries.small).matches &&
 | |
|         !matchMedia(Foundation.media_queries.medium).matches;
 | |
|     },
 | |
| 
 | |
|     inheritable_classes : function ($target) {
 | |
|       var settings = $.extend({}, this.settings, this.data_options($target)),
 | |
|           inheritables = ['tip-top', 'tip-left', 'tip-bottom', 'tip-right', 'radius', 'round'].concat(settings.additional_inheritable_classes),
 | |
|           classes = $target.attr('class'),
 | |
|           filtered = classes ? $.map(classes.split(' '), function (el, i) {
 | |
|             if ($.inArray(el, inheritables) !== -1) {
 | |
|               return el;
 | |
|             }
 | |
|           }).join(' ') : '';
 | |
| 
 | |
|       return $.trim(filtered);
 | |
|     },
 | |
| 
 | |
|     convert_to_touch : function($target) {
 | |
|       var self = this,
 | |
|           $tip = self.getTip($target),
 | |
|           settings = $.extend({}, self.settings, self.data_options($target));
 | |
| 
 | |
|       if ($tip.find('.tap-to-close').length === 0) {
 | |
|         $tip.append('<span class="tap-to-close">'+settings.touch_close_text+'</span>');
 | |
|         $tip.on('click.fndtn.tooltip.tapclose touchstart.fndtn.tooltip.tapclose MSPointerDown.fndtn.tooltip.tapclose', function(e) {
 | |
|           self.hide($target);
 | |
|         });
 | |
|       }
 | |
| 
 | |
|       $target.data('tooltip-open-event-type', 'touch');
 | |
|     },
 | |
| 
 | |
|     show : function ($target) {
 | |
|       var $tip = this.getTip($target);
 | |
| 
 | |
|       if ($target.data('tooltip-open-event-type') == 'touch') {
 | |
|         this.convert_to_touch($target);
 | |
|       }
 | |
| 
 | |
|       this.reposition($target, $tip, $target.attr('class'));
 | |
|       $target.addClass('open');
 | |
|       $tip.fadeIn(150);
 | |
|     },
 | |
| 
 | |
|     hide : function ($target) {
 | |
|       var $tip = this.getTip($target);
 | |
| 
 | |
|       $tip.fadeOut(150, function() {
 | |
|         $tip.find('.tap-to-close').remove();
 | |
|         $tip.off('click.fndtn.tooltip.tapclose MSPointerDown.fndtn.tapclose');
 | |
|         $target.removeClass('open');
 | |
|       });
 | |
|     },
 | |
| 
 | |
|     off : function () {
 | |
|       var self = this;
 | |
|       this.S(this.scope).off('.fndtn.tooltip');
 | |
|       this.S(this.settings.tooltip_class).each(function (i) {
 | |
|         $('[' + self.attr_name() + ']').eq(i).attr('title', $(this).text());
 | |
|       }).remove();
 | |
|     },
 | |
| 
 | |
|     reflow : function () {}
 | |
|   };
 | |
| }(jQuery, window, window.document));
 |