diff --git a/build/tota11y.js b/build/tota11y.js index 14031a88..0fa0337f 100644 --- a/build/tota11y.js +++ b/build/tota11y.js @@ -1,5 +1,5 @@ /*! - * tota11y v0.0.9 + * tota11y v0.0.10 * 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-07-22 + * Date: 2015-07-29 * */ /******/ (function(modules) { // webpackBootstrap @@ -79,30 +79,83 @@ var $ = __webpack_require__(/*! jquery */ 2); var plugins = __webpack_require__(/*! ./plugins */ 7); - var logoTemplate = __webpack_require__(/*! ./templates/logo.handlebars */ 46); + var logoTemplate = __webpack_require__(/*! ./templates/logo.handlebars */ 45); // Chrome Accessibility Developer Tools - required once as a global - __webpack_require__(/*! script!./~/accessibility-developer-tools/dist/js/axs_testing.js */ 47); + __webpack_require__(/*! script!./~/accessibility-developer-tools/dist/js/axs_testing.js */ 46); var Toolbar = (function () { function Toolbar() { _classCallCheck(this, Toolbar); + + this.activePlugin = null; } _createClass(Toolbar, [{ + key: "handlePluginClick", + + /** + * Manages the state of the toolbar when a plugin is clicked, and toggles + * the appropriate plugins on and off. + */ + value: function handlePluginClick(plugin) { + // If the plugin was already selected, toggle it off + if (plugin === this.activePlugin) { + plugin.deactivate(); + this.activePlugin = null; + } else { + // Deactivate the active plugin if there is one + if (this.activePlugin) { + this.activePlugin.deactivate(); + } + + // Activate the selected plugin + plugin.activate(); + this.activePlugin = plugin; + } + } + }, { key: "appendTo", + + /** + * Renders the toolbar and appends it to the specified element. + */ value: function appendTo($el) { + var _this = this; + var $logo = $(logoTemplate()); var $toolbar = undefined; - // Attach each plugin - var $plugins = E("div", { className: "tota11y-plugins" }); - plugins.forEach(function (plugin) { - // Mount the plugin to the list - plugin.appendTo($plugins); + var $defaultPlugins = plugins["default"].map(function (Plugin) { + // eslint-disable-line no-unused-vars + // Render each plugin with the bound click handler + return E(Plugin, { onClick: _this.handlePluginClick.bind(_this) }); }); - var handleClick = function handleClick(e) { + var $experimentalPlugins = null; + if (plugins.experimental.length) { + $experimentalPlugins = E( + "div", + null, + E( + "div", + { className: "tota11y-plugins-separator" }, + "Experimental" + ), + plugins.experimental.map(function (Plugin) { + return E(Plugin, { onClick: _this.handlePluginClick.bind(_this) }); + }) + ); + } + + var $plugins = E( + "div", + { className: "tota11y-plugins" }, + $defaultPlugins, + $experimentalPlugins + ); + + var handleToggleClick = function handleToggleClick(e) { e.preventDefault(); e.stopPropagation(); $toolbar.toggleClass("tota11y-expanded"); @@ -112,7 +165,7 @@ "a", { href: "#", className: "tota11y-toolbar-toggle", - onClick: handleClick }, + onClick: handleToggleClick }, E( "div", { className: "tota11y-toolbar-logo" }, @@ -147,6 +200,7 @@ // TODO: Make this customizable bar.appendTo($("body")); }); + // eslint-disable-line no-unused-vars /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(/*! ./element */ 1))) /***/ }, @@ -161,44 +215,61 @@ */ "use strict"; - var $ = __webpack_require__(/*! jquery */ 2); - function buildElement(type, props) { for (var _len = arguments.length, children = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { children[_key - 2] = arguments[_key]; } + // We need to require jQuery inside of this method because `require()` + // will work different after mocha's magic "before" method runs. + // + // This allows us to use the jQuery instance provided by our jsdom + // instance. + var $ = __webpack_require__(/*! jquery */ 2); + // Is our element a TextNode? if (props === undefined) { // Type will be the text content, which can simply be returned here return type; - } - // Create a jQuery element - var $el = $(document.createElement(type)); - - // Iterate through props - if (props !== null) { - for (var propName in props) { - // onClick gets turned into a jQuery event handler - // TODO: Handle props like onHover, onFocus, etc. - if (propName === "onClick") { - var handler = props[propName]; - $el.click(handler); - } else { - var value = props[propName]; - $el.prop(propName, value); + // Is our element a Plugin? + } else if (type.render) { + // Render the plugin with the passed-in click handler + return type.render(props && props.onClick); + + // Otherwise, build the element with jQuery + } else { + var _ret = (function () { + var $el = $("<" + type + ">"); + + // Iterate through props + if (props !== null) { + for (var propName in props) { + // onClick gets turned into a jQuery event handler + // TODO: Handle props like onHover, onFocus, etc. + if (propName === "onClick") { + var handler = props[propName]; + $el.click(handler); + } else { + var value = props[propName]; + $el.prop(propName, value); + } + } } - } - } - // Recurse through the children and append each resulting element to the - // parent - children.forEach(function (child) { - $el.append(buildElement(child)); - }); + // Recurse through the children and append each resulting element to + // the parent + children.forEach(function (child) { + $el.append(buildElement(child)); + }); - return $el; + return { + v: $el + }; + })(); + + if (typeof _ret === "object") return _ret.v; + } } module.exports = buildElement; @@ -9456,7 +9527,7 @@ /***/ function(module, exports, __webpack_require__) { exports = module.exports = __webpack_require__(/*! ./../~/css-loader/lib/css-base.js */ 5)(); - 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: 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-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: 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", ""]); /***/ }, /* 5 */ @@ -9761,13 +9832,17 @@ "use strict"; var AltTextPlugin = __webpack_require__(/*! ./alt-text */ 33); - var ContrastPlugin = __webpack_require__(/*! ./contrast */ 35); - var HeadingsPlugin = __webpack_require__(/*! ./headings */ 40); + var ContrastPlugin = __webpack_require__(/*! ./contrast */ 34); + var HeadingsPlugin = __webpack_require__(/*! ./headings */ 39); var LabelsPlugin = __webpack_require__(/*! ./labels */ 8); - var LandmarksPlugin = __webpack_require__(/*! ./landmarks */ 44); - var LinkTextPlugin = __webpack_require__(/*! ./link-text */ 45); + var LandmarksPlugin = __webpack_require__(/*! ./landmarks */ 43); + var LinkTextPlugin = __webpack_require__(/*! ./link-text */ 44); + + module.exports = { + "default": [new HeadingsPlugin(), new ContrastPlugin(), new LinkTextPlugin(), new LabelsPlugin(), new AltTextPlugin(), new LandmarksPlugin()], - module.exports = [new HeadingsPlugin(), new ContrastPlugin(), new LinkTextPlugin(), new LabelsPlugin(), new AltTextPlugin(), new LandmarksPlugin()]; + experimental: [] + }; /***/ }, /* 8 */ @@ -9830,10 +9905,13 @@ value: function run() { var _this = this; - var result = audit("controlsWithoutLabel"); + var _audit = audit("controlsWithoutLabel"); - if (result.result === "FAIL") { - result.elements.forEach(function (element) { + var result = _audit.result; + var elements = _audit.elements; + + if (result === "FAIL") { + elements.forEach(function (element) { var $el = $(element); var title = "Input is missing a label"; @@ -9883,14 +9961,13 @@ var $ = __webpack_require__(/*! jquery */ 2); var InfoPanel = __webpack_require__(/*! ./shared/info-panel */ 10); var template = __webpack_require__(/*! ../templates/plugin.handlebars */ 30); - var id = 1; var Plugin = (function () { function Plugin() { _classCallCheck(this, Plugin); - this.id = id++; this.panel = new InfoPanel(this.getTitle()); + this.$checkbox = null; } _createClass(Plugin, [{ @@ -9935,68 +10012,48 @@ /** * Renders the plugin view. */ - value: function render() { + value: function render(clickHandler) { + var _this = this; + var templateData = { title: this.getTitle(), description: this.getDescription() }; - return $(template(templateData)); - } - }, { - key: "appendTo", - - /** - * Attaches the plugin to a given DOMNode. - * (chainable) - */ - value: function appendTo($el) { - var _this = this; - - // Render and mount plugin - var $plugin = this.render(); - $el.append($plugin); - - var $checkbox = $plugin.find(".tota11y-plugin-checkbox"); + var $plugin = $(template(templateData)); - $checkbox.click(function (e) { + this.$checkbox = $plugin.find(".tota11y-plugin-checkbox"); + this.$checkbox.click(function (e) { e.stopPropagation(); - - // Trigger a `plugin-switched` event on the container, which will - // be dispatched to all plugins. We include this plugin's ID to - // determine if we should enable or disable the plugin listening - // for this event. - $el.trigger("plugin-switched", [_this.id]); - - // If our checkbox is checked, run and render the panel. - // Otherwise, cleanup. - if ($checkbox.is(":checked")) { - _this.run(); - _this.panel.render(); - } else { - _this.cleanup(); - _this.panel.destroy(); - } + clickHandler(_this); }); - // Listen for the `plugin-switched` event on the plugins container. - $el.on("plugin-switched", function (e, pluginId) { - // If we are the plugin that the user has interacted with, ignore - // this step. We handle our own behavior before the event is - // dispatched. - if (pluginId === _this.id) { - return; + return $plugin; + } + }, { + key: "activate", - // If we are an active plugin that the user switched from, we - // uncheck ourselves and clean up. - } else if ($checkbox.is(":checked")) { - $checkbox.attr("checked", false); - _this.cleanup(); - _this.panel.destroy(); - } - }); + /** + * Activate the plugin from the UI. + */ + value: function activate() { + this.run(); + this.panel.render(); + } + }, { + key: "deactivate", - return this; + /** + * Deactivate the plugin from the UI. + */ + value: function deactivate() { + 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); } }]); @@ -10231,6 +10288,17 @@ $activeTab = this._addTab("Summary", this.summary); } + // Wire annotation toggling. + this.$el.find(".toggle-annotation").click(function (e) { + if ($(e.target).prop("checked")) { + // Showing annotations. + annotate.show(); + } else { + // Hiding annotations. + annotate.hide(); + } + }); + if (this.errors.length > 0) { (function () { var $errors = $("
\n This image does not have an associated \"alt\" attribute. Please specify\n the alt text for this image like so:\n
\n\n<img src=\"..\" alt=\"Image description\">
\n\n\n If the image is decorative and does not convey any information to the\n surrounding content, however, you may leave this \"alt\" attribute empty, or\n specify a \"role\" attribute with a value of \"presentation.\"\n
\n\n<img src=\"..\" alt=\"\">\n<img src=\"..\" role=\"presentation\">
\n";
- },"useData":true});
-
-/***/ },
-/* 35 */
/*!***********************************!*\
!*** ./plugins/contrast/index.js ***!
\***********************************/
@@ -11715,12 +11831,12 @@
var $ = __webpack_require__(/*! jquery */ 2);
var Plugin = __webpack_require__(/*! ../base */ 9);
- var annotate = __webpack_require__(/*! ../shared/annotate */ 20)("labels");
+ var annotate = __webpack_require__(/*! ../shared/annotate */ 20)("contrast");
- var titleTemplate = __webpack_require__(/*! ./error-title.handlebars */ 36);
- var descriptionTemplate = __webpack_require__(/*! ./error-description.handlebars */ 37);
+ var titleTemplate = __webpack_require__(/*! ./error-title.handlebars */ 35);
+ var descriptionTemplate = __webpack_require__(/*! ./error-description.handlebars */ 36);
- __webpack_require__(/*! ./style.less */ 38);
+ __webpack_require__(/*! ./style.less */ 37);
var ContrastPlugin = (function (_Plugin) {
function ContrastPlugin() {
@@ -11894,7 +12010,7 @@
module.exports = ContrastPlugin;
/***/ },
-/* 36 */
+/* 35 */
/*!*************************************************!*\
!*** ./plugins/contrast/error-title.handlebars ***!
\*************************************************/
@@ -11916,7 +12032,7 @@
},"useData":true});
/***/ },
-/* 37 */
+/* 36 */
/*!*******************************************************!*\
!*** ./plugins/contrast/error-description.handlebars ***!
\*******************************************************/
@@ -11948,7 +12064,7 @@
},"useData":true});
/***/ },
-/* 38 */
+/* 37 */
/*!*************************************!*\
!*** ./plugins/contrast/style.less ***!
\*************************************/
@@ -11957,7 +12073,7 @@
// style-loader: Adds some css to the DOM by adding a