diff --git a/build/tota11y.js b/build/tota11y.js index 7335c653..994fd0e8 100644 --- a/build/tota11y.js +++ b/build/tota11y.js @@ -1,5 +1,5 @@ /*! - * tota11y v0.1.0 + * tota11y v0.1.1 * http://khan.github.io/tota11y * * Includes Accessibility Developer Tools @@ -9,7 +9,7 @@ * Released under the MIT license * http://github.com/Khan/tota11y/blob/master/LICENSE.txt * - * Date: 2015-09-17 + * Date: 2015-09-27 * */ /******/ (function(modules) { // webpackBootstrap @@ -79,10 +79,10 @@ var $ = __webpack_require__(/*! jquery */ 4); var plugins = __webpack_require__(/*! ./plugins */ 9); - var logoTemplate = __webpack_require__(/*! ./templates/logo.handlebars */ 48); + var logoTemplate = __webpack_require__(/*! ./templates/logo.handlebars */ 47); // Chrome Accessibility Developer Tools - required once as a global - __webpack_require__(/*! script!./~/accessibility-developer-tools/dist/js/axs_testing.js */ 49); + __webpack_require__(/*! script!./~/accessibility-developer-tools/dist/js/axs_testing.js */ 48); var Toolbar = (function () { function Toolbar() { @@ -160,23 +160,27 @@ e.preventDefault(); e.stopPropagation(); $toolbar.toggleClass("tota11y-expanded"); + $toolbar.attr("aria-expanded", $toolbar.is(".tota11y-expanded")); }; var $toggle = E( - "a", - { href: "#", + "button", + { "aria-controls": "tota11y-toolbar", className: "tota11y-toolbar-toggle", - onClick: handleToggleClick }, + onClick: handleToggleClick, + "aria-label": "[tota11y] Toggle menu" }, E( "div", - { className: "tota11y-toolbar-logo" }, + { "aria-hidden": "true", className: "tota11y-toolbar-logo" }, $logo ) ); $toolbar = E( "div", - { className: "tota11y tota11y-toolbar" }, + { id: "tota11y-toolbar", className: "tota11y tota11y-toolbar", + role: "region", + "aria-expanded": "false" }, E( "div", { className: "tota11y-toolbar-body" }, @@ -252,10 +256,18 @@ if (propName === "onClick") { var handler = props[propName]; $el.click(handler); - } else { - var value = props[propName]; - $el.prop(propName, value); - } + + // Some passed-in props need to be set with $.attr + // Currently we do this for role and aria-* + } else if (/^aria-/.test(propName) || propName === "role") { + var value = props[propName]; + $el.attr(propName, value); + + // All other props can go right to $.prop + } else { + var value = props[propName]; + $el.prop(propName, value); + } } } @@ -9534,7 +9546,7 @@ /***/ function(module, exports, __webpack_require__) { exports = module.exports = __webpack_require__(/*! ./../~/css-loader/lib/css-base.js */ 7)(); - exports.push([module.id, ".tota11y-dark-color-scheme {\n background-color: #333333 !important;\n color: #f2f2f2 !important;\n}\n.tota11y-no-select {\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n user-select: none !important;\n}\n/**\n * Base styles for tota11y to make sure things look consistent under\n * reasonable circumstances.\n */\n.tota11y,\n.tota11y * {\n border: none !important;\n box-sizing: border-box !important;\n color: #f2f2f2 !important;\n font-family: Arial !important;\n font-size: 14px !important;\n font-style: normal !important;\n font-weight: 400 !important;\n line-height: 1.35 !important;\n margin: 0 !important;\n padding: 0 !important;\n text-align: left !important;\n text-shadow: none !important;\n}\n.tota11y * {\n height: auto !important;\n width: auto !important;\n}\n.tota11y strong {\n font-weight: bold !important;\n}\n.tota11y pre,\n.tota11y code {\n background-color: #dddddd !important;\n border: none !important;\n border-radius: 0 !important;\n color: inherit !important;\n font-family: monospace !important;\n font-size: inherit !important;\n line-height: inherit !important;\n}\n.tota11y pre {\n padding: 5px 10px !important;\n margin: 0 0 10px !important;\n overflow-x: scroll !important;\n}\n.tota11y code {\n border-radius: 2px !important;\n display: inline !important;\n padding: 1px !important;\n}\n.tota11y i,\n.tota11y em {\n font-style: italic !important;\n}\n.tota11y p {\n margin: 0 0 10px !important;\n}\n.tota11y a,\n.tota11y a:hover,\n.tota11y a:focus {\n background-color: inherit !important;\n color: inherit !important;\n text-decoration: none !important;\n}\n.tota11y-toolbar {\n background-color: #333333 !important;\n color: #f2f2f2 !important;\n position: fixed !important;\n top: auto !important;\n right: auto !important;\n bottom: 0 !important;\n left: 10px !important;\n border-top-left-radius: 5px !important;\n border-top-right-radius: 5px !important;\n overflow: hidden !important;\n z-index: 9998 !important;\n}\n.tota11y-toolbar-toggle {\n display: block !important;\n padding: 7px !important;\n}\n.tota11y-toolbar-logo {\n height: 25px !important;\n margin: 0 auto !important;\n text-align: center !important;\n width: 35px !important;\n}\n.tota11y-toolbar-logo svg {\n height: 25px !important;\n}\n.tota11y-toolbar-body {\n display: none !important;\n}\n.tota11y-toolbar.tota11y-expanded .tota11y-toolbar-body {\n display: block !important;\n}\n.tota11y-plugins-separator {\n font-size: 12px !important;\n margin: 7px 15px 0 !important;\n text-transform: uppercase !important;\n}\n.tota11y-plugin {\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n user-select: none !important;\n border-bottom: 1px solid #555555 !important;\n}\n.tota11y-plugin-label {\n -webkit-box-align: center !important;\n -webkit-align-items: center !important;\n -ms-flex-align: center !important;\n align-items: center !important;\n display: -webkit-box !important;\n display: -webkit-flex !important;\n display: -ms-flexbox !important;\n display: flex !important;\n padding: 12px 12px 12px 0 !important;\n margin: 0 !important;\n}\n.tota11y-plugin-label:hover {\n cursor: pointer !important;\n}\n.tota11y-plugin-control {\n margin: 0 15px !important;\n}\n.tota11y-plugin-checkbox {\n display: none !important;\n}\n.tota11y-plugin-indicator {\n border-radius: 16px !important;\n border: 1px solid #999999 !important;\n color: transparent !important;\n font-size: 13px !important;\n height: 16px !important;\n line-height: 16px !important;\n padding: 0 0 0 1px !important;\n width: 16px !important;\n}\n.tota11y-plugin-checkbox:checked + .tota11y-plugin-indicator {\n background-color: #639b24 !important;\n border-color: #639b24 !important;\n color: white !important;\n}\n.tota11y-plugin-title {\n font-weight: bold !important;\n}\n.tota11y-plugin-description {\n font-size: 11px !important;\n font-style: italic !important;\n width: 200px !important;\n margin-right: 3px !important;\n}\n", ""]); + exports.push([module.id, ".tota11y-dark-color-scheme {\n background-color: #333333 !important;\n color: #f2f2f2 !important;\n}\n.tota11y-no-select {\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n user-select: none !important;\n}\n/**\n * Base styles for tota11y to make sure things look consistent under\n * reasonable circumstances.\n */\n.tota11y,\n.tota11y * {\n border: none !important;\n box-sizing: border-box !important;\n color: #f2f2f2 !important;\n font-family: Arial !important;\n font-size: 14px !important;\n font-style: normal !important;\n font-weight: 400 !important;\n line-height: 1.35 !important;\n margin: 0 !important;\n padding: 0 !important;\n text-align: left !important;\n text-shadow: none !important;\n}\n.tota11y * {\n height: auto !important;\n width: auto !important;\n}\n.tota11y strong {\n font-weight: bold !important;\n}\n.tota11y pre,\n.tota11y code {\n background-color: #dddddd !important;\n border: none !important;\n border-radius: 0 !important;\n color: inherit !important;\n font-family: monospace !important;\n font-size: inherit !important;\n line-height: inherit !important;\n}\n.tota11y pre {\n padding: 5px 10px !important;\n margin: 0 0 10px !important;\n overflow-x: scroll !important;\n}\n.tota11y code {\n border-radius: 2px !important;\n display: inline !important;\n padding: 1px !important;\n}\n.tota11y i,\n.tota11y em {\n font-style: italic !important;\n}\n.tota11y p {\n margin: 0 0 10px !important;\n}\n.tota11y a,\n.tota11y a:hover,\n.tota11y a:focus {\n background-color: inherit !important;\n color: inherit !important;\n text-decoration: none !important;\n}\n.tota11y-toolbar {\n background-color: #333333 !important;\n color: #f2f2f2 !important;\n position: fixed !important;\n top: auto !important;\n right: auto !important;\n bottom: 0 !important;\n left: 10px !important;\n border-top-left-radius: 5px !important;\n border-top-right-radius: 5px !important;\n overflow: hidden !important;\n z-index: 9998 !important;\n}\n.tota11y-toolbar-toggle {\n background-color: #333333 !important;\n display: block !important;\n padding: 7px !important;\n width: 100% !important;\n}\n.tota11y-toolbar-logo {\n height: 25px !important;\n margin: 0 auto !important;\n text-align: center !important;\n width: 35px !important;\n}\n.tota11y-toolbar-logo svg {\n height: 25px !important;\n}\n.tota11y-toolbar-body {\n display: none !important;\n}\n.tota11y-toolbar.tota11y-expanded .tota11y-toolbar-body {\n display: block !important;\n}\n.tota11y-sr-only {\n border: 0 !important;\n clip: rect(0, 0, 0, 0) !important;\n height: 1px !important;\n margin: -1px !important;\n overflow: hidden !important;\n padding: 0 !important;\n position: absolute !important;\n width: 1px !important;\n}\n", ""]); /***/ }, /* 7 */ @@ -9839,12 +9851,12 @@ "use strict"; var AltTextPlugin = __webpack_require__(/*! ./alt-text */ 10); - var ContrastPlugin = __webpack_require__(/*! ./contrast */ 32); - var HeadingsPlugin = __webpack_require__(/*! ./headings */ 37); - var LabelsPlugin = __webpack_require__(/*! ./labels */ 41); - var LandmarksPlugin = __webpack_require__(/*! ./landmarks */ 43); - var LinkTextPlugin = __webpack_require__(/*! ./link-text */ 44); - var A11yTextWand = __webpack_require__(/*! ./a11y-text-wand */ 45); + var ContrastPlugin = __webpack_require__(/*! ./contrast */ 31); + var HeadingsPlugin = __webpack_require__(/*! ./headings */ 36); + var LabelsPlugin = __webpack_require__(/*! ./labels */ 40); + var LandmarksPlugin = __webpack_require__(/*! ./landmarks */ 42); + var LinkTextPlugin = __webpack_require__(/*! ./link-text */ 43); + var A11yTextWand = __webpack_require__(/*! ./a11y-text-wand */ 44); module.exports = { "default": [new HeadingsPlugin(), new ContrastPlugin(), new LinkTextPlugin(), new LabelsPlugin(), new AltTextPlugin(), new LandmarksPlugin()], @@ -9876,7 +9888,7 @@ var $ = __webpack_require__(/*! jquery */ 4); var Plugin = __webpack_require__(/*! ../base */ 11); var annotate = __webpack_require__(/*! ../shared/annotate */ 13)("alt-text"); - var audit = __webpack_require__(/*! ../shared/audit */ 31); + var audit = __webpack_require__(/*! ../shared/audit */ 30); var AltTextPlugin = (function (_Plugin) { _inherits(AltTextPlugin, _Plugin); @@ -9985,7 +9997,7 @@ \*************************/ /***/ function(module, exports, __webpack_require__) { - /** + /* WEBPACK VAR INJECTION */(function(E) {/** * Base class for plugins. * * This module defines methods to render and mount plugins to the toolbar. @@ -10002,15 +10014,15 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - var $ = __webpack_require__(/*! jquery */ 4); var InfoPanel = __webpack_require__(/*! ./shared/info-panel */ 12); - var template = __webpack_require__(/*! ../templates/plugin.handlebars */ 30); + + __webpack_require__(/*! ./style.less */ 28); var Plugin = (function () { function Plugin() { _classCallCheck(this, Plugin); - this.panel = new InfoPanel(this.getTitle()); + this.panel = new InfoPanel(this); this.$checkbox = null; } @@ -10059,20 +10071,46 @@ value: function render(clickHandler) { var _this = this; - var templateData = { - title: this.getTitle(), - description: this.getDescription() - }; - - var $plugin = $(template(templateData)); + this.$checkbox = E("input", { + className: "tota11y-plugin-checkbox tota11y-sr-only", + type: "checkbox", + onClick: function () { + return clickHandler(_this); + } }); + + var $switch = E( + "label", + { className: "tota11y-plugin-switch" }, + this.$checkbox, + E( + "div", + { "aria-hidden": "true", + className: "tota11y-plugin-indicator" }, + "✓" + ), + E( + "div", + { className: "tota11y-plugin-info" }, + E( + "div", + { className: "tota11y-plugin-title" }, + this.getTitle() + ), + E( + "div", + { className: "tota11y-plugin-description" }, + this.getDescription() + ) + ) + ); - this.$checkbox = $plugin.find(".tota11y-plugin-checkbox"); - this.$checkbox.click(function (e) { - e.stopPropagation(); - clickHandler(_this); - }); + var $el = E( + "li", + { role: "menu-item", className: "tota11y-plugin" }, + $switch + ); - return $plugin; + return $el; } /** @@ -10094,10 +10132,7 @@ this.cleanup(); this.panel.destroy(); - // If we toggle the plugin ourselves, the checkbox will already be - // unchecked. If another plugin becomes active, however, this method - // will be called and will uncheck the checkbox. - this.$checkbox.attr("checked", false); + this.$checkbox.prop("checked", false); } }]); @@ -10105,6 +10140,7 @@ })(); module.exports = Plugin; + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ./element */ 3))) /***/ }, /* 12 */ @@ -10113,7 +10149,7 @@ \********************************************/ /***/ function(module, exports, __webpack_require__) { - /** + /* WEBPACK VAR INJECTION */(function(E) {/** * The following code defines an information panel that can be invoked from * any plugin to display summaries, errors, or more information about what * the plugin is doing. @@ -10138,20 +10174,19 @@ var $ = __webpack_require__(/*! jquery */ 4); var annotate = __webpack_require__(/*! ../annotate */ 13)("info-panel"); - var template = __webpack_require__(/*! ./template.handlebars */ 25); - var errorTemplate = __webpack_require__(/*! ./error.handlebars */ 26); - var tabTemplate = __webpack_require__(/*! ./tab.handlebars */ 27); - __webpack_require__(/*! ./style.less */ 28); + var errorTemplate = __webpack_require__(/*! ./error.handlebars */ 25); + __webpack_require__(/*! ./style.less */ 26); var INITIAL_PANEL_MARGIN_PX = 10; var COLLAPSED_CLASS_NAME = "tota11y-collapsed"; var HIDDEN_CLASS_NAME = "tota11y-info-hidden"; var InfoPanel = (function () { - function InfoPanel(title) { + function InfoPanel(plugin) { _classCallCheck(this, InfoPanel); - this.title = title; + this.plugin = plugin; + this.about = null; this.summary = null; this.errors = []; @@ -10160,19 +10195,10 @@ } /** - * Sets the title of the info panel + * Sets the contents of the about section as HTML */ _createClass(InfoPanel, [{ - key: "setTitle", - value: function setTitle(title) { - this.title = title; - } - - /** - * Sets the contents of the about section as HTML - */ - }, { key: "setAbout", value: function setAbout(about) { this.about = about; @@ -10204,7 +10230,20 @@ var _this = this; // Create and append a tab marker - var $tab = $(tabTemplate({ title: title })); + var $tab = E( + "li", + { className: "tota11y-info-tab" }, + E( + "a", + { className: "tota11y-info-tab-anchor", href: "#" }, + E( + "span", + { className: "tota11y-info-tab-anchor-text" }, + title + ) + ) + ); + this.$el.find(".tota11y-info-tabs").append($tab); // Create and append the tab content @@ -10241,20 +10280,27 @@ value: function initAndPosition() { var _this2 = this; - var panelRightPx = INITIAL_PANEL_MARGIN_PX; - var panelBottomPx = INITIAL_PANEL_MARGIN_PX; + var panelLeftPx = undefined, + panelTopPx = undefined; // Wire up the dismiss button this.$el.find(".tota11y-info-dismiss-trigger").click(function (e) { e.preventDefault(); e.stopPropagation(); _this2.$el.addClass(HIDDEN_CLASS_NAME); + + // (a11y) Bring the focus back to the plugin's checkbox + _this2.plugin.$checkbox.focus(); }); // Append the info panel to the body. In reality we'll likely want // it directly adjacent to the toolbar. $("body").append(this.$el); + // Position info panel on the bottom right of the window + panelLeftPx = window.innerWidth - this.$el.width() - INITIAL_PANEL_MARGIN_PX; + panelTopPx = window.innerHeight - this.$el.height() - INITIAL_PANEL_MARGIN_PX; + // Wire up draggable surface var $draggable = this.$el.find(".tota11y-info-title"); var isDragging = false; @@ -10262,8 +10308,8 @@ // Variables for the starting positions of the mouse and panel var initMouseX = undefined, initMouseY = undefined; - var initPanelRight = undefined, - initPanelBottom = undefined; + var initPanelLeft = undefined, + initPanelTop = undefined; $draggable.on("mousedown", function (e) { e.preventDefault(); @@ -10275,8 +10321,8 @@ initMouseX = e.pageX; initMouseY = e.pageY; - initPanelRight = panelRightPx; - initPanelBottom = panelBottomPx; + initPanelLeft = panelLeftPx; + initPanelTop = panelTopPx; }).on("mouseup", function (e) { e.preventDefault(); isDragging = false; @@ -10291,18 +10337,18 @@ var deltaX = e.pageX - initMouseX; var deltaY = e.pageY - initMouseY; - panelRightPx = initPanelRight - deltaX; - panelBottomPx = initPanelBottom - deltaY; + panelLeftPx = initPanelLeft + deltaX; + panelTopPx = initPanelTop + deltaY; _this2.$el.css({ - right: panelRightPx, - bottom: panelBottomPx + left: panelLeftPx, + top: panelTopPx }); }); this.$el.css({ - right: panelRightPx, - bottom: panelBottomPx + left: panelLeftPx, + top: panelTopPx }); } }, { @@ -10317,9 +10363,42 @@ var hasContent = false; - this.$el = $(template({ - title: this.title - })); + this.$el = E( + "div", + { className: "tota11y tota11y-info", tabindex: "-1" }, + E( + "header", + { className: "tota11y-info-title" }, + this.plugin.getTitle(), + E( + "span", + { className: "tota11y-info-controls" }, + E( + "label", + { className: "tota11y-info-annotation-toggle" }, + "Annotate:", + " ", + E("input", { + className: "toggle-annotation", + type: "checkbox", + checked: "checked" }) + ), + E( + "a", + { "aria-label": "Close info panel", + href: "#", + className: "tota11y-info-dismiss-trigger" }, + "×" + ) + ) + ), + E( + "div", + { className: "tota11y-info-body" }, + E("div", { className: "tota11y-info-sections" }), + E("ul", { role: "tablist", className: "tota11y-info-tabs" }) + ) + ); // Add the appropriate tabs based on which information the info panel // was provided, then highlight the most important one. @@ -10449,6 +10528,9 @@ this.initAndPosition(); } + // (a11y) Shift focus to the newly-opened info panel + this.$el.focus(); + return this.$el; } }, { @@ -10474,6 +10556,7 @@ })(); module.exports = InfoPanel; + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ./element */ 3))) /***/ }, /* 13 */ @@ -11546,22 +11629,6 @@ /***/ }, /* 25 */ -/*!*******************************************************!*\ - !*** ./plugins/shared/info-panel/template.handlebars ***! - \*******************************************************/ -/***/ function(module, exports, __webpack_require__) { - - var Handlebars = __webpack_require__(/*! ./~/handlebars/runtime.js */ 15); - module.exports = (Handlebars["default"] || Handlebars).template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { - var helper; - - return "
\n
\n " - + this.escapeExpression(((helper = (helper = helpers.title || (depth0 != null ? depth0.title : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0,{"name":"title","hash":{},"data":data}) : helper))) - + "\n \n \n \n ×\n \n \n
\n
\n
\n \n
\n
\n"; - },"useData":true}); - -/***/ }, -/* 26 */ /*!****************************************************!*\ !*** ./plugins/shared/info-panel/error.handlebars ***! \****************************************************/ @@ -11571,29 +11638,13 @@ module.exports = (Handlebars["default"] || Handlebars).template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { var stack1, helper; - return "
  • \n \n
    \n
    \n
    \n \n
    \n \n ›\n \n " + return "
  • \n \n
    \n
    \n
    \n \n
    \n \n ›\n \n " + ((stack1 = ((helper = (helper = helpers.title || (depth0 != null ? depth0.title : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0,{"name":"title","hash":{},"data":data}) : helper))) != null ? stack1 : "") + "\n
    \n
    \n
    \n
    \n Relevant code:\n \n
    \n
    \n
  • \n"; },"useData":true}); /***/ }, -/* 27 */ -/*!**************************************************!*\ - !*** ./plugins/shared/info-panel/tab.handlebars ***! - \**************************************************/ -/***/ function(module, exports, __webpack_require__) { - - var Handlebars = __webpack_require__(/*! ./~/handlebars/runtime.js */ 15); - module.exports = (Handlebars["default"] || Handlebars).template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { - var helper; - - return "
  • \n \n " - + this.escapeExpression(((helper = (helper = helpers.title || (depth0 != null ? depth0.title : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0,{"name":"title","hash":{},"data":data}) : helper))) - + "\n \n
  • \n"; - },"useData":true}); - -/***/ }, -/* 28 */ +/* 26 */ /*!**********************************************!*\ !*** ./plugins/shared/info-panel/style.less ***! \**********************************************/ @@ -11602,7 +11653,7 @@ // style-loader: Adds some css to the DOM by adding a