$.fn.romoTooltip = function() { return $.map(this, function(element) { return new RomoTooltip(element); }); } var RomoTooltip = function(element) { this.elem = $(element); this.doInitPopup(); this.hoverState = 'out'; this.delayEnter = 0; this.delayLeave = 0; if (this.elem.data('romo-tooltip-delay') !== undefined && this.elem.data('romo-tooltip-delay') !== '') { this.delayEnter = this.elem.data('romo-tooltip-delay'); this.delayLeave = this.elem.data('romo-tooltip-delay'); } if (this.elem.data('romo-tooltip-delay-enter') !== undefined && this.elem.data('romo-tooltip-delay-enter') !== '') { this.delayEnter = this.elem.data('romo-tooltip-delay-enter'); } if (this.elem.data('romo-tooltip-delay-leave') !== undefined && this.elem.data('romo-tooltip-delay-leave') !== '') { this.delayLeave = this.elem.data('romo-tooltip-delay-leave'); } if (this.elem.data('romo-tooltip-style-class') !== undefined) { this.bodyElem.addClass(this.elem.data('romo-tooltip-style-class')); } this.elem.on('mouseenter', $.proxy(this.onToggleEnter, this)); this.elem.on('mouseleave', $.proxy(this.onToggleLeave, this)); this.elem.on('tooltip:triggerPopupOpen', $.proxy(this.onPopupOpen, this)); this.elem.on('tooltip:triggerPopupClose', $.proxy(this.onPopupClose, this)); this.elem.on('tooltip:triggerSetContent', $.proxy(this.onSetContent, this)); $(window).on('resize', $.proxy(this.onResizeWindow, this)) this.doInit(); this.doInitBody(); if (this.elem.data('romo-tooltip-content') === undefined) { this.doBindInvoke(); } this.elem.trigger('tooltip:ready', [this]); } RomoTooltip.prototype.doInit = function() { // override as needed } RomoTooltip.prototype.doInitPopup = function() { this.popupElem = $('
'); this.popupElem.appendTo(this.elem.closest(this.elem.data('romo-tooltip-append-to-closest') || 'body')); this.bodyElem = this.popupElem.find('> .romo-tooltip-body'); this.popupPosition = this.elem.data('romo-tooltip-position') || 'top'; this.popupElem.attr('data-romo-tooltip-position', this.popupPosition); this.popupAlignment = this.elem.data('romo-tooltip-alignment') || 'center'; this.popupElem.attr('data-romo-tooltip-alignment', this.popupAlignment); this.doSetPopupZIndex(this.elem); // don't propagate click events on the popup elem. this prevents the popup // from closing when clicked (see body click event bind on popup open) this.popupElem.on('click', function(e) { if (e !== undefined) { e.stopPropagation(); } }) // the popup should be treated like a child elem. add it to Romo's // parent-child elems so it will be removed when the elem is removed. // delay adding it b/c other components may `append` generated tooltips // meaning the tooltip is removed and then re-added. if added immediately // the "remove" part will incorrectly remove the popup. setTimeout($.proxy(function() { Romo.parentChildElems.add(this.elem, [this.popupElem]); }, this), 1); } RomoTooltip.prototype.doInitBody = function() { this.doResetBody(); this.bodyElem.css({ 'min-width': this.elem.data('romo-tooltip-min-width'), 'max-width': this.elem.data('romo-tooltip-max-width'), 'width': this.elem.data('romo-tooltip-width'), 'min-height': this.elem.data('romo-tooltip-min-height'), 'max-height': this.elem.data('romo-tooltip-max-height'), 'height': this.elem.data('romo-tooltip-height') }); } RomoTooltip.prototype.doResetBody = function() { this.bodyElem.css({ 'min-width': '', 'max-width': '', 'width': '', 'min-height': '', 'max-height': '', 'height': '', }); } RomoTooltip.prototype.doBindInvoke = function() { this.romoInvoke = this.elem.romoInvoke()[0]; this.romoInvoke.doUnBindInvoke(); // disable auto invoke on click this.elem.on('invoke:loadStart', $.proxy(function(e, invoke) { this.doLoadBodyStart(); }, this)); this.elem.on('invoke:loadSuccess', $.proxy(function(e, data, invoke) { this.doLoadBodySuccess(data); }, this)); this.elem.on('invoke:loadError', $.proxy(function(e, xhr, invoke) { this.doLoadBodyError(xhr); }, this)); } RomoTooltip.prototype.doLoadBodyStart = function() { this._setBodyHtml(''); this.doInitBody(); this.doPlacePopupElem(); this.elem.trigger('tooltip:loadBodyStart', [this]); } RomoTooltip.prototype.doLoadBodySuccess = function(data) { Romo.initHtml(this.bodyElem, data); this.doInitBody(); this.doPlacePopupElem(); this.elem.trigger('tooltip:loadBodySuccess', [data, this]); } RomoTooltip.prototype.doLoadBodyError = function(xhr) { this.elem.trigger('tooltip:loadBodyError', [xhr, this]); } RomoTooltip.prototype.onToggleEnter = function(e) { if (e !== undefined) { e.preventDefault(); } this.hoverState = 'in'; if (this.elem.hasClass('disabled') === false) { clearTimeout(this.timeout); this.timeout = setTimeout($.proxy(function() { if (this.hoverState ==='in') { this.doPopupOpen(); } }, this), this.delayEnter); } } RomoTooltip.prototype.onToggleLeave = function(e) { if (e !== undefined) { e.preventDefault(); } this.hoverState = 'out'; if (this.elem.hasClass('disabled') === false) { clearTimeout(this.timeout); this.timeout = setTimeout($.proxy(function() { if (this.hoverState === 'out') { this.doPopupClose(); } }, this), this.delayLeave); } } RomoTooltip.prototype.onResizeWindow = function(e) { if (this.elem.hasClass('disabled') === false && this.hoverState === 'in') { this.doPlacePopupElem(); } } RomoTooltip.prototype.onPopupOpen = function(e) { if (e !== undefined) { e.preventDefault(); } if (this.elem.hasClass('disabled') === false) { this.doPopupOpen(); } } RomoTooltip.prototype.doPopupOpen = function() { if (this.romoInvoke !== undefined) { this.romoInvoke.doInvoke(); } else { this._setBodyHtml(this.elem.data('romo-tooltip-content')); } this.popupElem.addClass('romo-tooltip-open'); this.doPlacePopupElem(); if (this.elem.parents('.romo-modal-popup').size() !== 0) { $('body').on('modal:mousemove', $.proxy(this.onModalPopupChange, this)); $('body').on('modal:popupclose', $.proxy(this.onModalPopupChange, this)); } $(window).on('resize', $.proxy(this.onResizeWindow, this)); this.elem.trigger('tooltip:popupOpen', [this]); } RomoTooltip.prototype.onPopupClose = function(e) { if (e !== undefined) { e.preventDefault(); } if (this.elem.hasClass('disabled') === false) { this.doPopupClose(); } } RomoTooltip.prototype.doPopupClose = function() { this.popupElem.removeClass('romo-tooltip-open'); if (this.elem.parents('.romo-modal-popup').size() !== 0) { $('body').off('modal:mousemove', $.proxy(this.onModalPopupChange, this)); $('body').off('modal:popupclose', $.proxy(this.onModalPopupChange, this)); } $(window).off('resize', $.proxy(this.onResizeWindow, this)); this.elem.trigger('tooltip:popupClose', [this]); } RomoTooltip.prototype.onModalPopupChange = function(e) { if (e !== undefined) { this.doPopupClose(); } return true; } RomoTooltip.prototype.onSetContent = function(e, value) { if (e !== undefined) { e.preventDefault(); } this.doSetContent(value); } RomoTooltip.prototype.doSetContent = function(value) { this.elem.data('romo-tooltip-content', value); this._setBodyHtml(this.elem.data('romo-tooltip-content')); this.doPlacePopupElem(); } RomoTooltip.prototype.onResizeWindow = function(e) { this.doPlacePopupElem(); return true; } RomoTooltip.prototype.doPlacePopupElem = function() { if (this.elem.parents('.romo-modal-popup').size() !== 0) { this.popupElem.css({'position': 'fixed'}); } var pos = $.extend({}, this.elem[0].getBoundingClientRect(), this.elem.offset()); var w = this.popupElem[0].offsetWidth; var h = this.popupElem[0].offsetHeight; var pad = 6 + 1; // arrow size + spacing var offset = {}; switch (this.popupPosition) { case 'top': $.extend(offset, { top: pos.top - h - pad, left: pos.left + pos.width / 2 - w / 2 }); break; case 'bottom': $.extend(offset, { top: pos.top + pos.height + pad, left: pos.left + pos.width / 2 - w / 2 }); break; case 'left': $.extend(offset, { top: pos.top + pos.height / 2 - h / 2, left: pos.left - w - pad }); break; case 'right': $.extend(offset, { top: pos.top + pos.height / 2 - h / 2, left: pos.left + pos.width + pad }); break; } this.popupElem.offset(offset); } RomoTooltip.prototype.doSetPopupZIndex = function(relativeElem) { var relativeZIndex = Romo.parseZIndex(relativeElem); this.popupElem.css({'z-index': relativeZIndex + 1100}); // see z-index.css } // private RomoTooltip.prototype._setBodyHtml = function(content) { this.bodyElem.html(content || ''); } Romo.onInitUI(function(e) { Romo.initUIElems(e, '[data-romo-tooltip-auto="true"]').romoTooltip(); });