├── .editorconfig ├── LICENSE ├── README.md ├── bower.json ├── jquery-accessible-dialog-tooltip-aria.js └── package.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [*.{js,scss,css,html,hbs,twig,json}] 14 | indent_style = space 15 | indent_size = 4 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Nicolas Hoffmann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jQuery Simple and Accessible Dialog Tooltip Window 2 | 3 | This jQuery plugin provides you a shiny and accessible dialog tooltip window, using ARIA. 4 | 5 | A presentation page and demo is here: https://a11y.nicolas-hoffmann.net/dialog-tooltip/ 6 | 7 | ## How it works 8 | 9 | Basically, the scripts wraps each class="js-tooltip" into a span class="your-prefix-class-container", when you activate one, it inserts a dialog element just after the clicked element (in the container), puts the focus into it and traps focus in the dialog tooltip. When you exit it, the focus is given back to the element that opened it. 10 | 11 | For mouse users, they can click outside the dialog tooltip to close it. 12 | 13 | If you never activate a dialog tooltip, it won’t be anywhere in the code. 14 | 15 | ## Options and attributes 16 | 17 | Simply put class="js-tooltip" on a button to activate the script. 18 | 19 | - Attribute data-tooltip-prefix-class: the prefix to all style classes of the dialog tooltip. 20 | - Attribute data-tooltip-text: the text of your dialog tooltip (will be put into a p tag). 21 | - Attribute data-tooltip-content-id: the id of (hidden) content in your page that will be put into your dialog tooltip. 22 | - Attribute data-tooltip-title: the main title of the dialog tooltip. 23 | - Attribute data-tooltip-close-text: the text of the close button in your dialog tooltip. 24 | - Attribute data-tooltip-close-title: the title attribute of the close button in your dialog tooltip. 25 | - Attribute data-tooltip-close-img: a path to a valid image for the close button. 26 | 27 | Another feature: when you click on a button that launches a modal tooltip, the class is-active is added to this button. 28 | 29 | Enjoy. 30 | 31 | Chuck Norris approved this 32 | 33 | P.S: this plugin is in [MIT license](https://github.com/nico3333fr/jquery-accessible-dialog-tooltip-aria/blob/master/LICENSE). It couldn't be done without the precious help of @ScreenFeedFr, @sophieschuermans, @johan_ramon, @goetsu and @romaingervois. 34 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-accessible-dialog-tooltip-aria", 3 | "description": "This jQuery plugin will add a shiny and accessible dialog tooltip window, using ARIA", 4 | "homepage": "https://a11y.nicolas-hoffmann.net/dialog-tooltip/", 5 | "main": "jquery-accessible-dialog-tooltip-aria.js", 6 | "version": "1.6.2", 7 | "keywords": [ 8 | "Accessibility", 9 | "ARIA", 10 | "dialog", 11 | "tooltip", 12 | "a11y", 13 | "jQuery Plugin" 14 | ], 15 | "authors": [ 16 | { 17 | "name": "Nicolas Hoffmann", 18 | "email": "dante3333@gmail.com", 19 | "web": "https://www.nicolas-hoffmann.net/" 20 | } 21 | ], 22 | "dependencies": { 23 | "jquery": ">=1.0.0" 24 | }, 25 | "repositories": [ 26 | { 27 | "type": "git", 28 | "url": "git://github.com/nico3333fr/jquery-accessible-dialog-tooltip-aria.git" 29 | } 30 | ], 31 | "license": "MIT", 32 | "ignore": [ 33 | "**/.*", 34 | "node_modules", 35 | "bower_components", 36 | "README.md" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /jquery-accessible-dialog-tooltip-aria.js: -------------------------------------------------------------------------------- 1 | jQuery(document).ready(function($) { 2 | 3 | /* 4 | * jQuery simple and accessible dialog tooltip window, using ARIA 5 | * @version v1.6.2 6 | * Website: https://a11y.nicolas-hoffmann.net/dialog-tooltip/ 7 | * License MIT: https://github.com/nico3333fr/jquery-accessible-dialog-tooltip-aria/blob/master/LICENSE 8 | */ 9 | // loading tooltip ------------------------------------------------------------------------------------------------------------ 10 | // init 11 | var $js_tooltips = $('.js-tooltip'), 12 | $body = $('body'); 13 | 14 | if ($js_tooltips.length) { // if there are at least one :) 15 | 16 | $js_tooltips.each(function(index_to_expand) { 17 | var $this = $(this), 18 | options = $this.data(), 19 | $tooltip_prefix_class = typeof options.tooltipPrefixClass !== 'undefined' ? options.tooltipPrefixClass + '-' : '', 20 | index_lisible = index_to_expand + 1; 21 | 22 | $this.attr({ 23 | 'id': 'label_tooltip_' + index_lisible 24 | }); 25 | // wraps element in a container 26 | $this.wrap(''); 27 | 28 | }); 29 | 30 | } 31 | 32 | // jQuery formatted selector to search for focusable items 33 | var focusableElementsString = "a[href], area[href], input:not([type='hidden']):not([disabled], select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]"; 34 | 35 | 36 | // events ------------------ 37 | $body.on('click', function(event) { 38 | var $target = $(event.target), 39 | $focus_back = $('#' + $('#js-tooltip-close').attr('data-focus-back')), 40 | $dialog_tooltip = $('.js-dialogtooltip'), 41 | id_back_content = $dialog_tooltip.attr('data-content-back-id'); 42 | 43 | // if click outside => close 44 | if ((!$target.is('.js-dialogtooltip') && !$target.is('.js-tooltip') && !$target.closest(".js-dialogtooltip").length) || ($target.is($focus_back))) { 45 | if ( id_back_content !== '' ){ 46 | var $content = $('#js-tooltip-content').html(), 47 | $content_back_place = $('#' + id_back_content); 48 | 49 | $content_back_place.html($content); 50 | } 51 | 52 | $dialog_tooltip.remove(); 53 | $focus_back.removeClass('is-active'); 54 | } 55 | }) 56 | .on('click', ".js-tooltip:not('.is-active')", function(event) { 57 | var $this = $(this), 58 | options = $this.data(), 59 | $tooltip_prefix_class = typeof options.tooltipPrefixClass !== 'undefined' ? options.tooltipPrefixClass + '-' : '', 60 | $tooltip_text = options.tooltipText || '', 61 | $tooltip_content_id = typeof options.tooltipContentId !== 'undefined' ? '#' + options.tooltipContentId : '', 62 | $tooltip_content_back_id = typeof options.tooltipContentId !== 'undefined' ? options.tooltipContentId : '', 63 | $tooltip_title = options.tooltipTitle || '', 64 | $tooltip_close_text = options.tooltipCloseText || 'Close', 65 | $tooltip_close_title = options.tooltipCloseTitle || options.tooltipCloseText, 66 | $tooltip_close_img = options.tooltipCloseImg || '', 67 | $tooltip_starter_id = $this.attr('id'), 68 | $tooltip_code; 69 | 70 | // close tooltip and remove active one 71 | var $old_tooltip = $('#js-tooltip'), 72 | id_back_content = $old_tooltip.attr('data-content-back-id'); 73 | 74 | if ( id_back_content !== '' ){ 75 | var $content = $('#js-tooltip-content').html(), 76 | $content_back_place = $('#' + id_back_content); 77 | 78 | $content_back_place.html($content); 79 | } 80 | $old_tooltip.remove(); 81 | $('.js-tooltip').removeClass('is-active'); 82 | 83 | // insert code at the end 84 | $tooltip_code = '
'; 85 | $tooltip_code += ''; 92 | 93 | if ($tooltip_title !== '') { 94 | $tooltip_code += '

' + $tooltip_title + '

'; 95 | } 96 | if ($tooltip_text !== '') { 97 | $tooltip_code += '

' + $tooltip_text + '

'; 98 | } else { 99 | if ($tooltip_content_id !== '' && $($tooltip_content_id).length) { 100 | $tooltip_code += '
'; 101 | $tooltip_code += $($tooltip_content_id).html(); 102 | $tooltip_code += '
'; 103 | $($tooltip_content_id).html(''); 104 | } 105 | } 106 | $tooltip_code += '
'; 107 | 108 | // Chrome bug 109 | setTimeout(function() { 110 | $($tooltip_code).insertAfter($this); 111 | }, 50); 112 | // fix for Chrome bug resolution… 113 | setTimeout(function() { 114 | $('#js-tooltip-close').focus(); 115 | }, 51); 116 | 117 | $('#' + $tooltip_starter_id).addClass('is-active'); 118 | 119 | event.preventDefault(); 120 | 121 | }) 122 | /* 123 | .on( 'mouseleave', '#js-tooltip', function( event ) { 124 | var $this = $(this), 125 | options = $this.data(), 126 | $tooltip_launched_by = options.launchedBy, 127 | $focus_back = $('#' + options.focusBack), 128 | $close_button = $this.find('.tooltip-close'); 129 | 130 | $close_button.click(); 131 | $focus_back.removeClass('is-active'); 132 | 133 | })*/ 134 | ; 135 | 136 | // close button and esc key 137 | $body.on('click', '#js-tooltip-close', function() { 138 | var $this = $(this), 139 | $focus_back = $('#' + $this.attr('data-focus-back')), 140 | id_back_content = $this.parents('#js-tooltip').attr('data-content-back-id'); 141 | 142 | if ( id_back_content !== '' ){ 143 | var $content = $('#js-tooltip-content').html(), 144 | $content_back_place = $('#' + id_back_content); 145 | 146 | $content_back_place.html($content); 147 | } 148 | $('#js-tooltip').remove(); 149 | $focus_back.focus(); 150 | $focus_back.removeClass('is-active'); 151 | 152 | }) 153 | .on("keydown", "#js-tooltip", function(event) { 154 | var $this = $(this); 155 | 156 | if (event.keyCode == 27) { // esc 157 | $('#js-tooltip-close').click(); 158 | event.preventDefault(); 159 | } 160 | if (event.keyCode == 9) { // tab or maj+tab 161 | 162 | // get list of all children elements in given object 163 | var children = $this.find('*'); 164 | 165 | // get list of focusable items 166 | var focusableItems = children.filter(focusableElementsString).filter(':visible'); 167 | 168 | // get currently focused item 169 | var focusedItem = $(document.activeElement); 170 | 171 | // get the number of focusable items 172 | var numberOfFocusableItems = focusableItems.length 173 | 174 | var focusedItemIndex = focusableItems.index(focusedItem); 175 | 176 | if (!event.shiftKey && (focusedItemIndex == numberOfFocusableItems - 1)) { 177 | focusableItems.get(0).focus(); 178 | event.preventDefault(); 179 | } 180 | if (event.shiftKey && focusedItemIndex == 0) { 181 | focusableItems.get(numberOfFocusableItems - 1).focus(); 182 | event.preventDefault(); 183 | } 184 | 185 | 186 | } 187 | 188 | }); 189 | 190 | 191 | 192 | }); 193 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "jQuery accessible dialog tooltip, using ARIA", 3 | "name": "jquery-accessible-dialog-tooltip-aria", 4 | "description": "This jQuery plugin will add a shiny and accessible dialog tooltip window, using ARIA", 5 | "version": "1.6.2", 6 | "main": "jquery-accessible-dialog-tooltip-aria.js", 7 | "keywords": [ 8 | "Accessibility", 9 | "ARIA", 10 | "dialog", 11 | "tooltip", 12 | "a11y", 13 | "jQuery Plugin" 14 | ], 15 | "author": [ 16 | { 17 | "name": "Nicolas Hoffmann", 18 | "email": "dante3333@gmail.com", 19 | "web": "https://www.nicolas-hoffmann.net/" 20 | } 21 | ], 22 | "dependencies": { 23 | "jquery": ">=1.0.0" 24 | }, 25 | "bugs": { 26 | "web": "https://github.com/nico3333fr/jquery-accessible-dialog-tooltip-aria/issues" 27 | }, 28 | "repositories": [ 29 | { 30 | "type": "git", 31 | "url": "https://github.com/nico3333fr/jquery-accessible-dialog-tooltip-aria.git" 32 | } 33 | ], 34 | "license": [ 35 | { 36 | "name": "MIT", 37 | "url": "https://github.com/nico3333fr/jquery-accessible-dialog-tooltip-aria/blob/master/LICENSE" 38 | } 39 | ], 40 | "homepage": "https://a11y.nicolas-hoffmann.net/dialog-tooltip/" 41 | } 42 | --------------------------------------------------------------------------------