From da45ef2fbaf36c9e47f2b499d2e54a413eb98a01 Mon Sep 17 00:00:00 2001 From: "James D. Forrester" Date: Fri, 31 Oct 2014 16:24:10 -0700 Subject: [PATCH] Update OOjs UI to v0.1.0-pre (eee616d664) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit New changes: f2e316a JS/PHP comparison test suite tweaks d6dbeb1 [BREAKING CHANGE] Rename InlineMenuWidget → DropdownWidget 2c53fc3 ButtonElement: Add 'font-family: inherit;' to support ButtonInputWidgets ac42c94 More documentation tweaks 71b3ebc FieldLayout: Add 'help' config option support to PHP 5265427 OOUI PHP: Support RTL text direction 9204727 Clean up horrible things in LookupInputWidget Change-Id: Ifb7ffb180033422b5c3abfe56eb63a5b44d6789e --- resources/lib/oojs-ui/oojs-ui-apex.css | 39 +- resources/lib/oojs-ui/oojs-ui-apex.js | 4 +- resources/lib/oojs-ui/oojs-ui-apex.svg.css | 39 +- resources/lib/oojs-ui/oojs-ui-mediawiki.css | 41 +- resources/lib/oojs-ui/oojs-ui-mediawiki.js | 4 +- .../lib/oojs-ui/oojs-ui-mediawiki.svg.css | 41 +- resources/lib/oojs-ui/oojs-ui.js | 382 ++++++++++-------- 7 files changed, 309 insertions(+), 241 deletions(-) diff --git a/resources/lib/oojs-ui/oojs-ui-apex.css b/resources/lib/oojs-ui/oojs-ui-apex.css index 746cec36da..21ea55c5a7 100644 --- a/resources/lib/oojs-ui/oojs-ui-apex.css +++ b/resources/lib/oojs-ui/oojs-ui-apex.css @@ -1,12 +1,12 @@ /*! - * OOjs UI v0.1.0-pre (da4b0d5c14) + * OOjs UI v0.1.0-pre (eee616d664) * https://www.mediawiki.org/wiki/OOjs_UI * * Copyright 2011–2014 OOjs Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2014-10-30T00:10:19Z + * Date: 2014-10-31T23:24:06Z */ /* @noflip */ .oo-ui-rtl { @@ -20,6 +20,7 @@ cursor: pointer; display: inline-block; vertical-align: middle; + font-family: inherit; -webkit-touch-callout: none; -webkit-user-select: none; -moz-user-select: none; @@ -1399,14 +1400,14 @@ padding: 0.33em 0.75em; color: #888888; } -.oo-ui-inlineMenuWidget { +.oo-ui-dropdownWidget { position: relative; display: inline-block; margin: 0.25em 0; width: 100%; max-width: 50em; } -.oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget-handle { width: 100%; display: inline-block; cursor: pointer; @@ -1419,57 +1420,57 @@ -moz-box-sizing: border-box; box-sizing: border-box; } -.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator, -.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon { +.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator, +.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon { position: absolute; background-position: center center; background-repeat: no-repeat; } -.oo-ui-inlineMenuWidget .oo-ui-menuWidget { +.oo-ui-dropdownWidget .oo-ui-menuWidget { z-index: 1; width: 100%; } -.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle { cursor: default; } -.oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget-handle { height: 2.5em; border: solid 1px rgba(0, 0, 0, 0.1); border-radius: 0.25em; } -.oo-ui-inlineMenuWidget-handle:hover { +.oo-ui-dropdownWidget-handle:hover { border-color: rgba(0, 0, 0, 0.2); } -.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator { +.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator { right: 0; } -.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon { +.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon { left: 0.25em; } -.oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label { +.oo-ui-dropdownWidget-handle .oo-ui-labelElement-label { line-height: 2.5em; margin: 0 0.5em; } -.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator, -.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon { +.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator, +.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon { top: 0; width: 2.5em; height: 2.5em; opacity: 0.8; } -.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle { color: #cccccc; text-shadow: 0 1px 1px #ffffff; border-color: #dddddd; background-color: #f3f3f3; } -.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator { +.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator { opacity: 0.2; } -.oo-ui-inlineMenuWidget.oo-ui-iconElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label { +.oo-ui-dropdownWidget.oo-ui-iconElement .oo-ui-dropdownWidget-handle .oo-ui-labelElement-label { margin-left: 3em; } -.oo-ui-inlineMenuWidget.oo-ui-indicatorElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label { +.oo-ui-dropdownWidget.oo-ui-indicatorElement .oo-ui-dropdownWidget-handle .oo-ui-labelElement-label { margin-right: 2em; } .oo-ui-outlineItemWidget { diff --git a/resources/lib/oojs-ui/oojs-ui-apex.js b/resources/lib/oojs-ui/oojs-ui-apex.js index 0db21a4823..fa46278061 100644 --- a/resources/lib/oojs-ui/oojs-ui-apex.js +++ b/resources/lib/oojs-ui/oojs-ui-apex.js @@ -1,12 +1,12 @@ /*! - * OOjs UI v0.1.0-pre (da4b0d5c14) + * OOjs UI v0.1.0-pre (eee616d664) * https://www.mediawiki.org/wiki/OOjs_UI * * Copyright 2011–2014 OOjs Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2014-10-30T00:10:09Z + * Date: 2014-10-31T23:23:56Z */ /* Instantiation */ diff --git a/resources/lib/oojs-ui/oojs-ui-apex.svg.css b/resources/lib/oojs-ui/oojs-ui-apex.svg.css index c1bd8a0b0a..10d8afb2a5 100644 --- a/resources/lib/oojs-ui/oojs-ui-apex.svg.css +++ b/resources/lib/oojs-ui/oojs-ui-apex.svg.css @@ -1,12 +1,12 @@ /*! - * OOjs UI v0.1.0-pre (da4b0d5c14) + * OOjs UI v0.1.0-pre (eee616d664) * https://www.mediawiki.org/wiki/OOjs_UI * * Copyright 2011–2014 OOjs Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2014-10-30T00:10:19Z + * Date: 2014-10-31T23:24:06Z */ /* @noflip */ .oo-ui-rtl { @@ -20,6 +20,7 @@ cursor: pointer; display: inline-block; vertical-align: middle; + font-family: inherit; -webkit-touch-callout: none; -webkit-user-select: none; -moz-user-select: none; @@ -1399,14 +1400,14 @@ padding: 0.33em 0.75em; color: #888888; } -.oo-ui-inlineMenuWidget { +.oo-ui-dropdownWidget { position: relative; display: inline-block; margin: 0.25em 0; width: 100%; max-width: 50em; } -.oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget-handle { width: 100%; display: inline-block; cursor: pointer; @@ -1419,57 +1420,57 @@ -moz-box-sizing: border-box; box-sizing: border-box; } -.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator, -.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon { +.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator, +.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon { position: absolute; background-position: center center; background-repeat: no-repeat; } -.oo-ui-inlineMenuWidget .oo-ui-menuWidget { +.oo-ui-dropdownWidget .oo-ui-menuWidget { z-index: 1; width: 100%; } -.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle { cursor: default; } -.oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget-handle { height: 2.5em; border: solid 1px rgba(0, 0, 0, 0.1); border-radius: 0.25em; } -.oo-ui-inlineMenuWidget-handle:hover { +.oo-ui-dropdownWidget-handle:hover { border-color: rgba(0, 0, 0, 0.2); } -.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator { +.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator { right: 0; } -.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon { +.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon { left: 0.25em; } -.oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label { +.oo-ui-dropdownWidget-handle .oo-ui-labelElement-label { line-height: 2.5em; margin: 0 0.5em; } -.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator, -.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon { +.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator, +.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon { top: 0; width: 2.5em; height: 2.5em; opacity: 0.8; } -.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle { color: #cccccc; text-shadow: 0 1px 1px #ffffff; border-color: #dddddd; background-color: #f3f3f3; } -.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator { +.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator { opacity: 0.2; } -.oo-ui-inlineMenuWidget.oo-ui-iconElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label { +.oo-ui-dropdownWidget.oo-ui-iconElement .oo-ui-dropdownWidget-handle .oo-ui-labelElement-label { margin-left: 3em; } -.oo-ui-inlineMenuWidget.oo-ui-indicatorElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label { +.oo-ui-dropdownWidget.oo-ui-indicatorElement .oo-ui-dropdownWidget-handle .oo-ui-labelElement-label { margin-right: 2em; } .oo-ui-outlineItemWidget { diff --git a/resources/lib/oojs-ui/oojs-ui-mediawiki.css b/resources/lib/oojs-ui/oojs-ui-mediawiki.css index 574342789d..dd4fe03c0c 100644 --- a/resources/lib/oojs-ui/oojs-ui-mediawiki.css +++ b/resources/lib/oojs-ui/oojs-ui-mediawiki.css @@ -1,12 +1,12 @@ /*! - * OOjs UI v0.1.0-pre (da4b0d5c14) + * OOjs UI v0.1.0-pre (eee616d664) * https://www.mediawiki.org/wiki/OOjs_UI * * Copyright 2011–2014 OOjs Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2014-10-30T00:10:19Z + * Date: 2014-10-31T23:24:06Z */ /* @noflip */ .oo-ui-rtl { @@ -20,6 +20,7 @@ cursor: pointer; display: inline-block; vertical-align: middle; + font-family: inherit; -webkit-touch-callout: none; -webkit-user-select: none; -moz-user-select: none; @@ -1285,14 +1286,14 @@ padding: 0.33em 0.75em; color: #888888; } -.oo-ui-inlineMenuWidget { +.oo-ui-dropdownWidget { position: relative; display: inline-block; margin: 0.25em 0; width: 100%; max-width: 50em; } -.oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget-handle { width: 100%; display: inline-block; cursor: pointer; @@ -1305,59 +1306,59 @@ -moz-box-sizing: border-box; box-sizing: border-box; } -.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator, -.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon { +.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator, +.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon { position: absolute; background-position: center center; background-repeat: no-repeat; } -.oo-ui-inlineMenuWidget .oo-ui-menuWidget { +.oo-ui-dropdownWidget .oo-ui-menuWidget { z-index: 1; width: 100%; } -.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle { cursor: default; } -.oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget-handle { height: 2.5em; border: solid 1px #cccccc; border-radius: 0.1em; } -.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator { +.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator { right: 0; } -.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon { +.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon { left: 0.25em; } -.oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label { +.oo-ui-dropdownWidget-handle .oo-ui-labelElement-label { line-height: 2.5em; margin: 0 1em; } -.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator, -.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon { +.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator, +.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon { top: 0; width: 2.5em; height: 2.5em; } -.oo-ui-inlineMenuWidget:hover .oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget:hover .oo-ui-dropdownWidget-handle { border-color: #aaaaaa; } -.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle { color: #cccccc; text-shadow: 0 1px 1px #ffffff; border-color: #dddddd; background-color: #f3f3f3; } -.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator { +.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator { opacity: 0.2; } -.oo-ui-inlineMenuWidget.oo-ui-iconElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label { +.oo-ui-dropdownWidget.oo-ui-iconElement .oo-ui-dropdownWidget-handle .oo-ui-labelElement-label { margin-left: 3em; } -.oo-ui-inlineMenuWidget.oo-ui-indicatorElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label { +.oo-ui-dropdownWidget.oo-ui-indicatorElement .oo-ui-dropdownWidget-handle .oo-ui-labelElement-label { margin-right: 2em; } -.oo-ui-inlineMenuWidget .oo-ui-selectWidget { +.oo-ui-dropdownWidget .oo-ui-selectWidget { border-top-color: #ffffff; } .oo-ui-outlineItemWidget { diff --git a/resources/lib/oojs-ui/oojs-ui-mediawiki.js b/resources/lib/oojs-ui/oojs-ui-mediawiki.js index 5a7462aca4..e4fbd64704 100644 --- a/resources/lib/oojs-ui/oojs-ui-mediawiki.js +++ b/resources/lib/oojs-ui/oojs-ui-mediawiki.js @@ -1,12 +1,12 @@ /*! - * OOjs UI v0.1.0-pre (da4b0d5c14) + * OOjs UI v0.1.0-pre (eee616d664) * https://www.mediawiki.org/wiki/OOjs_UI * * Copyright 2011–2014 OOjs Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2014-10-30T00:10:09Z + * Date: 2014-10-31T23:23:56Z */ /** * @class diff --git a/resources/lib/oojs-ui/oojs-ui-mediawiki.svg.css b/resources/lib/oojs-ui/oojs-ui-mediawiki.svg.css index 3495e3d4c5..8f4e5a1c76 100644 --- a/resources/lib/oojs-ui/oojs-ui-mediawiki.svg.css +++ b/resources/lib/oojs-ui/oojs-ui-mediawiki.svg.css @@ -1,12 +1,12 @@ /*! - * OOjs UI v0.1.0-pre (da4b0d5c14) + * OOjs UI v0.1.0-pre (eee616d664) * https://www.mediawiki.org/wiki/OOjs_UI * * Copyright 2011–2014 OOjs Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2014-10-30T00:10:19Z + * Date: 2014-10-31T23:24:06Z */ /* @noflip */ .oo-ui-rtl { @@ -20,6 +20,7 @@ cursor: pointer; display: inline-block; vertical-align: middle; + font-family: inherit; -webkit-touch-callout: none; -webkit-user-select: none; -moz-user-select: none; @@ -1285,14 +1286,14 @@ padding: 0.33em 0.75em; color: #888888; } -.oo-ui-inlineMenuWidget { +.oo-ui-dropdownWidget { position: relative; display: inline-block; margin: 0.25em 0; width: 100%; max-width: 50em; } -.oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget-handle { width: 100%; display: inline-block; cursor: pointer; @@ -1305,59 +1306,59 @@ -moz-box-sizing: border-box; box-sizing: border-box; } -.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator, -.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon { +.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator, +.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon { position: absolute; background-position: center center; background-repeat: no-repeat; } -.oo-ui-inlineMenuWidget .oo-ui-menuWidget { +.oo-ui-dropdownWidget .oo-ui-menuWidget { z-index: 1; width: 100%; } -.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle { cursor: default; } -.oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget-handle { height: 2.5em; border: solid 1px #cccccc; border-radius: 0.1em; } -.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator { +.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator { right: 0; } -.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon { +.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon { left: 0.25em; } -.oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label { +.oo-ui-dropdownWidget-handle .oo-ui-labelElement-label { line-height: 2.5em; margin: 0 1em; } -.oo-ui-inlineMenuWidget-handle .oo-ui-indicatorElement-indicator, -.oo-ui-inlineMenuWidget-handle .oo-ui-iconElement-icon { +.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator, +.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon { top: 0; width: 2.5em; height: 2.5em; } -.oo-ui-inlineMenuWidget:hover .oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget:hover .oo-ui-dropdownWidget-handle { border-color: #aaaaaa; } -.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-inlineMenuWidget-handle { +.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle { color: #cccccc; text-shadow: 0 1px 1px #ffffff; border-color: #dddddd; background-color: #f3f3f3; } -.oo-ui-inlineMenuWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator { +.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator { opacity: 0.2; } -.oo-ui-inlineMenuWidget.oo-ui-iconElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label { +.oo-ui-dropdownWidget.oo-ui-iconElement .oo-ui-dropdownWidget-handle .oo-ui-labelElement-label { margin-left: 3em; } -.oo-ui-inlineMenuWidget.oo-ui-indicatorElement .oo-ui-inlineMenuWidget-handle .oo-ui-labelElement-label { +.oo-ui-dropdownWidget.oo-ui-indicatorElement .oo-ui-dropdownWidget-handle .oo-ui-labelElement-label { margin-right: 2em; } -.oo-ui-inlineMenuWidget .oo-ui-selectWidget { +.oo-ui-dropdownWidget .oo-ui-selectWidget { border-top-color: #ffffff; } .oo-ui-outlineItemWidget { diff --git a/resources/lib/oojs-ui/oojs-ui.js b/resources/lib/oojs-ui/oojs-ui.js index d4ac1218ce..3aaeae238c 100644 --- a/resources/lib/oojs-ui/oojs-ui.js +++ b/resources/lib/oojs-ui/oojs-ui.js @@ -1,12 +1,12 @@ /*! - * OOjs UI v0.1.0-pre (da4b0d5c14) + * OOjs UI v0.1.0-pre (eee616d664) * https://www.mediawiki.org/wiki/OOjs_UI * * Copyright 2011–2014 OOjs Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2014-10-30T00:10:09Z + * Date: 2014-10-31T23:23:56Z */ ( function ( OO ) { @@ -800,7 +800,7 @@ OO.ui.Element.getWindow = function ( obj ) { * * @static * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the direction for - * @return {string} Text direction, either `ltr` or `rtl` + * @return {string} Text direction, either 'ltr' or 'rtl' */ OO.ui.Element.getDir = function ( obj ) { var isDoc, isWin; @@ -4294,7 +4294,7 @@ OO.ui.IndicatorElement.prototype.setIndicatorTitle = function ( indicatorTitle ) /** * Get indicator name. * - * @return {string} title Symbolic name of indicator + * @return {string} Symbolic name of indicator */ OO.ui.IndicatorElement.prototype.getIndicator = function () { return this.indicator; @@ -4398,7 +4398,7 @@ OO.ui.LabelElement.prototype.setLabel = function ( label ) { /** * Get the label. * - * @return {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or + * @return {jQuery|string|Function|null} Label nodes; text; a function that returns nodes or * text; or null for no label */ OO.ui.LabelElement.prototype.getLabel = function () { @@ -4546,7 +4546,7 @@ OO.ui.FlaggedElement.prototype.hasFlag = function ( flag ) { /** * Get the names of all flags set. * - * @return {string[]} flags Flag names + * @return {string[]} Flag names */ OO.ui.FlaggedElement.prototype.getFlags = function () { return Object.keys( this.flags ); @@ -7862,6 +7862,10 @@ OO.ui.ItemWidget.prototype.setElementGroup = function ( group ) { * * Subclasses must handle `select` and `choose` events on #lookupMenu to make use of selections. * + * Subclasses that set the value of #lookupInput from their `choose` or `select` handler should + * be aware that this will cause new suggestions to be looked up for the new value. If this is + * not desired, disable lookups with #setLookupsDisabled, then set the value, then re-enable lookups. + * * @class * @abstract * @@ -7885,7 +7889,8 @@ OO.ui.LookupInputWidget = function OoUiLookupInputWidget( input, config ) { this.lookupCache = {}; this.lookupQuery = null; this.lookupRequest = null; - this.populating = false; + this.lookupsDisabled = false; + this.lookupInputFocused = false; // Events this.lookupInput.$input.on( { @@ -7894,6 +7899,7 @@ OO.ui.LookupInputWidget = function OoUiLookupInputWidget( input, config ) { mousedown: this.onLookupInputMouseDown.bind( this ) } ); this.lookupInput.connect( this, { change: 'onLookupInputChange' } ); + this.lookupMenu.connect( this, { toggle: 'onLookupMenuToggle' } ); // Initialization this.$element.addClass( 'oo-ui-lookupWidget' ); @@ -7909,7 +7915,8 @@ OO.ui.LookupInputWidget = function OoUiLookupInputWidget( input, config ) { * @param {jQuery.Event} e Input focus event */ OO.ui.LookupInputWidget.prototype.onLookupInputFocus = function () { - this.openLookupMenu(); + this.lookupInputFocused = true; + this.populateLookupMenu(); }; /** @@ -7918,7 +7925,8 @@ OO.ui.LookupInputWidget.prototype.onLookupInputFocus = function () { * @param {jQuery.Event} e Input blur event */ OO.ui.LookupInputWidget.prototype.onLookupInputBlur = function () { - this.lookupMenu.toggle( false ); + this.closeLookupMenu(); + this.lookupInputFocused = false; }; /** @@ -7927,7 +7935,13 @@ OO.ui.LookupInputWidget.prototype.onLookupInputBlur = function () { * @param {jQuery.Event} e Input mouse down event */ OO.ui.LookupInputWidget.prototype.onLookupInputMouseDown = function () { - this.openLookupMenu(); + // Only open the menu if the input was already focused. + // This way we allow the user to open the menu again after closing it with Esc + // by clicking in the input. Opening (and populating) the menu when initially + // clicking into the input is handled by the focus handler. + if ( this.lookupInputFocused ) { + this.openLookupMenu(); + } }; /** @@ -7936,7 +7950,23 @@ OO.ui.LookupInputWidget.prototype.onLookupInputMouseDown = function () { * @param {string} value New input value */ OO.ui.LookupInputWidget.prototype.onLookupInputChange = function () { - this.openLookupMenu(); + if ( this.lookupInputFocused ) { + this.populateLookupMenu(); + } +}; + +/** + * Handle the lookup menu being shown/hidden. + * @param {boolean} visible Whether the lookup menu is now visible. + */ +OO.ui.LookupInputWidget.prototype.onLookupMenuToggle = function ( visible ) { + if ( !visible ) { + // When the menu is hidden, abort any active request and clear the menu. + // This has to be done here in addition to closeLookupMenu(), because + // MenuWidget will close itself when the user presses Esc. + this.abortLookupRequest(); + this.lookupMenu.clearItems(); + } }; /** @@ -7949,35 +7979,61 @@ OO.ui.LookupInputWidget.prototype.getLookupMenu = function () { }; /** - * Open the menu. + * Disable or re-enable lookups. + * + * When lookups are disabled, calls to #populateLookupMenu will be ignored. + * + * @param {boolean} disabled Disable lookups + */ +OO.ui.LookupInputWidget.prototype.setLookupsDisabled = function ( disabled ) { + this.lookupsDisabled = !!disabled; +}; + +/** + * Open the menu. If there are no entries in the menu, this does nothing. * * @chainable */ OO.ui.LookupInputWidget.prototype.openLookupMenu = function () { - var value = this.lookupInput.getValue(); - - if ( this.lookupMenu.$input.is( ':focus' ) && $.trim( value ) !== '' ) { - this.populateLookupMenu(); + if ( !this.lookupMenu.isEmpty() ) { this.lookupMenu.toggle( true ); - } else { - this.lookupMenu - .clearItems() - .toggle( false ); } + return this; +}; +/** + * Close the menu, empty it, and abort any pending request. + * + * @chainable + */ +OO.ui.LookupInputWidget.prototype.closeLookupMenu = function () { + this.lookupMenu.toggle( false ); + this.abortLookupRequest(); + this.lookupMenu.clearItems(); return this; }; /** - * Populate lookup menu with current information. + * Request menu items based on the input's current value, and when they arrive, + * populate the menu with these items and show the menu. + * + * If lookups have been disabled with #setLookupsDisabled, this function does nothing. * * @chainable */ OO.ui.LookupInputWidget.prototype.populateLookupMenu = function () { - var widget = this; + var widget = this, + value = this.lookupInput.getValue(); - if ( !this.populating ) { - this.populating = true; + if ( this.lookupsDisabled ) { + return; + } + + // If the input is empty, clear the menu + if ( value === '' ) { + this.closeLookupMenu(); + // Skip population if there is already a request pending for the current value + } else if ( value !== this.lookupQuery ) { this.getLookupMenuItems() .done( function ( items ) { widget.lookupMenu.clearItems(); @@ -7986,15 +8042,12 @@ OO.ui.LookupInputWidget.prototype.populateLookupMenu = function () { .addItems( items ) .toggle( true ); widget.initializeLookupMenuSelection(); - widget.openLookupMenu(); } else { - widget.lookupMenu.toggle( true ); + widget.lookupMenu.toggle( false ); } - widget.populating = false; } ) .fail( function () { widget.lookupMenu.clearItems(); - widget.populating = false; } ); } @@ -8002,7 +8055,7 @@ OO.ui.LookupInputWidget.prototype.populateLookupMenu = function () { }; /** - * Set selection in the lookup menu with current information. + * Select and highlight the first selectable item in the menu. * * @chainable */ @@ -8017,67 +8070,78 @@ OO.ui.LookupInputWidget.prototype.initializeLookupMenuSelection = function () { * Get lookup menu items for the current query. * * @return {jQuery.Promise} Promise object which will be passed menu items as the first argument - * of the done event + * of the done event. If the request was aborted to make way for a subsequent request, + * this promise will not be rejected: it will remain pending forever. */ OO.ui.LookupInputWidget.prototype.getLookupMenuItems = function () { var widget = this, value = this.lookupInput.getValue(), - deferred = $.Deferred(); + deferred = $.Deferred(), + ourRequest; - if ( value && value !== this.lookupQuery ) { - // Abort current request if query has changed - if ( this.lookupRequest ) { - this.lookupRequest.abort(); - this.lookupQuery = null; - this.lookupRequest = null; - } - if ( value in this.lookupCache ) { - deferred.resolve( this.getLookupMenuItemsFromData( this.lookupCache[value] ) ); - } else { - this.lookupQuery = value; - this.lookupRequest = this.getLookupRequest() - .always( function () { + this.abortLookupRequest(); + if ( value in this.lookupCache ) { + deferred.resolve( this.getLookupMenuItemsFromData( this.lookupCache[value] ) ); + } else { + this.lookupInput.pushPending(); + this.lookupQuery = value; + ourRequest = this.lookupRequest = this.getLookupRequest(); + ourRequest + .always( function () { + // We need to pop pending even if this is an old request, otherwise + // the widget will remain pending forever. + // TODO: this assumes that an aborted request will fail or succeed soon after + // being aborted, or at least eventually. It would be nice if we could popPending() + // at abort time, but only if we knew that we hadn't already called popPending() + // for that request. + widget.lookupInput.popPending(); + } ) + .done( function ( data ) { + // If this is an old request (and aborting it somehow caused it to still succeed), + // ignore its success completely + if ( ourRequest === widget.lookupRequest ) { widget.lookupQuery = null; widget.lookupRequest = null; - } ) - .done( function ( data ) { widget.lookupCache[value] = widget.getLookupCacheItemFromData( data ); deferred.resolve( widget.getLookupMenuItemsFromData( widget.lookupCache[value] ) ); - } ) - .fail( function () { + } + } ) + .fail( function () { + // If this is an old request (or a request failing because it's being aborted), + // ignore its failure completely + if ( ourRequest === widget.lookupRequest ) { + widget.lookupQuery = null; + widget.lookupRequest = null; deferred.reject(); - } ); - this.pushPending(); - this.lookupRequest.always( function () { - widget.popPending(); + } } ); - } } return deferred.promise(); }; /** - * Get a new request object of the current lookup query value. - * - * @abstract - * @return {jqXHR} jQuery AJAX object, or promise object with an .abort() method + * Abort the currently pending lookup request, if any. */ -OO.ui.LookupInputWidget.prototype.getLookupRequest = function () { - // Stub, implemented in subclass - return null; +OO.ui.LookupInputWidget.prototype.abortLookupRequest = function () { + var oldRequest = this.lookupRequest; + if ( oldRequest ) { + // First unset this.lookupRequest to the fail handler will notice + // that the request is no longer current + this.lookupRequest = null; + this.lookupQuery = null; + oldRequest.abort(); + } }; /** - * Handle successful lookup request. - * - * Overriding methods should call #populateLookupMenu when results are available and cache results - * for future lookups in #lookupCache as an array of #OO.ui.MenuItemWidget objects. + * Get a new request object of the current lookup query value. * * @abstract - * @param {Mixed} data Response from server + * @return {jQuery.Promise} jQuery AJAX object, or promise object with an .abort() method */ -OO.ui.LookupInputWidget.prototype.onLookupRequestDone = function () { +OO.ui.LookupInputWidget.prototype.getLookupRequest = function () { // Stub, implemented in subclass + return null; }; /** @@ -8736,85 +8800,9 @@ OO.ui.ToggleButtonWidget.prototype.setValue = function ( value ) { }; /** - * Icon widget. - * - * See OO.ui.IconElement for more information. - * - * @class - * @extends OO.ui.Widget - * @mixins OO.ui.IconElement - * @mixins OO.ui.TitledElement - * - * @constructor - * @param {Object} [config] Configuration options - */ -OO.ui.IconWidget = function OoUiIconWidget( config ) { - // Config intialization - config = config || {}; - - // Parent constructor - OO.ui.IconWidget.super.call( this, config ); - - // Mixin constructors - OO.ui.IconElement.call( this, $.extend( {}, config, { $icon: this.$element } ) ); - OO.ui.TitledElement.call( this, $.extend( {}, config, { $titled: this.$element } ) ); - - // Initialization - this.$element.addClass( 'oo-ui-iconWidget' ); -}; - -/* Setup */ - -OO.inheritClass( OO.ui.IconWidget, OO.ui.Widget ); -OO.mixinClass( OO.ui.IconWidget, OO.ui.IconElement ); -OO.mixinClass( OO.ui.IconWidget, OO.ui.TitledElement ); - -/* Static Properties */ - -OO.ui.IconWidget.static.tagName = 'span'; - -/** - * Indicator widget. + * Dropdown menu of options. * - * See OO.ui.IndicatorElement for more information. - * - * @class - * @extends OO.ui.Widget - * @mixins OO.ui.IndicatorElement - * @mixins OO.ui.TitledElement - * - * @constructor - * @param {Object} [config] Configuration options - */ -OO.ui.IndicatorWidget = function OoUiIndicatorWidget( config ) { - // Config intialization - config = config || {}; - - // Parent constructor - OO.ui.IndicatorWidget.super.call( this, config ); - - // Mixin constructors - OO.ui.IndicatorElement.call( this, $.extend( {}, config, { $indicator: this.$element } ) ); - OO.ui.TitledElement.call( this, $.extend( {}, config, { $titled: this.$element } ) ); - - // Initialization - this.$element.addClass( 'oo-ui-indicatorWidget' ); -}; - -/* Setup */ - -OO.inheritClass( OO.ui.IndicatorWidget, OO.ui.Widget ); -OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.IndicatorElement ); -OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.TitledElement ); - -/* Static Properties */ - -OO.ui.IndicatorWidget.static.tagName = 'span'; - -/** - * Inline menu of options. - * - * Inline menus provide a control for accessing a menu and compose a menu within the widget, which + * Dropdown menus provide a control for accessing a menu and compose a menu within the widget, which * can be accessed using the #getMenu method. * * Use with OO.ui.MenuItemWidget. @@ -8830,12 +8818,12 @@ OO.ui.IndicatorWidget.static.tagName = 'span'; * @param {Object} [config] Configuration options * @cfg {Object} [menu] Configuration options to pass to menu widget */ -OO.ui.InlineMenuWidget = function OoUiInlineMenuWidget( config ) { +OO.ui.DropdownWidget = function OoUiDropdownWidget( config ) { // Configuration initialization config = $.extend( { indicator: 'down' }, config ); // Parent constructor - OO.ui.InlineMenuWidget.super.call( this, config ); + OO.ui.DropdownWidget.super.call( this, config ); // Mixin constructors OO.ui.IconElement.call( this, config ); @@ -8853,20 +8841,20 @@ OO.ui.InlineMenuWidget = function OoUiInlineMenuWidget( config ) { // Initialization this.$handle - .addClass( 'oo-ui-inlineMenuWidget-handle' ) + .addClass( 'oo-ui-dropdownWidget-handle' ) .append( this.$icon, this.$label, this.$indicator ); this.$element - .addClass( 'oo-ui-inlineMenuWidget' ) + .addClass( 'oo-ui-dropdownWidget' ) .append( this.$handle, this.menu.$element ); }; /* Setup */ -OO.inheritClass( OO.ui.InlineMenuWidget, OO.ui.Widget ); -OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.IconElement ); -OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.IndicatorElement ); -OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.LabelElement ); -OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.TitledElement ); +OO.inheritClass( OO.ui.DropdownWidget, OO.ui.Widget ); +OO.mixinClass( OO.ui.DropdownWidget, OO.ui.IconElement ); +OO.mixinClass( OO.ui.DropdownWidget, OO.ui.IndicatorElement ); +OO.mixinClass( OO.ui.DropdownWidget, OO.ui.LabelElement ); +OO.mixinClass( OO.ui.DropdownWidget, OO.ui.TitledElement ); /* Methods */ @@ -8875,7 +8863,7 @@ OO.mixinClass( OO.ui.InlineMenuWidget, OO.ui.TitledElement ); * * @return {OO.ui.MenuWidget} Menu of widget */ -OO.ui.InlineMenuWidget.prototype.getMenu = function () { +OO.ui.DropdownWidget.prototype.getMenu = function () { return this.menu; }; @@ -8884,7 +8872,7 @@ OO.ui.InlineMenuWidget.prototype.getMenu = function () { * * @param {OO.ui.MenuItemWidget} item Selected menu item */ -OO.ui.InlineMenuWidget.prototype.onMenuSelect = function ( item ) { +OO.ui.DropdownWidget.prototype.onMenuSelect = function ( item ) { var selectedLabel; if ( !item ) { @@ -8906,7 +8894,7 @@ OO.ui.InlineMenuWidget.prototype.onMenuSelect = function ( item ) { * * @param {jQuery.Event} e Mouse click event */ -OO.ui.InlineMenuWidget.prototype.onClick = function ( e ) { +OO.ui.DropdownWidget.prototype.onClick = function ( e ) { // Skip clicks within the menu if ( $.contains( this.menu.$element[0], e.target ) ) { return; @@ -8922,6 +8910,82 @@ OO.ui.InlineMenuWidget.prototype.onClick = function ( e ) { return false; }; +/** + * Icon widget. + * + * See OO.ui.IconElement for more information. + * + * @class + * @extends OO.ui.Widget + * @mixins OO.ui.IconElement + * @mixins OO.ui.TitledElement + * + * @constructor + * @param {Object} [config] Configuration options + */ +OO.ui.IconWidget = function OoUiIconWidget( config ) { + // Config intialization + config = config || {}; + + // Parent constructor + OO.ui.IconWidget.super.call( this, config ); + + // Mixin constructors + OO.ui.IconElement.call( this, $.extend( {}, config, { $icon: this.$element } ) ); + OO.ui.TitledElement.call( this, $.extend( {}, config, { $titled: this.$element } ) ); + + // Initialization + this.$element.addClass( 'oo-ui-iconWidget' ); +}; + +/* Setup */ + +OO.inheritClass( OO.ui.IconWidget, OO.ui.Widget ); +OO.mixinClass( OO.ui.IconWidget, OO.ui.IconElement ); +OO.mixinClass( OO.ui.IconWidget, OO.ui.TitledElement ); + +/* Static Properties */ + +OO.ui.IconWidget.static.tagName = 'span'; + +/** + * Indicator widget. + * + * See OO.ui.IndicatorElement for more information. + * + * @class + * @extends OO.ui.Widget + * @mixins OO.ui.IndicatorElement + * @mixins OO.ui.TitledElement + * + * @constructor + * @param {Object} [config] Configuration options + */ +OO.ui.IndicatorWidget = function OoUiIndicatorWidget( config ) { + // Config intialization + config = config || {}; + + // Parent constructor + OO.ui.IndicatorWidget.super.call( this, config ); + + // Mixin constructors + OO.ui.IndicatorElement.call( this, $.extend( {}, config, { $indicator: this.$element } ) ); + OO.ui.TitledElement.call( this, $.extend( {}, config, { $titled: this.$element } ) ); + + // Initialization + this.$element.addClass( 'oo-ui-indicatorWidget' ); +}; + +/* Setup */ + +OO.inheritClass( OO.ui.IndicatorWidget, OO.ui.Widget ); +OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.IndicatorElement ); +OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.TitledElement ); + +/* Static Properties */ + +OO.ui.IndicatorWidget.static.tagName = 'span'; + /** * Base class for input widgets. * @@ -9126,9 +9190,9 @@ OO.ui.InputWidget.prototype.blur = function () { * @param {Object} [config] Configuration options * @cfg {string} [type='button'] HTML tag `type` attribute, may be 'button', 'submit' or 'reset' * @cfg {boolean} [useInputTag=false] Whether to use `` rather than `