jquery.tipsy: Improve accessibility slightly
authorDerk-Jan Hartman <hartman.wiki@gmail.com>
Sun, 18 May 2014 15:22:31 +0000 (17:22 +0200)
committerBartosz Dziewoński <matma.rex@gmail.com>
Wed, 13 May 2015 08:09:01 +0000 (08:09 +0000)
- use role tooltip
- use aria-hidden when element is hidden
- use focus and blur in case of trigger:hover as well

Bug: T65960
Change-Id: Ib7746458e11e068e43cdc3c168751e81f9d9876e

resources/src/jquery.tipsy/jquery.tipsy.js

index 2a37fa8..29b7490 100644 (file)
@@ -16,6 +16,7 @@
         this.$element = $(element);
         this.options = options;
         this.enabled = true;
+        this.keyHandler = $.proxy( this.closeOnEsc, this );
         this.fixTitle();
     }
 
                 if (this.options.className) {
                     $tip.addClass(maybeCall(this.options.className, this.$element[0]));
                 }
-                $tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body);
+                $tip.remove()
+                    .css({top: 0, left: 0, visibility: 'hidden', display: 'block'})
+                    .attr( 'aria-hidden', 'true' )
+                    .appendTo(document.body);
 
                 var pos = $.extend({}, this.$element.offset(), {
                     width: this.$element[0].offsetWidth,
                 }
                 $tip.css(tp);
 
+                $( document ).on( 'keydown', this.keyHandler );
                 if (this.options.fade) {
-                    $tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity}, 100);
+                    $tip.stop()
+                        .css({opacity: 0, display: 'block', visibility: 'visible'})
+                        .attr( 'aria-hidden', 'false' )
+                        .animate({opacity: this.options.opacity}, 100);
                 } else {
-                    $tip.css({visibility: 'visible', opacity: this.options.opacity});
+                    $tip
+                        .css({visibility: 'visible', opacity: this.options.opacity})
+                        .attr( 'aria-hidden', 'false' );
                 }
             }
         },
 
         hide: function() {
+            $( document ).off( 'keydown', this.keyHandler );
             if (this.options.fade) {
                 this.tip().stop().fadeOut(100, function() { $(this).remove(); });
             } else {
 
         tip: function() {
             if (!this.$tip) {
-                this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>');
+                this.$tip = $('<div class="tipsy" role="tooltip"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>');
             }
             return this.$tip;
         },
             }
         },
 
+        // $.proxy event handler
+        closeOnEsc: function ( e ) {
+            if ( e.keyCode === 27 ) {
+                this.hide();
+            }
+        },
+
         enable: function() { this.enabled = true; },
         disable: function() { this.enabled = false; },
         toggleEnabled: function() { this.enabled = !this.enabled; }
         if (!options.live) this.each(function() { get(this); });
 
         if ( options.trigger != 'manual' ) {
-            var eventIn  = options.trigger == 'hover' ? 'mouseenter' : 'focus',
-                eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
+            var eventIn  = options.trigger == 'hover' ? 'mouseenter focus' : 'focus',
+                eventOut = options.trigger == 'hover' ? 'mouseleave blur' : 'blur';
             if ( options.live ) {
                 mw.track( 'mw.deprecate', 'tipsy-live' );
                 mw.log.warn( 'Use of the "live" option of jquery.tipsy is deprecated.' );