(function($, undefined){ acf.newTooltip = function( props ){ // ensure object if( typeof props !== 'object' ) { props = { text: props }; } // confirmRemove if( props.confirmRemove !== undefined ) { props.textConfirm = acf.__('Remove'); props.textCancel = acf.__('Cancel'); return new TooltipConfirm( props ); // confirm } else if( props.confirm !== undefined ) { return new TooltipConfirm( props ); // default } else { return new Tooltip( props ); } }; var Tooltip = acf.Model.extend({ data: { text: '', timeout: 0, target: null }, tmpl: function(){ return '
'; }, setup: function( props ){ $.extend(this.data, props); this.$el = $(this.tmpl()); }, initialize: function(){ // render this.render(); // append this.show(); // position this.position(); // timeout var timeout = this.get('timeout'); if( timeout ) { setTimeout( $.proxy(this.fade, this), timeout ); } }, update: function( props ){ $.extend(this.data, props); this.initialize(); }, render: function(){ this.html( this.get('text') ); }, show: function(){ $('body').append( this.$el ); }, hide: function(){ this.$el.remove(); }, fade: function(){ // add class this.$el.addClass('acf-fade-up'); // remove this.setTimeout(function(){ this.remove(); }, 250); }, html: function( html ){ this.$el.html( html ); }, position: function(){ // vars var $tooltip = this.$el; var $target = this.get('target'); if( !$target ) return; // Reset position. $tooltip.removeClass('right left bottom top').css({ top: 0, left: 0 }); // Declare tollerance to edge of screen. var tolerance = 10; // Find target position. var targetWidth = $target.outerWidth(); var targetHeight = $target.outerHeight(); var targetTop = $target.offset().top; var targetLeft = $target.offset().left; // Find tooltip position. var tooltipWidth = $tooltip.outerWidth(); var tooltipHeight = $tooltip.outerHeight(); var tooltipTop = $tooltip.offset().top; // Should be 0, but WP media grid causes this to be 32 (toolbar padding). // Assume default top alignment. var top = targetTop - tooltipHeight - tooltipTop; var left = targetLeft + (targetWidth / 2) - (tooltipWidth / 2); // Check if too far left. if( left < tolerance ) { $tooltip.addClass('right'); left = targetLeft + targetWidth; top = targetTop + (targetHeight / 2) - (tooltipHeight / 2) - tooltipTop; // Check if too far right. } else if( (left + tooltipWidth + tolerance) > $(window).width() ) { $tooltip.addClass('left'); left = targetLeft - tooltipWidth; top = targetTop + (targetHeight / 2) - (tooltipHeight / 2) - tooltipTop; // Check if too far up. } else if( top - $(window).scrollTop() < tolerance ) { $tooltip.addClass('bottom'); top = targetTop + targetHeight - tooltipTop; // No colision with edges. } else { $tooltip.addClass('top'); } // update css $tooltip.css({ 'top': top, 'left': left }); } }); var TooltipConfirm = Tooltip.extend({ data: { text: '', textConfirm: '', textCancel: '', target: null, targetConfirm: true, confirm: function(){}, cancel: function(){}, context: false }, events: { 'click [data-event="cancel"]': 'onCancel', 'click [data-event="confirm"]': 'onConfirm', }, addEvents: function(){ // add events acf.Model.prototype.addEvents.apply(this); // vars var $document = $(document); var $target = this.get('target'); // add global 'cancel' click event // - use timeout to avoid the current 'click' event triggering the onCancel function this.setTimeout(function(){ this.on( $document, 'click', 'onCancel' ); }); // add target 'confirm' click event // - allow setting to control this feature if( this.get('targetConfirm') ) { this.on( $target, 'click', 'onConfirm' ); } }, removeEvents: function(){ // remove events acf.Model.prototype.removeEvents.apply(this); // vars var $document = $(document); var $target = this.get('target'); // remove custom events this.off( $document, 'click' ); this.off( $target, 'click' ); }, render: function(){ // defaults var text = this.get('text') || acf.__('Are you sure?'); var textConfirm = this.get('textConfirm') || acf.__('Yes'); var textCancel = this.get('textCancel') || acf.__('No'); // html var html = [ text, '' + textConfirm + '', '' + textCancel + '' ].join(' '); // html this.html( html ); // class this.$el.addClass('-confirm'); }, onCancel: function( e, $el ){ // prevent default e.preventDefault(); e.stopImmediatePropagation(); // callback var callback = this.get('cancel'); var context = this.get('context') || this; callback.apply( context, arguments ); //remove this.remove(); }, onConfirm: function( e, $el ){ // prevent default e.preventDefault(); e.stopImmediatePropagation(); // callback var callback = this.get('confirm'); var context = this.get('context') || this; callback.apply( context, arguments ); //remove this.remove(); } }); // storage acf.models.Tooltip = Tooltip; acf.models.TooltipConfirm = TooltipConfirm; /** * tooltipManager * * description * * @date 17/4/18 * @since 5.6.9 * * @param type $var Description. Default. * @return type Description. */ var tooltipHoverHelper = new acf.Model({ tooltip: false, events: { 'mouseenter .acf-js-tooltip': 'showTitle', 'mouseup .acf-js-tooltip': 'hideTitle', 'mouseleave .acf-js-tooltip': 'hideTitle' }, showTitle: function( e, $el ){ // vars var title = $el.attr('title'); // bail ealry if no title if( !title ) { return; } // clear title to avoid default browser tooltip $el.attr('title', ''); // create if( !this.tooltip ) { this.tooltip = acf.newTooltip({ text: title, target: $el }); // update } else { this.tooltip.update({ text: title, target: $el }); } }, hideTitle: function( e, $el ){ // hide tooltip this.tooltip.hide(); // restore title $el.attr('title', this.tooltip.get('text')); } }); })(jQuery);