corrade-http-templates – Blame information for rev 57

Subversion Repositories:
Rev:
Rev Author Line No. Line
57 office 1 /*!
2 * jQuery UI Tooltip 1.12.1
3 * http://jqueryui.com
4 *
5 * Copyright jQuery Foundation and other contributors
6 * Released under the MIT license.
7 * http://jquery.org/license
8 */
9  
10 //>>label: Tooltip
11 //>>group: Widgets
12 //>>description: Shows additional information for any element on hover or focus.
13 //>>docs: http://api.jqueryui.com/tooltip/
14 //>>demos: http://jqueryui.com/tooltip/
15 //>>css.structure: ../../themes/base/core.css
16 //>>css.structure: ../../themes/base/tooltip.css
17 //>>css.theme: ../../themes/base/theme.css
18  
19 ( function( factory ) {
20 if ( typeof define === "function" && define.amd ) {
21  
22 // AMD. Register as an anonymous module.
23 define( [
24 "jquery",
25 "../keycode",
26 "../position",
27 "../unique-id",
28 "../version",
29 "../widget"
30 ], factory );
31 } else {
32  
33 // Browser globals
34 factory( jQuery );
35 }
36 }( function( $ ) {
37  
38 $.widget( "ui.tooltip", {
39 version: "1.12.1",
40 options: {
41 classes: {
42 "ui-tooltip": "ui-corner-all ui-widget-shadow"
43 },
44 content: function() {
45  
46 // support: IE<9, Opera in jQuery <1.7
47 // .text() can't accept undefined, so coerce to a string
48 var title = $( this ).attr( "title" ) || "";
49  
50 // Escape title, since we're going from an attribute to raw HTML
51 return $( "<a>" ).text( title ).html();
52 },
53 hide: true,
54  
55 // Disabled elements have inconsistent behavior across browsers (#8661)
56 items: "[title]:not([disabled])",
57 position: {
58 my: "left top+15",
59 at: "left bottom",
60 collision: "flipfit flip"
61 },
62 show: true,
63 track: false,
64  
65 // Callbacks
66 close: null,
67 open: null
68 },
69  
70 _addDescribedBy: function( elem, id ) {
71 var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
72 describedby.push( id );
73 elem
74 .data( "ui-tooltip-id", id )
75 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
76 },
77  
78 _removeDescribedBy: function( elem ) {
79 var id = elem.data( "ui-tooltip-id" ),
80 describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
81 index = $.inArray( id, describedby );
82  
83 if ( index !== -1 ) {
84 describedby.splice( index, 1 );
85 }
86  
87 elem.removeData( "ui-tooltip-id" );
88 describedby = $.trim( describedby.join( " " ) );
89 if ( describedby ) {
90 elem.attr( "aria-describedby", describedby );
91 } else {
92 elem.removeAttr( "aria-describedby" );
93 }
94 },
95  
96 _create: function() {
97 this._on( {
98 mouseover: "open",
99 focusin: "open"
100 } );
101  
102 // IDs of generated tooltips, needed for destroy
103 this.tooltips = {};
104  
105 // IDs of parent tooltips where we removed the title attribute
106 this.parents = {};
107  
108 // Append the aria-live region so tooltips announce correctly
109 this.liveRegion = $( "<div>" )
110 .attr( {
111 role: "log",
112 "aria-live": "assertive",
113 "aria-relevant": "additions"
114 } )
115 .appendTo( this.document[ 0 ].body );
116 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
117  
118 this.disabledTitles = $( [] );
119 },
120  
121 _setOption: function( key, value ) {
122 var that = this;
123  
124 this._super( key, value );
125  
126 if ( key === "content" ) {
127 $.each( this.tooltips, function( id, tooltipData ) {
128 that._updateContent( tooltipData.element );
129 } );
130 }
131 },
132  
133 _setOptionDisabled: function( value ) {
134 this[ value ? "_disable" : "_enable" ]();
135 },
136  
137 _disable: function() {
138 var that = this;
139  
140 // Close open tooltips
141 $.each( this.tooltips, function( id, tooltipData ) {
142 var event = $.Event( "blur" );
143 event.target = event.currentTarget = tooltipData.element[ 0 ];
144 that.close( event, true );
145 } );
146  
147 // Remove title attributes to prevent native tooltips
148 this.disabledTitles = this.disabledTitles.add(
149 this.element.find( this.options.items ).addBack()
150 .filter( function() {
151 var element = $( this );
152 if ( element.is( "[title]" ) ) {
153 return element
154 .data( "ui-tooltip-title", element.attr( "title" ) )
155 .removeAttr( "title" );
156 }
157 } )
158 );
159 },
160  
161 _enable: function() {
162  
163 // restore title attributes
164 this.disabledTitles.each( function() {
165 var element = $( this );
166 if ( element.data( "ui-tooltip-title" ) ) {
167 element.attr( "title", element.data( "ui-tooltip-title" ) );
168 }
169 } );
170 this.disabledTitles = $( [] );
171 },
172  
173 open: function( event ) {
174 var that = this,
175 target = $( event ? event.target : this.element )
176  
177 // we need closest here due to mouseover bubbling,
178 // but always pointing at the same event target
179 .closest( this.options.items );
180  
181 // No element to show a tooltip for or the tooltip is already open
182 if ( !target.length || target.data( "ui-tooltip-id" ) ) {
183 return;
184 }
185  
186 if ( target.attr( "title" ) ) {
187 target.data( "ui-tooltip-title", target.attr( "title" ) );
188 }
189  
190 target.data( "ui-tooltip-open", true );
191  
192 // Kill parent tooltips, custom or native, for hover
193 if ( event && event.type === "mouseover" ) {
194 target.parents().each( function() {
195 var parent = $( this ),
196 blurEvent;
197 if ( parent.data( "ui-tooltip-open" ) ) {
198 blurEvent = $.Event( "blur" );
199 blurEvent.target = blurEvent.currentTarget = this;
200 that.close( blurEvent, true );
201 }
202 if ( parent.attr( "title" ) ) {
203 parent.uniqueId();
204 that.parents[ this.id ] = {
205 element: this,
206 title: parent.attr( "title" )
207 };
208 parent.attr( "title", "" );
209 }
210 } );
211 }
212  
213 this._registerCloseHandlers( event, target );
214 this._updateContent( target, event );
215 },
216  
217 _updateContent: function( target, event ) {
218 var content,
219 contentOption = this.options.content,
220 that = this,
221 eventType = event ? event.type : null;
222  
223 if ( typeof contentOption === "string" || contentOption.nodeType ||
224 contentOption.jquery ) {
225 return this._open( event, target, contentOption );
226 }
227  
228 content = contentOption.call( target[ 0 ], function( response ) {
229  
230 // IE may instantly serve a cached response for ajax requests
231 // delay this call to _open so the other call to _open runs first
232 that._delay( function() {
233  
234 // Ignore async response if tooltip was closed already
235 if ( !target.data( "ui-tooltip-open" ) ) {
236 return;
237 }
238  
239 // JQuery creates a special event for focusin when it doesn't
240 // exist natively. To improve performance, the native event
241 // object is reused and the type is changed. Therefore, we can't
242 // rely on the type being correct after the event finished
243 // bubbling, so we set it back to the previous value. (#8740)
244 if ( event ) {
245 event.type = eventType;
246 }
247 this._open( event, target, response );
248 } );
249 } );
250 if ( content ) {
251 this._open( event, target, content );
252 }
253 },
254  
255 _open: function( event, target, content ) {
256 var tooltipData, tooltip, delayedShow, a11yContent,
257 positionOption = $.extend( {}, this.options.position );
258  
259 if ( !content ) {
260 return;
261 }
262  
263 // Content can be updated multiple times. If the tooltip already
264 // exists, then just update the content and bail.
265 tooltipData = this._find( target );
266 if ( tooltipData ) {
267 tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
268 return;
269 }
270  
271 // If we have a title, clear it to prevent the native tooltip
272 // we have to check first to avoid defining a title if none exists
273 // (we don't want to cause an element to start matching [title])
274 //
275 // We use removeAttr only for key events, to allow IE to export the correct
276 // accessible attributes. For mouse events, set to empty string to avoid
277 // native tooltip showing up (happens only when removing inside mouseover).
278 if ( target.is( "[title]" ) ) {
279 if ( event && event.type === "mouseover" ) {
280 target.attr( "title", "" );
281 } else {
282 target.removeAttr( "title" );
283 }
284 }
285  
286 tooltipData = this._tooltip( target );
287 tooltip = tooltipData.tooltip;
288 this._addDescribedBy( target, tooltip.attr( "id" ) );
289 tooltip.find( ".ui-tooltip-content" ).html( content );
290  
291 // Support: Voiceover on OS X, JAWS on IE <= 9
292 // JAWS announces deletions even when aria-relevant="additions"
293 // Voiceover will sometimes re-read the entire log region's contents from the beginning
294 this.liveRegion.children().hide();
295 a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
296 a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
297 a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
298 a11yContent.appendTo( this.liveRegion );
299  
300 function position( event ) {
301 positionOption.of = event;
302 if ( tooltip.is( ":hidden" ) ) {
303 return;
304 }
305 tooltip.position( positionOption );
306 }
307 if ( this.options.track && event && /^mouse/.test( event.type ) ) {
308 this._on( this.document, {
309 mousemove: position
310 } );
311  
312 // trigger once to override element-relative positioning
313 position( event );
314 } else {
315 tooltip.position( $.extend( {
316 of: target
317 }, this.options.position ) );
318 }
319  
320 tooltip.hide();
321  
322 this._show( tooltip, this.options.show );
323  
324 // Handle tracking tooltips that are shown with a delay (#8644). As soon
325 // as the tooltip is visible, position the tooltip using the most recent
326 // event.
327 // Adds the check to add the timers only when both delay and track options are set (#14682)
328 if ( this.options.track && this.options.show && this.options.show.delay ) {
329 delayedShow = this.delayedShow = setInterval( function() {
330 if ( tooltip.is( ":visible" ) ) {
331 position( positionOption.of );
332 clearInterval( delayedShow );
333 }
334 }, $.fx.interval );
335 }
336  
337 this._trigger( "open", event, { tooltip: tooltip } );
338 },
339  
340 _registerCloseHandlers: function( event, target ) {
341 var events = {
342 keyup: function( event ) {
343 if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
344 var fakeEvent = $.Event( event );
345 fakeEvent.currentTarget = target[ 0 ];
346 this.close( fakeEvent, true );
347 }
348 }
349 };
350  
351 // Only bind remove handler for delegated targets. Non-delegated
352 // tooltips will handle this in destroy.
353 if ( target[ 0 ] !== this.element[ 0 ] ) {
354 events.remove = function() {
355 this._removeTooltip( this._find( target ).tooltip );
356 };
357 }
358  
359 if ( !event || event.type === "mouseover" ) {
360 events.mouseleave = "close";
361 }
362 if ( !event || event.type === "focusin" ) {
363 events.focusout = "close";
364 }
365 this._on( true, target, events );
366 },
367  
368 close: function( event ) {
369 var tooltip,
370 that = this,
371 target = $( event ? event.currentTarget : this.element ),
372 tooltipData = this._find( target );
373  
374 // The tooltip may already be closed
375 if ( !tooltipData ) {
376  
377 // We set ui-tooltip-open immediately upon open (in open()), but only set the
378 // additional data once there's actually content to show (in _open()). So even if the
379 // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
380 // the period between open() and _open().
381 target.removeData( "ui-tooltip-open" );
382 return;
383 }
384  
385 tooltip = tooltipData.tooltip;
386  
387 // Disabling closes the tooltip, so we need to track when we're closing
388 // to avoid an infinite loop in case the tooltip becomes disabled on close
389 if ( tooltipData.closing ) {
390 return;
391 }
392  
393 // Clear the interval for delayed tracking tooltips
394 clearInterval( this.delayedShow );
395  
396 // Only set title if we had one before (see comment in _open())
397 // If the title attribute has changed since open(), don't restore
398 if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
399 target.attr( "title", target.data( "ui-tooltip-title" ) );
400 }
401  
402 this._removeDescribedBy( target );
403  
404 tooltipData.hiding = true;
405 tooltip.stop( true );
406 this._hide( tooltip, this.options.hide, function() {
407 that._removeTooltip( $( this ) );
408 } );
409  
410 target.removeData( "ui-tooltip-open" );
411 this._off( target, "mouseleave focusout keyup" );
412  
413 // Remove 'remove' binding only on delegated targets
414 if ( target[ 0 ] !== this.element[ 0 ] ) {
415 this._off( target, "remove" );
416 }
417 this._off( this.document, "mousemove" );
418  
419 if ( event && event.type === "mouseleave" ) {
420 $.each( this.parents, function( id, parent ) {
421 $( parent.element ).attr( "title", parent.title );
422 delete that.parents[ id ];
423 } );
424 }
425  
426 tooltipData.closing = true;
427 this._trigger( "close", event, { tooltip: tooltip } );
428 if ( !tooltipData.hiding ) {
429 tooltipData.closing = false;
430 }
431 },
432  
433 _tooltip: function( element ) {
434 var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
435 content = $( "<div>" ).appendTo( tooltip ),
436 id = tooltip.uniqueId().attr( "id" );
437  
438 this._addClass( content, "ui-tooltip-content" );
439 this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
440  
441 tooltip.appendTo( this._appendTo( element ) );
442  
443 return this.tooltips[ id ] = {
444 element: element,
445 tooltip: tooltip
446 };
447 },
448  
449 _find: function( target ) {
450 var id = target.data( "ui-tooltip-id" );
451 return id ? this.tooltips[ id ] : null;
452 },
453  
454 _removeTooltip: function( tooltip ) {
455 tooltip.remove();
456 delete this.tooltips[ tooltip.attr( "id" ) ];
457 },
458  
459 _appendTo: function( target ) {
460 var element = target.closest( ".ui-front, dialog" );
461  
462 if ( !element.length ) {
463 element = this.document[ 0 ].body;
464 }
465  
466 return element;
467 },
468  
469 _destroy: function() {
470 var that = this;
471  
472 // Close open tooltips
473 $.each( this.tooltips, function( id, tooltipData ) {
474  
475 // Delegate to close method to handle common cleanup
476 var event = $.Event( "blur" ),
477 element = tooltipData.element;
478 event.target = event.currentTarget = element[ 0 ];
479 that.close( event, true );
480  
481 // Remove immediately; destroying an open tooltip doesn't use the
482 // hide animation
483 $( "#" + id ).remove();
484  
485 // Restore the title
486 if ( element.data( "ui-tooltip-title" ) ) {
487  
488 // If the title attribute has changed since open(), don't restore
489 if ( !element.attr( "title" ) ) {
490 element.attr( "title", element.data( "ui-tooltip-title" ) );
491 }
492 element.removeData( "ui-tooltip-title" );
493 }
494 } );
495 this.liveRegion.remove();
496 }
497 } );
498  
499 // DEPRECATED
500 // TODO: Switch return back to widget declaration at top of file when this is removed
501 if ( $.uiBackCompat !== false ) {
502  
503 // Backcompat for tooltipClass option
504 $.widget( "ui.tooltip", $.ui.tooltip, {
505 options: {
506 tooltipClass: null
507 },
508 _tooltip: function() {
509 var tooltipData = this._superApply( arguments );
510 if ( this.options.tooltipClass ) {
511 tooltipData.tooltip.addClass( this.options.tooltipClass );
512 }
513 return tooltipData;
514 }
515 } );
516 }
517  
518 return $.ui.tooltip;
519  
520 } ) );