Merge "mediawiki.ui: button: Use the correct background color for disabled buttons"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 17 Feb 2015 14:00:35 +0000 (14:00 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 17 Feb 2015 14:00:35 +0000 (14:00 +0000)
includes/htmlform/HTMLCheckField.php
resources/src/jquery/jquery.confirmable.js
resources/src/jquery/jquery.confirmable.mediawiki.js
resources/src/jquery/jquery.makeCollapsible.css
resources/src/jquery/jquery.tablesorter.js
tests/qunit/QUnitTestResources.php
tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js [new file with mode: 0644]

index e54f748..4942327 100644 (file)
@@ -58,23 +58,16 @@ class HTMLCheckField extends HTMLFormField {
         * @return string
         */
        function loadDataFromRequest( $request ) {
-               $invert = false;
-               if ( isset( $this->mParams['invert'] ) && $this->mParams['invert'] ) {
-                       $invert = true;
-               }
+               $invert = isset( $this->mParams['invert'] ) && $this->mParams['invert'];
 
                // GetCheck won't work like we want for checks.
                // Fetch the value in either one of the two following case:
                // - we have a valid token (form got posted or GET forged by the user)
                // - checkbox name has a value (false or true), ie is not null
                if ( $request->getCheck( 'wpEditToken' ) || $request->getVal( $this->mName ) !== null ) {
-                       // XOR has the following truth table, which is what we want
-                       // INVERT VALUE | OUTPUT
-                       // true   true  | false
-                       // false  true  | true
-                       // false  false | false
-                       // true   false | true
-                       return $request->getBool( $this->mName ) xor $invert;
+                       return $invert
+                               ? !$request->getBool( $this->mName )
+                               : $request->getBool( $this->mName );
                } else {
                        return $this->getDefault();
                }
index 339e65a..1ecce6c 100644 (file)
@@ -40,6 +40,8 @@
         * @param {string} [options.i18n.confirm] Text to use for the confirmation question.
         * @param {string} [options.i18n.yes] Text to use for the 'Yes' button.
         * @param {string} [options.i18n.no] Text to use for the 'No' button.
+        * @param {string} [options.i18n.yesTitle] Title text to use for the 'Yes' button.
+        * @param {string} [options.i18n.noTitle] Title text to use for the 'No' button.
         *
         * @chainable
         */
                                if ( options.handler ) {
                                        $buttonYes.on( options.events, options.handler );
                                }
+                               if ( options.i18n.yesTitle ) {
+                                       $buttonYes.attr( 'title', options.i18n.yesTitle );
+                               }
                                $buttonYes = options.buttonCallback( $buttonYes, 'yes' );
 
                                // Clone it without any events and prevent default action to represent the 'No' button.
                                                $interface.css( 'width', 0 );
                                                e.preventDefault();
                                        } );
+                               if ( options.i18n.noTitle ) {
+                                       $buttonNo.attr( 'title', options.i18n.noTitle );
+                               } else {
+                                       $buttonNo.removeAttr( 'title' );
+                               }
                                $buttonNo = options.buttonCallback( $buttonNo, 'no' );
 
                                // Prevent memory leaks
                        space: ' ',
                        confirm: 'Are you sure?',
                        yes: 'Yes',
-                       no: 'No'
+                       no: 'No',
+                       yesTitle: undefined,
+                       noTitle: undefined
                }
        };
 }( jQuery ) );
index d4a106e..daf23a9 100644 (file)
@@ -9,6 +9,8 @@
                space: mw.message( 'word-separator' ).text(),
                confirm: mw.message( 'confirmable-confirm', mw.user ).text(),
                yes: mw.message( 'confirmable-yes' ).text(),
-               no: mw.message( 'confirmable-no' ).text()
+               no: mw.message( 'confirmable-no' ).text(),
+               yesTitle: undefined,
+               noTitle: undefined
        };
 }( mediaWiki, jQuery ) );
index 0f47150..2e5efba 100644 (file)
@@ -6,18 +6,38 @@
        -ms-user-select: none;
        user-select: none;
 }
+/* Align the toggle based on the direction of the content language */
+/* @noflip */
+.mw-content-ltr .mw-collapsible-toggle,
+.mw-content-rtl .mw-content-ltr .mw-collapsible-toggle {
+       float: right;
+}
+/* @noflip */
+.mw-content-rtl .mw-collapsible-toggle,
+.mw-content-ltr .mw-content-rtl .mw-collapsible-toggle {
+       float: left;
+}
+
 .mw-customtoggle,
 .mw-collapsible-toggle {
        cursor: pointer;
 }
 
 /* collapse links in captions should be inline */
-caption .mw-collapsible-toggle {
+caption .mw-collapsible-toggle,
+.mw-content-ltr caption .mw-collapsible-toggle,
+.mw-content-rtl caption .mw-collapsible-toggle,
+.mw-content-rtl .mw-content-ltr caption .mw-collapsible-toggle,
+.mw-content-ltr .mw-content-rtl caption .mw-collapsible-toggle {
        float: none;
 }
 
 /* list-items go as wide as their parent element, don't float them inside list items */
-li .mw-collapsible-toggle {
+li .mw-collapsible-toggle,
+.mw-content-ltr li .mw-collapsible-toggle,
+.mw-content-rtl li .mw-collapsible-toggle,
+.mw-content-rtl .mw-content-ltr li .mw-collapsible-toggle,
+.mw-content-ltr .mw-content-rtl li .mw-collapsible-toggle {
        float: none;
 }
 
index afff1a6..ff5ff0a 100644 (file)
 
                        clearTableBody: function ( table ) {
                                $( table.tBodies[0] ).empty();
+                       },
+
+                       getParser: function ( id ) {
+                               buildTransformTable();
+                               buildDateTable();
+                               cacheRegexs();
+                               buildCollationTable();
+
+                               return getParserById( id );
                        }
                };
 
index 29834c1..4bcd814 100644 (file)
@@ -60,6 +60,7 @@ return array(
                        'tests/qunit/suites/resources/jquery/jquery.placeholder.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.tabIndex.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js',
+                       'tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js',
                        'tests/qunit/suites/resources/jquery/jquery.textSelection.test.js',
                        'tests/qunit/data/mediawiki.jqueryMsg.data.js',
                        'tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js',
diff --git a/tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js b/tests/qunit/suites/resources/jquery/jquery.tablesorter.parsers.test.js
new file mode 100644 (file)
index 0000000..2c56eea
--- /dev/null
@@ -0,0 +1,200 @@
+( function ( $, mw ) {
+       /**
+        * This module tests the input/output capabilities of the parsers of tablesorter.
+        * It does not test actual sorting.
+        */
+
+       var text, ipv4,
+               simpleMDYDatesInMDY, simpleMDYDatesInDMY, oldMDYDates, complexMDYDates, clobberedDates, MYDates, YDates,
+               currencyData, transformedCurrencyData,
+               config = {
+                       wgContentLanguage: 'en',
+                       /* default date format of the content language */
+                       wgDefaultDateFormat: 'dmy',
+                       /* These two are important for numeric interpretations */
+                       wgSeparatorTransformTable: ['', ''],
+                       wgDigitTransformTable: ['', '']
+               };
+
+       QUnit.module( 'jquery.tablesorter.parsers', QUnit.newMwEnvironment( { config: config } ) );
+
+       /**
+        * For a value, check if the parser recognizes it and how it transforms it
+        *
+        * @param {String} msg text to pass on to qunit describing the test case
+        * @param {String[]} parserId of the parser that will be tested
+        * @param {String[][]} data Array of testcases. Each testcase, array of
+        *              inputValue: The string value that we want to test the parser for
+        *              recognized: If we expect that this value's type is detectable by the parser
+        *              outputValue: The value the parser has converted the input to
+        *              msg: describing the testcase
+        * @param {function($table)} callback something to do before we start the testcase
+        */
+       function parserTest( msg, parserId, data, callback ) {
+               QUnit.test( msg, data.length * 2, function ( assert ) {
+                       var extractedR, extractedF, parser;
+
+                       if (callback !== undefined ) {
+                               callback();
+                       }
+
+                       parser = $.tablesorter.getParser( parserId );
+                       $.each( data, function ( index, testcase ) {
+                               extractedR = parser.is( testcase[0] );
+                               extractedF = parser.format( testcase[0] );
+
+                               assert.strictEqual( extractedR, testcase[1], 'Detect: ' + testcase[3] );
+                               assert.strictEqual( extractedF, testcase[2], 'Sortkey: ' + testcase[3] );
+                       } );
+
+               } );
+       }
+
+       text  = [
+               [ 'Mars', true, 'mars', 'Simple text' ],
+               [ 'Mẘas', true, 'mẘas', 'Non ascii character' ],
+               [ 'A sentence', true, 'a sentence', 'A sentence with space chars' ]
+       ];
+       parserTest( 'Textual keys', 'text', text );
+
+       ipv4 = [
+               // Some randomly generated fake IPs
+               ['0.0.0.0', true, 0, 'An IP address' ],
+               ['255.255.255.255', true, 255255255255, 'An IP address' ],
+               ['45.238.27.109', true, 45238027109, 'An IP address' ],
+               ['1.238.27.1', true, 1238027001, 'An IP address with small numbers' ],
+               ['238.27.1', false, 238027001, 'A malformed IP Address' ],
+               ['1', false, 1, 'A super malformed IP Address' ],
+               ['Just text', false, 0, 'A line with just text' ],
+               ['45.238.27.109Postfix', false, 45238027109, 'An IP address with a connected postfix' ],
+               ['45.238.27.109 postfix', false, 45238027109, 'An IP address with a seperated postfix' ]
+       ];
+       parserTest( 'IPv4', 'IPAddress', ipv4 );
+
+       simpleMDYDatesInMDY = [
+               ['January 17, 2010',    true, 20100117, 'Long middle endian date'],
+               ['Jan 17, 2010',        true, 20100117, 'Short middle endian date'],
+               ['1/17/2010',           true, 20100117, 'Numeric middle endian date'],
+               ['01/17/2010',          true, 20100117, 'Numeric middle endian date with padding on month'],
+               ['01/07/2010',          true, 20100107, 'Numeric middle endian date with padding on day'],
+               ['01/07/0010',          true, 20100107, 'Numeric middle endian date with padding on year'],
+               ['5.12.1990',           true, 19900512, 'Numeric middle endian date with . separator']
+       ];
+       parserTest( 'MDY Dates using mdy content language', 'date', simpleMDYDatesInMDY );
+
+       simpleMDYDatesInDMY = [
+               ['January 17, 2010',    true, 20100117, 'Long middle endian date'],
+               ['Jan 17, 2010',        true, 20100117, 'Short middle endian date'],
+               ['1/17/2010',           true, 20101701, 'Numeric middle endian date'],
+               ['01/17/2010',          true, 20101701, 'Numeric middle endian date with padding on month'],
+               ['01/07/2010',          true, 20100701, 'Numeric middle endian date with padding on day'],
+               ['01/07/0010',          true, 20100701, 'Numeric middle endian date with padding on year'],
+               ['5.12.1990',           true, 19901205, 'Numeric middle endian date with . separator']
+       ];
+       parserTest( 'MDY Dates using dmy content language', 'date', simpleMDYDatesInDMY, function () {
+               mw.config.set( {
+                       'wgDefaultDateFormat': 'dmy',
+                       'wgContentLanguage': 'de'
+               } );
+       } );
+
+       oldMDYDates = [
+               ['January 19, 1400 BC',         false, '99999999', 'BC'],
+               ['January 19, 1400BC',          false, '99999999', 'Connected BC'],
+               ['January, 19 1400 B.C.',       false, '99999999', 'B.C.'],
+               ['January 19, 1400 AD',         false, '99999999', 'AD'],
+               ['January, 19 10',                      true, 20100119, 'AD'],
+               ['January, 19 1',                       false, '99999999', 'AD']
+       ];
+       parserTest( 'Very old MDY dates', 'date', oldMDYDates );
+
+       complexMDYDates = [
+               ['January, 19 2010',    true, 20100119, 'Comma after month'],
+               ['January 19, 2010',    true, 20100119, 'Comma after day'],
+               ['January/19/2010',             true, 20100119, 'Forward slash separator'],
+               ['04 22 1991',                  true, 19910422, 'Month with 0 padding'],
+               ['April 21 1991',               true, 19910421, 'Space separation'],
+               ['04 22 1991',                  true, 19910422, 'Month with 0 padding'],
+               ['December 12 \'10',    true, 20101212, ''],
+               ['Dec 12 \'10',                 true, 20101212, ''],
+               ['Dec. 12 \'10',                true, 20101212, '']
+       ];
+       parserTest( 'MDY Dates', 'date', complexMDYDates );
+
+       clobberedDates = [
+               ['January, 19 2010 - January, 20 2010', false, '99999999', 'Date range with hyphen'],
+               ['January, 19 2010 — January, 20 2010',       false, '99999999', 'Date range with mdash'],
+               ['prefixJanuary, 19 2010',      false, '99999999', 'Connected prefix'],
+               ['prefix January, 19 2010',     false, '99999999', 'Prefix'],
+               ['December 12 2010postfix',     false, '99999999', 'ConnectedPostfix'],
+               ['December 12 2010 postfix',    false, '99999999', 'Postfix'],
+               ['A simple text',               false, '99999999', 'Plain text in date sort'],
+               ['04l22l1991',                  false, '99999999', 'l char as separator'],
+               ['January\\19\\2010',   false, '99999999', 'backslash as date separator']
+       ];
+       parserTest( 'Clobbered Dates', 'date', clobberedDates );
+
+       MYDates = [
+               ['December 2010',       false, '99999999', 'Plain month year'],
+               ['Dec 2010',            false, '99999999', 'Abreviated month year'],
+               ['12 2010',                     false, '99999999', 'Numeric month year']
+       ];
+       parserTest( 'MY Dates', 'date', MYDates );
+
+       YDates = [
+               ['2010',        false, '99999999', 'Plain 4-digit year'],
+               ['876',         false, '99999999', '3-digit year'],
+               ['76',          false, '99999999', '2-digit year'],
+               ['\'76',        false, '99999999', '2-digit millenium bug year'],
+               ['2010 BC',     false, '99999999', '4-digit year BC']
+       ];
+       parserTest( 'Y Dates', 'date', YDates );
+
+       currencyData = [
+               ['1.02 $',      true, 1.02, ''],
+               ['$ 3.00',      true, 3, ''],
+               ['€ 2,99',    true, 299, ''],
+               ['$ 1.00',      true, 1, ''],
+               ['$3.50',       true, 3.50, ''],
+               ['$ 1.50',      true, 1.50, ''],
+               ['€ 0.99',    true, 0.99, ''],
+               ['$ 299.99',    true, 299.99, ''],
+               ['$ 2,299.99',  true, 2299.99, ''],
+               ['$ 2,989',     true, 2989, ''],
+               ['$ 2 299.99',  true, 2299.99, ''],
+               ['$ 2 989',     true, 2989, ''],
+               ['$ 2.989',     true, 2.989, '']
+       ];
+       parserTest( 'Currency', 'currency', currencyData );
+
+       transformedCurrencyData = [
+               ['1.02 $',      true, 102, ''],
+               ['$ 3.00',      true, 300, ''],
+               ['€ 2,99',    true, 2.99, ''],
+               ['$ 1.00',      true, 100, ''],
+               ['$3.50',       true, 350, ''],
+               ['$ 1.50',      true, 150, ''],
+               ['€ 0.99',    true, 99, ''],
+               ['$ 299.99',    true, 29999, ''],
+               ['$ 2\'299,99', true, 2299.99, ''],
+               ['$ 2,989',     true, 2.989, ''],
+               ['$ 2 299.99',  true, 229999, ''],
+               ['2 989 $',     true, 2989, ''],
+               ['299.99 $',    true, 29999, ''],
+               ['2\'299,99 $', true, 2299.99, ''],
+               ['2,989 $',     true, 2.989, ''],
+               ['2 299.99 $',  true, 229999, ''],
+               ['2 989 $',     true, 2989, '']
+       ];
+       parserTest( 'Currency with european separators', 'currency', transformedCurrencyData, function () {
+               mw.config.set( {
+                       // We expect 22'234.444,22
+                       // Map from ascii separators => localized separators
+                       wgSeparatorTransformTable: [',  .       ,', '\' ,       .'],
+                       wgDigitTransformTable: ['', '']
+               } );
+       } );
+
+       // TODO add numbers sorting tests for bug 8115 with a different language
+
+}( jQuery, mediaWiki ) );