/*!

* jQuery UI Tooltip 1.11.4
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
* http://api.jqueryui.com/tooltip/
*/

(function( factory ) {

if ( typeof define === "function" && define.amd ) {

        // AMD. Register as an anonymous module.
        define([
                "jquery",
                "./core",
                "./widget",
                "./position"
        ], factory );
} else {

        // Browser globals
        factory( jQuery );
}

}(function( $ ) {

return $.widget( “ui.tooltip”, {

version: "1.11.4",
options: {
        content: function() {
                // support: IE<9, Opera in jQuery <1.7
                // .text() can't accept undefined, so coerce to a string
                var title = $( this ).attr( "title" ) || "";
                // Escape title, since we're going from an attribute to raw HTML
                return $( "<a>" ).text( title ).html();
        },
        hide: true,
        // Disabled elements have inconsistent behavior across browsers (#8661)
        items: "[title]:not([disabled])",
        position: {
                my: "left top+15",
                at: "left bottom",
                collision: "flipfit flip"
        },
        show: true,
        tooltipClass: null,
        track: false,

        // callbacks
        close: null,
        open: null
},

_addDescribedBy: function( elem, id ) {
        var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
        describedby.push( id );
        elem
                .data( "ui-tooltip-id", id )
                .attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
},

_removeDescribedBy: function( elem ) {
        var id = elem.data( "ui-tooltip-id" ),
                describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
                index = $.inArray( id, describedby );

        if ( index !== -1 ) {
                describedby.splice( index, 1 );
        }

        elem.removeData( "ui-tooltip-id" );
        describedby = $.trim( describedby.join( " " ) );
        if ( describedby ) {
                elem.attr( "aria-describedby", describedby );
        } else {
                elem.removeAttr( "aria-describedby" );
        }
},

_create: function() {
        this._on({
                mouseover: "open",
                focusin: "open"
        });

        // IDs of generated tooltips, needed for destroy
        this.tooltips = {};

        // IDs of parent tooltips where we removed the title attribute
        this.parents = {};

        if ( this.options.disabled ) {
                this._disable();
        }

        // Append the aria-live region so tooltips announce correctly
        this.liveRegion = $( "<div>" )
                .attr({
                        role: "log",
                        "aria-live": "assertive",
                        "aria-relevant": "additions"
                })
                .addClass( "ui-helper-hidden-accessible" )
                .appendTo( this.document[ 0 ].body );
},

_setOption: function( key, value ) {
        var that = this;

        if ( key === "disabled" ) {
                this[ value ? "_disable" : "_enable" ]();
                this.options[ key ] = value;
                // disable element style changes
                return;
        }

        this._super( key, value );

        if ( key === "content" ) {
                $.each( this.tooltips, function( id, tooltipData ) {
                        that._updateContent( tooltipData.element );
                });
        }
},

_disable: function() {
        var that = this;

        // close open tooltips
        $.each( this.tooltips, function( id, tooltipData ) {
                var event = $.Event( "blur" );
                event.target = event.currentTarget = tooltipData.element[ 0 ];
                that.close( event, true );
        });

        // remove title attributes to prevent native tooltips
        this.element.find( this.options.items ).addBack().each(function() {
                var element = $( this );
                if ( element.is( "[title]" ) ) {
                        element
                                .data( "ui-tooltip-title", element.attr( "title" ) )
                                .removeAttr( "title" );
                }
        });
},

_enable: function() {
        // restore title attributes
        this.element.find( this.options.items ).addBack().each(function() {
                var element = $( this );
                if ( element.data( "ui-tooltip-title" ) ) {
                        element.attr( "title", element.data( "ui-tooltip-title" ) );
                }
        });
},

open: function( event ) {
        var that = this,
                target = $( event ? event.target : this.element )
                        // we need closest here due to mouseover bubbling,
                        // but always pointing at the same event target
                        .closest( this.options.items );

        // No element to show a tooltip for or the tooltip is already open
        if ( !target.length || target.data( "ui-tooltip-id" ) ) {
                return;
        }

        if ( target.attr( "title" ) ) {
                target.data( "ui-tooltip-title", target.attr( "title" ) );
        }

        target.data( "ui-tooltip-open", true );

        // kill parent tooltips, custom or native, for hover
        if ( event && event.type === "mouseover" ) {
                target.parents().each(function() {
                        var parent = $( this ),
                                blurEvent;
                        if ( parent.data( "ui-tooltip-open" ) ) {
                                blurEvent = $.Event( "blur" );
                                blurEvent.target = blurEvent.currentTarget = this;
                                that.close( blurEvent, true );
                        }
                        if ( parent.attr( "title" ) ) {
                                parent.uniqueId();
                                that.parents[ this.id ] = {
                                        element: this,
                                        title: parent.attr( "title" )
                                };
                                parent.attr( "title", "" );
                        }
                });
        }

        this._registerCloseHandlers( event, target );
        this._updateContent( target, event );
},

_updateContent: function( target, event ) {
        var content,
                contentOption = this.options.content,
                that = this,
                eventType = event ? event.type : null;

        if ( typeof contentOption === "string" ) {
                return this._open( event, target, contentOption );
        }

        content = contentOption.call( target[0], function( response ) {

                // IE may instantly serve a cached response for ajax requests
                // delay this call to _open so the other call to _open runs first
                that._delay(function() {

                        // Ignore async response if tooltip was closed already
                        if ( !target.data( "ui-tooltip-open" ) ) {
                                return;
                        }

                        // jQuery creates a special event for focusin when it doesn't
                        // exist natively. To improve performance, the native event
                        // object is reused and the type is changed. Therefore, we can't
                        // rely on the type being correct after the event finished
                        // bubbling, so we set it back to the previous value. (#8740)
                        if ( event ) {
                                event.type = eventType;
                        }
                        this._open( event, target, response );
                });
        });
        if ( content ) {
                this._open( event, target, content );
        }
},

_open: function( event, target, content ) {
        var tooltipData, tooltip, delayedShow, a11yContent,
                positionOption = $.extend( {}, this.options.position );

        if ( !content ) {
                return;
        }

        // Content can be updated multiple times. If the tooltip already
        // exists, then just update the content and bail.
        tooltipData = this._find( target );
        if ( tooltipData ) {
                tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
                return;
        }

        // if we have a title, clear it to prevent the native tooltip
        // we have to check first to avoid defining a title if none exists
        // (we don't want to cause an element to start matching [title])
        //
        // We use removeAttr only for key events, to allow IE to export the correct
        // accessible attributes. For mouse events, set to empty string to avoid
        // native tooltip showing up (happens only when removing inside mouseover).
        if ( target.is( "[title]" ) ) {
                if ( event && event.type === "mouseover" ) {
                        target.attr( "title", "" );
                } else {
                        target.removeAttr( "title" );
                }
        }

        tooltipData = this._tooltip( target );
        tooltip = tooltipData.tooltip;
        this._addDescribedBy( target, tooltip.attr( "id" ) );
        tooltip.find( ".ui-tooltip-content" ).html( content );

        // Support: Voiceover on OS X, JAWS on IE <= 9
        // JAWS announces deletions even when aria-relevant="additions"
        // Voiceover will sometimes re-read the entire log region's contents from the beginning
        this.liveRegion.children().hide();
        if ( content.clone ) {
                a11yContent = content.clone();
                a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
        } else {
                a11yContent = content;
        }
        $( "<div>" ).html( a11yContent ).appendTo( this.liveRegion );

        function position( event ) {
                positionOption.of = event;
                if ( tooltip.is( ":hidden" ) ) {
                        return;
                }
                tooltip.position( positionOption );
        }
        if ( this.options.track && event && /^mouse/.test( event.type ) ) {
                this._on( this.document, {
                        mousemove: position
                });
                // trigger once to override element-relative positioning
                position( event );
        } else {
                tooltip.position( $.extend({
                        of: target
                }, this.options.position ) );
        }

        tooltip.hide();

        this._show( tooltip, this.options.show );
        // Handle tracking tooltips that are shown with a delay (#8644). As soon
        // as the tooltip is visible, position the tooltip using the most recent
        // event.
        if ( this.options.show && this.options.show.delay ) {
                delayedShow = this.delayedShow = setInterval(function() {
                        if ( tooltip.is( ":visible" ) ) {
                                position( positionOption.of );
                                clearInterval( delayedShow );
                        }
                }, $.fx.interval );
        }

        this._trigger( "open", event, { tooltip: tooltip } );
},

_registerCloseHandlers: function( event, target ) {
        var events = {
                keyup: function( event ) {
                        if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
                                var fakeEvent = $.Event(event);
                                fakeEvent.currentTarget = target[0];
                                this.close( fakeEvent, true );
                        }
                }
        };

        // Only bind remove handler for delegated targets. Non-delegated
        // tooltips will handle this in destroy.
        if ( target[ 0 ] !== this.element[ 0 ] ) {
                events.remove = function() {
                        this._removeTooltip( this._find( target ).tooltip );
                };
        }

        if ( !event || event.type === "mouseover" ) {
                events.mouseleave = "close";
        }
        if ( !event || event.type === "focusin" ) {
                events.focusout = "close";
        }
        this._on( true, target, events );
},

close: function( event ) {
        var tooltip,
                that = this,
                target = $( event ? event.currentTarget : this.element ),
                tooltipData = this._find( target );

        // The tooltip may already be closed
        if ( !tooltipData ) {

                // We set ui-tooltip-open immediately upon open (in open()), but only set the
                // additional data once there's actually content to show (in _open()). So even if the
                // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
                // the period between open() and _open().
                target.removeData( "ui-tooltip-open" );
                return;
        }

        tooltip = tooltipData.tooltip;

        // disabling closes the tooltip, so we need to track when we're closing
        // to avoid an infinite loop in case the tooltip becomes disabled on close
        if ( tooltipData.closing ) {
                return;
        }

        // Clear the interval for delayed tracking tooltips
        clearInterval( this.delayedShow );

        // only set title if we had one before (see comment in _open())
        // If the title attribute has changed since open(), don't restore
        if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
                target.attr( "title", target.data( "ui-tooltip-title" ) );
        }

        this._removeDescribedBy( target );

        tooltipData.hiding = true;
        tooltip.stop( true );
        this._hide( tooltip, this.options.hide, function() {
                that._removeTooltip( $( this ) );
        });

        target.removeData( "ui-tooltip-open" );
        this._off( target, "mouseleave focusout keyup" );

        // Remove 'remove' binding only on delegated targets
        if ( target[ 0 ] !== this.element[ 0 ] ) {
                this._off( target, "remove" );
        }
        this._off( this.document, "mousemove" );

        if ( event && event.type === "mouseleave" ) {
                $.each( this.parents, function( id, parent ) {
                        $( parent.element ).attr( "title", parent.title );
                        delete that.parents[ id ];
                });
        }

        tooltipData.closing = true;
        this._trigger( "close", event, { tooltip: tooltip } );
        if ( !tooltipData.hiding ) {
                tooltipData.closing = false;
        }
},

_tooltip: function( element ) {
        var tooltip = $( "<div>" )
                        .attr( "role", "tooltip" )
                        .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
                                ( this.options.tooltipClass || "" ) ),
                id = tooltip.uniqueId().attr( "id" );

        $( "<div>" )
                .addClass( "ui-tooltip-content" )
                .appendTo( tooltip );

        tooltip.appendTo( this.document[0].body );

        return this.tooltips[ id ] = {
                element: element,
                tooltip: tooltip
        };
},

_find: function( target ) {
        var id = target.data( "ui-tooltip-id" );
        return id ? this.tooltips[ id ] : null;
},

_removeTooltip: function( tooltip ) {
        tooltip.remove();
        delete this.tooltips[ tooltip.attr( "id" ) ];
},

_destroy: function() {
        var that = this;

        // close open tooltips
        $.each( this.tooltips, function( id, tooltipData ) {
                // Delegate to close method to handle common cleanup
                var event = $.Event( "blur" ),
                        element = tooltipData.element;
                event.target = event.currentTarget = element[ 0 ];
                that.close( event, true );

                // Remove immediately; destroying an open tooltip doesn't use the
                // hide animation
                $( "#" + id ).remove();

                // Restore the title
                if ( element.data( "ui-tooltip-title" ) ) {
                        // If the title attribute has changed since open(), don't restore
                        if ( !element.attr( "title" ) ) {
                                element.attr( "title", element.data( "ui-tooltip-title" ) );
                        }
                        element.removeData( "ui-tooltip-title" );
                }
        });
        this.liveRegion.remove();
}

});

}));