From 727cfe1b70f3ee6dc673de94762cda31f34380c0 Mon Sep 17 00:00:00 2001 From: "James D. Forrester" Date: Tue, 25 Aug 2015 17:19:40 -0700 Subject: [PATCH] Update OOjs UI to v0.12.6 Release notes: https://git.wikimedia.org/blob/oojs%2Fui.git/v0.12.6/History.md Change-Id: I29ae78cc7f4913af3cc551a769d428cf85610d71 --- composer.json | 2 +- resources/lib/oojs-ui/i18n/ast.json | 3 +- resources/lib/oojs-ui/i18n/ca.json | 3 +- resources/lib/oojs-ui/i18n/de.json | 3 +- resources/lib/oojs-ui/i18n/el.json | 6 +- resources/lib/oojs-ui/i18n/en.json | 1 + resources/lib/oojs-ui/i18n/es.json | 3 +- resources/lib/oojs-ui/i18n/et.json | 3 +- resources/lib/oojs-ui/i18n/fr.json | 3 +- resources/lib/oojs-ui/i18n/gl.json | 3 +- resources/lib/oojs-ui/i18n/he.json | 3 +- resources/lib/oojs-ui/i18n/km.json | 5 +- resources/lib/oojs-ui/i18n/lb.json | 3 +- resources/lib/oojs-ui/i18n/lt.json | 3 +- resources/lib/oojs-ui/i18n/mk.json | 3 +- resources/lib/oojs-ui/i18n/pl.json | 6 +- resources/lib/oojs-ui/i18n/qqq.json | 1 + resources/lib/oojs-ui/i18n/ro.json | 3 +- resources/lib/oojs-ui/i18n/su.json | 21 + resources/lib/oojs-ui/i18n/uk.json | 6 +- resources/lib/oojs-ui/i18n/zh-hans.json | 14 +- .../lib/oojs-ui/oojs-ui-apex-noimages.css | 22 +- resources/lib/oojs-ui/oojs-ui-apex.js | 4 +- .../oojs-ui/oojs-ui-mediawiki-noimages.css | 38 +- resources/lib/oojs-ui/oojs-ui-mediawiki.js | 10 +- resources/lib/oojs-ui/oojs-ui.js | 597 +++++++++++++----- .../themes/apex/icons-editing-advanced.json | 4 + resources/lib/oojs-ui/themes/apex/icons.json | 4 +- .../themes/apex/images/icons/calendar-ltr.png | Bin 0 -> 213 bytes .../themes/apex/images/icons/calendar-ltr.svg | 4 + .../themes/apex/images/icons/calendar-rtl.png | Bin 0 -> 216 bytes .../themes/apex/images/icons/calendar-rtl.svg | 4 + .../mediawiki/icons-editing-advanced.json | 4 + .../lib/oojs-ui/themes/mediawiki/icons.json | 2 +- .../images/icons/calendar-ltr-invert.png | Bin 0 -> 255 bytes .../images/icons/calendar-ltr-invert.svg | 4 + .../mediawiki/images/icons/calendar-ltr.png | Bin 0 -> 213 bytes .../mediawiki/images/icons/calendar-ltr.svg | 4 + .../images/icons/calendar-rtl-invert.png | Bin 0 -> 239 bytes .../images/icons/calendar-rtl-invert.svg | 4 + .../mediawiki/images/icons/calendar-rtl.png | Bin 0 -> 216 bytes .../mediawiki/images/icons/calendar-rtl.svg | 4 + .../oojs-ui/themes/mediawiki/indicators.json | 2 +- 43 files changed, 605 insertions(+), 204 deletions(-) create mode 100644 resources/lib/oojs-ui/i18n/su.json create mode 100644 resources/lib/oojs-ui/themes/apex/images/icons/calendar-ltr.png create mode 100644 resources/lib/oojs-ui/themes/apex/images/icons/calendar-ltr.svg create mode 100644 resources/lib/oojs-ui/themes/apex/images/icons/calendar-rtl.png create mode 100644 resources/lib/oojs-ui/themes/apex/images/icons/calendar-rtl.svg create mode 100644 resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr-invert.png create mode 100644 resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr-invert.svg create mode 100644 resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr.png create mode 100644 resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr.svg create mode 100644 resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.png create mode 100644 resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.svg create mode 100644 resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl.png create mode 100644 resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl.svg diff --git a/composer.json b/composer.json index af9aeab397..1eb85fd81b 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "leafo/lessphp": "0.5.0", "liuggio/statsd-php-client": "1.0.16", "mediawiki/at-ease": "1.0.0", - "oojs/oojs-ui": "0.12.5", + "oojs/oojs-ui": "0.12.6", "php": ">=5.3.3", "psr/log": "1.0.0", "wikimedia/cdb": "1.0.1", diff --git a/resources/lib/oojs-ui/i18n/ast.json b/resources/lib/oojs-ui/i18n/ast.json index 216df703f3..3ecbe50b52 100644 --- a/resources/lib/oojs-ui/i18n/ast.json +++ b/resources/lib/oojs-ui/i18n/ast.json @@ -19,5 +19,6 @@ "ooui-dialog-process-retry": "Vuelvi a intentalo", "ooui-dialog-process-continue": "Siguir", "ooui-selectfile-not-supported": "Nun hai encontu pa la seleición de ficheros", - "ooui-selectfile-placeholder": "Nun se seleicionó nengún ficheru" + "ooui-selectfile-placeholder": "Nun se seleicionó nengún ficheru", + "ooui-selectfile-dragdrop-placeholder": "Soltar el ficheru equí (o facer clic pa restolar)" } diff --git a/resources/lib/oojs-ui/i18n/ca.json b/resources/lib/oojs-ui/i18n/ca.json index 35a550bfb1..33b0ce046b 100644 --- a/resources/lib/oojs-ui/i18n/ca.json +++ b/resources/lib/oojs-ui/i18n/ca.json @@ -28,5 +28,6 @@ "ooui-dialog-process-retry": "Torneu-ho a provar", "ooui-dialog-process-continue": "Continua", "ooui-selectfile-not-supported": "El tipus de fitxer no és compatible", - "ooui-selectfile-placeholder": "No s'ha seleccionat cap fitxer" + "ooui-selectfile-placeholder": "No s'ha seleccionat cap fitxer", + "ooui-selectfile-dragdrop-placeholder": "Deixeu-hi anar el fitxer (o feu clic a navega)" } diff --git a/resources/lib/oojs-ui/i18n/de.json b/resources/lib/oojs-ui/i18n/de.json index d5649b00bb..ee735ceab5 100644 --- a/resources/lib/oojs-ui/i18n/de.json +++ b/resources/lib/oojs-ui/i18n/de.json @@ -26,5 +26,6 @@ "ooui-dialog-process-retry": "Erneut versuchen", "ooui-dialog-process-continue": "Fortfahren", "ooui-selectfile-not-supported": "Die Dateiauswahl wird nicht unterstützt", - "ooui-selectfile-placeholder": "Keine Datei ausgewählt" + "ooui-selectfile-placeholder": "Keine Datei ausgewählt", + "ooui-selectfile-dragdrop-placeholder": "Dateien hier ablegen (oder klicken zum Durchsuchen)" } diff --git a/resources/lib/oojs-ui/i18n/el.json b/resources/lib/oojs-ui/i18n/el.json index 27f19963e0..b3c48455dd 100644 --- a/resources/lib/oojs-ui/i18n/el.json +++ b/resources/lib/oojs-ui/i18n/el.json @@ -8,7 +8,8 @@ "Geraki", "Glavkos", "Nikosguard", - "Tifa93" + "Tifa93", + "Stam.nikos" ] }, "ooui-outline-control-move-down": "Μετακίνηση στοιχείου προς τα κάτω", @@ -24,5 +25,6 @@ "ooui-dialog-process-retry": "Δοκιμάστε ξανά", "ooui-dialog-process-continue": "Συνέχεια", "ooui-selectfile-not-supported": "Επιλογή αρχείου δεν υποστηρίζεται", - "ooui-selectfile-placeholder": "Κανένα αρχείο δεν είναι επιλεγμένο" + "ooui-selectfile-placeholder": "Κανένα αρχείο δεν είναι επιλεγμένο", + "ooui-selectfile-dragdrop-placeholder": "Σύρετε ένα αρχείο εδώ (ή κάντε κλικ για αναζήτηση)" } diff --git a/resources/lib/oojs-ui/i18n/en.json b/resources/lib/oojs-ui/i18n/en.json index 9812ec6b47..db2399fd12 100644 --- a/resources/lib/oojs-ui/i18n/en.json +++ b/resources/lib/oojs-ui/i18n/en.json @@ -30,5 +30,6 @@ "ooui-dialog-process-continue": "Continue", "ooui-selectfile-not-supported": "File selection is not supported", "ooui-selectfile-placeholder": "No file is selected", + "ooui-selectfile-dragdrop-placeholder": "Drop file here (or click to browse)", "ooui-semicolon-separator": "; " } diff --git a/resources/lib/oojs-ui/i18n/es.json b/resources/lib/oojs-ui/i18n/es.json index e5a8e45948..3f690fc801 100644 --- a/resources/lib/oojs-ui/i18n/es.json +++ b/resources/lib/oojs-ui/i18n/es.json @@ -31,5 +31,6 @@ "ooui-dialog-process-retry": "Intentar de nuevo", "ooui-dialog-process-continue": "Continuar", "ooui-selectfile-not-supported": "No se admite la selección de archivos", - "ooui-selectfile-placeholder": "Ningún archivo seleccionado" + "ooui-selectfile-placeholder": "Ningún archivo seleccionado", + "ooui-selectfile-dragdrop-placeholder": "Soltar el archivo aquí (o pulsa para examinar)" } diff --git a/resources/lib/oojs-ui/i18n/et.json b/resources/lib/oojs-ui/i18n/et.json index e86f11e3a9..1283c8d62d 100644 --- a/resources/lib/oojs-ui/i18n/et.json +++ b/resources/lib/oojs-ui/i18n/et.json @@ -19,5 +19,6 @@ "ooui-dialog-process-retry": "Proovi uuesti", "ooui-dialog-process-continue": "Jätka", "ooui-selectfile-not-supported": "Faili valiku tugi puudub", - "ooui-selectfile-placeholder": "Faili ei ole valitud" + "ooui-selectfile-placeholder": "Faili ei ole valitud", + "ooui-selectfile-dragdrop-placeholder": "Lohista fail siia (või klõpsa, et sirvida)" } diff --git a/resources/lib/oojs-ui/i18n/fr.json b/resources/lib/oojs-ui/i18n/fr.json index 537f6b82ef..fe8ec04ac3 100644 --- a/resources/lib/oojs-ui/i18n/fr.json +++ b/resources/lib/oojs-ui/i18n/fr.json @@ -45,5 +45,6 @@ "ooui-dialog-process-retry": "Réessayer", "ooui-dialog-process-continue": "Continuer", "ooui-selectfile-not-supported": "La sélection de fichier n’est pas prise en charge", - "ooui-selectfile-placeholder": "Aucun fichier sélectionné" + "ooui-selectfile-placeholder": "Aucun fichier sélectionné", + "ooui-selectfile-dragdrop-placeholder": "Déposer le fichier ici (ou cliquez pour parcourir)" } diff --git a/resources/lib/oojs-ui/i18n/gl.json b/resources/lib/oojs-ui/i18n/gl.json index 1283c532c3..0f7ac78547 100644 --- a/resources/lib/oojs-ui/i18n/gl.json +++ b/resources/lib/oojs-ui/i18n/gl.json @@ -20,5 +20,6 @@ "ooui-dialog-process-retry": "Inténteo de novo", "ooui-dialog-process-continue": "Continuar", "ooui-selectfile-not-supported": "Non está soportada a selección de ficheiros", - "ooui-selectfile-placeholder": "Non se seleccionou ningún ficheiro" + "ooui-selectfile-placeholder": "Non se seleccionou ningún ficheiro", + "ooui-selectfile-dragdrop-placeholder": "Solte un ficheiro aquí (ou prema para buscalo)" } diff --git a/resources/lib/oojs-ui/i18n/he.json b/resources/lib/oojs-ui/i18n/he.json index de676651b4..b652d63a32 100644 --- a/resources/lib/oojs-ui/i18n/he.json +++ b/resources/lib/oojs-ui/i18n/he.json @@ -28,5 +28,6 @@ "ooui-dialog-process-retry": "לנסות שוב", "ooui-dialog-process-continue": "המשך", "ooui-selectfile-not-supported": "בחירת קבצים אינה נתמכת", - "ooui-selectfile-placeholder": "לא נבחר שום קובץ" + "ooui-selectfile-placeholder": "לא נבחר שום קובץ", + "ooui-selectfile-dragdrop-placeholder": "נא לשחרר את הקובץ כאן (או ללחוץ לעיון)" } diff --git a/resources/lib/oojs-ui/i18n/km.json b/resources/lib/oojs-ui/i18n/km.json index 0a8bfac24d..e54099d2fe 100644 --- a/resources/lib/oojs-ui/i18n/km.json +++ b/resources/lib/oojs-ui/i18n/km.json @@ -16,5 +16,8 @@ "ooui-dialog-process-error": "មានបញ្ហាអ្វីមួយ", "ooui-dialog-process-dismiss": "បិទ", "ooui-dialog-process-retry": "ព្យាយាមម្ដងទៀត", - "ooui-dialog-process-continue": "បន្ត" + "ooui-dialog-process-continue": "បន្ត", + "ooui-selectfile-not-supported": "ការជ្រើសរើសឯកសារមិនអាចប្រើបានទេ", + "ooui-selectfile-placeholder": "គ្មានឯកសារណាមួយត្រូវបានជ្រើសរើស", + "ooui-selectfile-dragdrop-placeholder": "ទម្លាក់ឯកសារនៅទីនេះ(ឬចុចដើម្បីរាវរក)" } diff --git a/resources/lib/oojs-ui/i18n/lb.json b/resources/lib/oojs-ui/i18n/lb.json index 79bb469b42..65bce10bfd 100644 --- a/resources/lib/oojs-ui/i18n/lb.json +++ b/resources/lib/oojs-ui/i18n/lb.json @@ -22,5 +22,6 @@ "ooui-dialog-process-dismiss": "Verwerfen", "ooui-dialog-process-retry": "Nach eng Kéier probéieren", "ooui-dialog-process-continue": "Virufueren", - "ooui-selectfile-placeholder": "Et ass kee Fichier erausgesicht" + "ooui-selectfile-placeholder": "Et ass kee Fichier erausgesicht", + "ooui-selectfile-dragdrop-placeholder": "Fichier hei deposéieren (oder klickt fir ze sichen)" } diff --git a/resources/lib/oojs-ui/i18n/lt.json b/resources/lib/oojs-ui/i18n/lt.json index 4334efb79c..20aa2f1147 100644 --- a/resources/lib/oojs-ui/i18n/lt.json +++ b/resources/lib/oojs-ui/i18n/lt.json @@ -20,5 +20,6 @@ "ooui-dialog-process-retry": "Bandykite dar kartą", "ooui-dialog-process-continue": "Tęsti", "ooui-selectfile-not-supported": "Failų pasirinkimas nepalaikomas", - "ooui-selectfile-placeholder": "Nėra pasirinktų failų" + "ooui-selectfile-placeholder": "Nėra pasirinktų failų", + "ooui-selectfile-dragdrop-placeholder": "Atitempkite failą čia (arba paspauskite paieškai)" } diff --git a/resources/lib/oojs-ui/i18n/mk.json b/resources/lib/oojs-ui/i18n/mk.json index 53e5bf4401..dd55db40a2 100644 --- a/resources/lib/oojs-ui/i18n/mk.json +++ b/resources/lib/oojs-ui/i18n/mk.json @@ -19,5 +19,6 @@ "ooui-dialog-process-retry": "Обиди се пак", "ooui-dialog-process-continue": "Продолжи", "ooui-selectfile-not-supported": "Изборот на податотеки не е поддржан", - "ooui-selectfile-placeholder": "Немате одбрано податотека" + "ooui-selectfile-placeholder": "Немате одбрано податотека", + "ooui-selectfile-dragdrop-placeholder": "Тука пуштете ја податотеката (или стиснете за да прелистате)" } diff --git a/resources/lib/oojs-ui/i18n/pl.json b/resources/lib/oojs-ui/i18n/pl.json index 81da6f507c..9dd84b0c63 100644 --- a/resources/lib/oojs-ui/i18n/pl.json +++ b/resources/lib/oojs-ui/i18n/pl.json @@ -16,7 +16,8 @@ "Jacenty359", "Matik7", "Gloria sah", - "Andrzej aa" + "Andrzej aa", + "The Polish" ] }, "ooui-outline-control-move-down": "Przenieś niżej", @@ -32,5 +33,6 @@ "ooui-dialog-process-retry": "Spróbuj ponownie", "ooui-dialog-process-continue": "Kontynuuj", "ooui-selectfile-not-supported": "Wybór pliku nie jest obsługiwany", - "ooui-selectfile-placeholder": "Nie wybrano pliku" + "ooui-selectfile-placeholder": "Nie wybrano pliku", + "ooui-selectfile-dragdrop-placeholder": "Umieść plik tutaj (lub kliknij, aby je przeglądać)" } diff --git a/resources/lib/oojs-ui/i18n/qqq.json b/resources/lib/oojs-ui/i18n/qqq.json index bef65ed873..607229d9ad 100644 --- a/resources/lib/oojs-ui/i18n/qqq.json +++ b/resources/lib/oojs-ui/i18n/qqq.json @@ -34,5 +34,6 @@ "ooui-dialog-process-continue": "Label for process dialog retry action button, visible when describing only warnings\n{{Identical|Continue}}", "ooui-selectfile-not-supported": "Label for the file selection dialog if file selection is not supported", "ooui-selectfile-placeholder": "Label for the file selection dialog when no file is currently selected", + "ooui-selectfile-dragdrop-placeholder": "Label for the file selection dialog when no file is currently selected in the drag drop UI. Suggests clicking to open the browse dialog.", "ooui-semicolon-separator": "{{optional}} Semicolon used as a separator" } diff --git a/resources/lib/oojs-ui/i18n/ro.json b/resources/lib/oojs-ui/i18n/ro.json index 970a602616..bf44621816 100644 --- a/resources/lib/oojs-ui/i18n/ro.json +++ b/resources/lib/oojs-ui/i18n/ro.json @@ -21,5 +21,6 @@ "ooui-dialog-process-retry": "Reîncearcă", "ooui-dialog-process-continue": "Continuă", "ooui-selectfile-not-supported": "Selecția de fișiere nu este acceptată", - "ooui-selectfile-placeholder": "Niciun fișier selectat" + "ooui-selectfile-placeholder": "Niciun fișier selectat", + "ooui-selectfile-dragdrop-placeholder": "Trageți fișierul aici (sau faceți clic pentru a răsfoi)" } diff --git a/resources/lib/oojs-ui/i18n/su.json b/resources/lib/oojs-ui/i18n/su.json new file mode 100644 index 0000000000..a8cf762e4b --- /dev/null +++ b/resources/lib/oojs-ui/i18n/su.json @@ -0,0 +1,21 @@ +{ + "@metadata": { + "authors": [ + "Kandar" + ] + }, + "ooui-outline-control-move-down": "Pindahkeun ka handap", + "ooui-outline-control-move-up": "Pindahkeun ka luhur", + "ooui-outline-control-remove": "Hapus", + "ooui-toolbar-more": "Lobaan", + "ooui-toolgroup-expand": "Lobaan", + "ooui-toolgroup-collapse": "Saeutikan", + "ooui-dialog-message-accept": "Heug", + "ooui-dialog-message-reject": "Bolay", + "ooui-dialog-process-error": "Aya nu teu bener", + "ooui-dialog-process-dismiss": "Tutup", + "ooui-dialog-process-retry": "Cobaan deui", + "ooui-dialog-process-continue": "Teruskeun", + "ooui-selectfile-not-supported": "Pamilihan berkas teu dirojong", + "ooui-selectfile-placeholder": "Taya berkas anu dipilih" +} diff --git a/resources/lib/oojs-ui/i18n/uk.json b/resources/lib/oojs-ui/i18n/uk.json index 9e0b97723b..9e727e472e 100644 --- a/resources/lib/oojs-ui/i18n/uk.json +++ b/resources/lib/oojs-ui/i18n/uk.json @@ -16,7 +16,8 @@ "Tifinaghes", "Ата", "Piramidion", - "A1" + "A1", + "Dars" ] }, "ooui-outline-control-move-down": "Перемістити елемент униз", @@ -32,5 +33,6 @@ "ooui-dialog-process-retry": "Спробуйте ще раз", "ooui-dialog-process-continue": "Продовжити", "ooui-selectfile-not-supported": "Вибір файлу не підтримується", - "ooui-selectfile-placeholder": "Жодного файлу не вибрано" + "ooui-selectfile-placeholder": "Жодного файлу не вибрано", + "ooui-selectfile-dragdrop-placeholder": "Помістіть файл сюди (або натисніть, щоб переглянути)" } diff --git a/resources/lib/oojs-ui/i18n/zh-hans.json b/resources/lib/oojs-ui/i18n/zh-hans.json index 7247d938e0..b5b51a0a50 100644 --- a/resources/lib/oojs-ui/i18n/zh-hans.json +++ b/resources/lib/oojs-ui/i18n/zh-hans.json @@ -16,21 +16,23 @@ "Yfdyh000", "Zhangjintao", "乌拉跨氪", - "Great Brightstar" + "Great Brightstar", + "Nbdd0121" ] }, - "ooui-outline-control-move-down": "项目下移", - "ooui-outline-control-move-up": "项目上移", + "ooui-outline-control-move-down": "向下移动一项", + "ooui-outline-control-move-up": "向上移动一项", "ooui-outline-control-remove": "移除项目", "ooui-toolbar-more": "更多", "ooui-toolgroup-expand": "更多", "ooui-toolgroup-collapse": "更少", "ooui-dialog-message-accept": "确定", "ooui-dialog-message-reject": "取消", - "ooui-dialog-process-error": "发生一些错误", - "ooui-dialog-process-dismiss": "解除", + "ooui-dialog-process-error": "发生了一些错误", + "ooui-dialog-process-dismiss": "关闭", "ooui-dialog-process-retry": "重试", "ooui-dialog-process-continue": "继续", "ooui-selectfile-not-supported": "文件选择不受支持", - "ooui-selectfile-placeholder": "没有选定文件" + "ooui-selectfile-placeholder": "没有选定文件", + "ooui-selectfile-dragdrop-placeholder": "将文件拖动至此(或点击以浏览)" } diff --git a/resources/lib/oojs-ui/oojs-ui-apex-noimages.css b/resources/lib/oojs-ui/oojs-ui-apex-noimages.css index 832036225b..1d07fe902b 100644 --- a/resources/lib/oojs-ui/oojs-ui-apex-noimages.css +++ b/resources/lib/oojs-ui/oojs-ui-apex-noimages.css @@ -1,12 +1,12 @@ /*! - * OOjs UI v0.12.5 + * OOjs UI v0.12.6 * https://www.mediawiki.org/wiki/OOjs_UI * * Copyright 2011–2015 OOjs UI Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2015-08-19T02:10:25Z + * Date: 2015-08-26T00:14:44Z */ @-webkit-keyframes oo-ui-progressBarWidget-slide { from { @@ -2112,6 +2112,24 @@ .oo-ui-selectFileWidget-notsupported.oo-ui-indicatorElement .oo-ui-selectFileWidget-handle { padding-right: 2em; } +.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dragdrop-ui .oo-ui-selectFileWidget-handle { + height: 3.5em; + border: 1px dashed #aaaaaa; + padding: 0.5em 1em; + background: #ffffff; + text-align: center; + vertical-align: middle; +} +.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dragdrop-ui .oo-ui-selectFileWidget-handle .oo-ui-iconElement-icon { + margin: 0.6em 0; +} +.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dragdrop-ui .oo-ui-selectFileWidget-handle .oo-ui-selectFileWidget-label { + color: #000000; +} +.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dragdrop-ui .oo-ui-selectFileWidget-handle:hover, +.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dragdrop-ui.oo-ui-selectFileWidget-canDrop .oo-ui-selectFileWidget-handle { + background-color: #eeeeee; +} .oo-ui-outlineOptionWidget { position: relative; cursor: pointer; diff --git a/resources/lib/oojs-ui/oojs-ui-apex.js b/resources/lib/oojs-ui/oojs-ui-apex.js index 085f744fad..6d6d46a4df 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.12.5 + * OOjs UI v0.12.6 * https://www.mediawiki.org/wiki/OOjs_UI * * Copyright 2011–2015 OOjs UI Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2015-08-19T02:10:17Z + * Date: 2015-08-26T00:14:36Z */ /** * @class diff --git a/resources/lib/oojs-ui/oojs-ui-mediawiki-noimages.css b/resources/lib/oojs-ui/oojs-ui-mediawiki-noimages.css index 41d06ff1ae..f23902a593 100644 --- a/resources/lib/oojs-ui/oojs-ui-mediawiki-noimages.css +++ b/resources/lib/oojs-ui/oojs-ui-mediawiki-noimages.css @@ -1,12 +1,12 @@ /*! - * OOjs UI v0.12.5 + * OOjs UI v0.12.6 * https://www.mediawiki.org/wiki/OOjs_UI * * Copyright 2011–2015 OOjs UI Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2015-08-19T02:10:25Z + * Date: 2015-08-26T00:14:44Z */ @-webkit-keyframes oo-ui-progressBarWidget-slide { from { @@ -149,10 +149,10 @@ } .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label, .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:focus > .oo-ui-labelElement-label { - color: #347bff; + color: #2962cc; } .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label { - color: #777777; + color: #347bff; } .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active > .oo-ui-labelElement-label, .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label { @@ -161,10 +161,10 @@ } .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label, .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus > .oo-ui-labelElement-label { - color: #00af89; + color: #008064; } .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label { - color: #777777; + color: #00af89; } .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active > .oo-ui-labelElement-label, .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label { @@ -173,10 +173,10 @@ } .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label, .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus > .oo-ui-labelElement-label { - color: #d11d13; + color: #8c130d; } .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label { - color: #777777; + color: #d11d13; } .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active > .oo-ui-labelElement-label, .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label { @@ -1121,6 +1121,9 @@ background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check.svg"); background-image: linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check.svg"); background-image: -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/check.png"); + background-size: contain; + background-position: center center; + background-repeat: no-repeat; } .oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover { background-color: #eeeeee; @@ -2304,6 +2307,25 @@ .oo-ui-selectFileWidget-notsupported.oo-ui-indicatorElement .oo-ui-selectFileWidget-handle { padding-right: 2em; } +.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dragdrop-ui .oo-ui-selectFileWidget-handle { + height: 3.5em; + border: 1px dashed #cccccc; + border-radius: 0; + padding: 0.5em 1em; + background: #ffffff; + text-align: center; + vertical-align: middle; +} +.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dragdrop-ui .oo-ui-selectFileWidget-handle .oo-ui-iconElement-icon { + margin: 0.6em 0; +} +.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dragdrop-ui .oo-ui-selectFileWidget-handle .oo-ui-selectFileWidget-label { + color: #000000; +} +.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dragdrop-ui .oo-ui-selectFileWidget-handle:hover, +.oo-ui-selectFileWidget.oo-ui-selectFileWidget-dragdrop-ui.oo-ui-selectFileWidget-canDrop .oo-ui-selectFileWidget-handle { + background-color: #eeeeee; +} .oo-ui-outlineOptionWidget { position: relative; cursor: pointer; diff --git a/resources/lib/oojs-ui/oojs-ui-mediawiki.js b/resources/lib/oojs-ui/oojs-ui-mediawiki.js index 7d20dfbde1..ecb210a4f4 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.12.5 + * OOjs UI v0.12.6 * https://www.mediawiki.org/wiki/OOjs_UI * * Copyright 2011–2015 OOjs UI Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2015-08-19T02:10:17Z + * Date: 2015-08-26T00:14:36Z */ /** * @class @@ -57,6 +57,12 @@ OO.ui.MediaWikiTheme.prototype.getElementClasses = function ( element ) { } } + if ( element instanceof OO.ui.SelectFileWidget ) { + if ( !element.isDisabled() && element.active ) { + variants.invert = true; + } + } + for ( variant in variants ) { classes[ variants[ variant ] ? 'on' : 'off' ].push( 'oo-ui-image-' + variant ); } diff --git a/resources/lib/oojs-ui/oojs-ui.js b/resources/lib/oojs-ui/oojs-ui.js index 5344b1ed64..e5f54fcd6b 100644 --- a/resources/lib/oojs-ui/oojs-ui.js +++ b/resources/lib/oojs-ui/oojs-ui.js @@ -1,12 +1,12 @@ /*! - * OOjs UI v0.12.5 + * OOjs UI v0.12.6 * https://www.mediawiki.org/wiki/OOjs_UI * * Copyright 2011–2015 OOjs UI Team and other contributors. * Released under the MIT license * http://oojs.mit-license.org * - * Date: 2015-08-19T02:10:17Z + * Date: 2015-08-26T00:14:36Z */ ( function ( OO ) { @@ -64,10 +64,10 @@ OO.ui.generateElementId = function () { * Inspired from :focusable in jQueryUI v1.11.4 - 2015-04-14 * * @param {jQuery} element Element to test - * @return {Boolean} [description] + * @return {boolean} */ OO.ui.isFocusableElement = function ( $element ) { - var node = $element[0], + var node = $element[ 0 ], nodeName = node.nodeName.toLowerCase(), // Check if the element have tabindex set isInElementGroup = /^(input|select|textarea|button|object)$/.test( nodeName ), @@ -283,6 +283,8 @@ OO.ui.infuse = function ( idOrNode ) { 'ooui-selectfile-not-supported': 'File selection is not supported', // Default placeholder for file selection widgets 'ooui-selectfile-placeholder': 'No file is selected', + // Default placeholder for file selection widgets when using drag drop UI + 'ooui-selectfile-dragdrop-placeholder': 'Drop file here (or click to browse)', // Semicolon separator 'ooui-semicolon-separator': '; ' }; @@ -369,14 +371,14 @@ OO.ui.infuse = function ( idOrNode ) { return true; } - protocol = url.split( ':', 1 )[0] + ':'; + protocol = url.split( ':', 1 )[ 0 ] + ':'; if ( !protocol.match( /^([A-za-z0-9\+\.\-])+:/ ) ) { // Not a valid protocol, safe return true; } // Safe if in the whitelist - return $.inArray( protocol, whitelist ) !== -1; + return whitelist.indexOf( protocol ) !== -1; }; } )(); @@ -1069,8 +1071,7 @@ OO.ui.Element = function OoUiElement( config ) { this.$element = config.$element || $( document.createElement( this.getTagName() ) ); this.elementGroup = null; - this.debouncedUpdateThemeClassesHandler = this.debouncedUpdateThemeClasses.bind( this ); - this.updateThemeClassesPending = false; + this.debouncedUpdateThemeClassesHandler = OO.ui.debounce( this.debouncedUpdateThemeClasses ); // Initialization if ( Array.isArray( config.classes ) ) { @@ -1171,7 +1172,7 @@ OO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) { if ( !$elem.length ) { throw new Error( 'Widget not found: ' + id ); } - data = $elem.data( 'ooui-infused' ) || $elem[0].oouiInfused; + data = $elem.data( 'ooui-infused' ) || $elem[ 0 ].oouiInfused; if ( data ) { // cached! if ( data === true ) { @@ -1248,7 +1249,7 @@ OO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) { // This element is now gone from the DOM, but if anyone is holding a reference to it, // let's allow them to OO.ui.infuse() it and do what they expect (T105828). // Do not use jQuery.data(), as using it on detached nodes leaks memory in 1.x line by design. - $elem[0].oouiInfused = obj; + $elem[ 0 ].oouiInfused = obj; top.resolve(); } obj.$element.data( 'ooui-infused', obj ); @@ -1312,6 +1313,8 @@ OO.ui.Element.static.getDocument = function ( obj ) { */ OO.ui.Element.static.getWindow = function ( obj ) { var doc = this.getDocument( obj ); + // Support: IE 8 + // Standard Document.defaultView is IE9+ return doc.parentWindow || doc.defaultView; }; @@ -1427,9 +1430,13 @@ OO.ui.Element.static.getRelativePosition = function ( $element, $anchor ) { */ OO.ui.Element.static.getBorders = function ( el ) { var doc = el.ownerDocument, + // Support: IE 8 + // Standard Document.defaultView is IE9+ win = doc.parentWindow || doc.defaultView, style = win && win.getComputedStyle ? win.getComputedStyle( el, null ) : + // Support: IE 8 + // Standard getComputedStyle() is IE9+ el.currentStyle, $el = $( el ), top = parseFloat( style ? style.borderTopWidth : $el.css( 'borderTopWidth' ) ) || 0, @@ -1455,6 +1462,8 @@ OO.ui.Element.static.getBorders = function ( el ) { OO.ui.Element.static.getDimensions = function ( el ) { var $el, $win, doc = el.ownerDocument || el.document, + // Support: IE 8 + // Standard Document.defaultView is IE9+ win = doc.parentWindow || doc.defaultView; if ( win === el || el === doc.documentElement ) { @@ -1571,16 +1580,18 @@ OO.ui.Element.static.getClosestScrollableContainer = function ( el, dimension ) * @param {Function} [config.complete] Function to call when scrolling completes */ OO.ui.Element.static.scrollIntoView = function ( el, config ) { + var rel, anim, callback, sc, $sc, eld, scd, $win; + // Configuration initialization config = config || {}; - var rel, anim = {}, - callback = typeof config.complete === 'function' && config.complete, - sc = this.getClosestScrollableContainer( el, config.direction ), - $sc = $( sc ), - eld = this.getDimensions( el ), - scd = this.getDimensions( sc ), - $win = $( this.getWindow( el ) ); + anim = {}; + callback = typeof config.complete === 'function' && config.complete; + sc = this.getClosestScrollableContainer( el, config.direction ); + $sc = $( sc ); + eld = this.getDimensions( el ); + scd = this.getDimensions( sc ); + $win = $( this.getWindow( el ) ); // Compute the distances between the edges of el and the edges of the scroll viewport if ( $sc.is( 'html, body' ) ) { @@ -1741,18 +1752,16 @@ OO.ui.Element.prototype.supports = function ( methods ) { * guaranteeing that theme updates do not occur within an element's constructor */ OO.ui.Element.prototype.updateThemeClasses = function () { - if ( !this.updateThemeClassesPending ) { - this.updateThemeClassesPending = true; - setTimeout( this.debouncedUpdateThemeClassesHandler ); - } + this.debouncedUpdateThemeClassesHandler(); }; /** * @private + * @localdoc This method is called directly from the QUnit tests instead of #updateThemeClasses, to + * make them synchronous. */ OO.ui.Element.prototype.debouncedUpdateThemeClasses = function () { OO.ui.theme.updateElementClasses( this ); - this.updateThemeClassesPending = false; }; /** @@ -2709,7 +2718,7 @@ OO.ui.Dialog = function OoUiDialog( config ) { this.actions = new OO.ui.ActionSet(); this.attachedActions = []; this.currentAction = null; - this.onDocumentKeyDownHandler = this.onDocumentKeyDown.bind( this ); + this.onDialogKeyDownHandler = this.onDialogKeyDown.bind( this ); // Events this.actions.connect( this, { @@ -2792,7 +2801,7 @@ OO.ui.Dialog.static.escapable = true; * @private * @param {jQuery.Event} e Key down event */ -OO.ui.Dialog.prototype.onDocumentKeyDown = function ( e ) { +OO.ui.Dialog.prototype.onDialogKeyDown = function ( e ) { if ( e.which === OO.ui.Keys.ESCAPE ) { this.close(); e.preventDefault(); @@ -2889,7 +2898,7 @@ OO.ui.Dialog.prototype.getSetupProcess = function ( data ) { this.actions.add( this.getActionWidgets( actions ) ); if ( this.constructor.static.escapable ) { - this.$document.on( 'keydown', this.onDocumentKeyDownHandler ); + this.$element.on( 'keydown', this.onDialogKeyDownHandler ); } }, this ); }; @@ -2902,7 +2911,7 @@ OO.ui.Dialog.prototype.getTeardownProcess = function ( data ) { return OO.ui.Dialog.parent.prototype.getTeardownProcess.call( this, data ) .first( function () { if ( this.constructor.static.escapable ) { - this.$document.off( 'keydown', this.onDocumentKeyDownHandler ); + this.$element.off( 'keydown', this.onDialogKeyDownHandler ); } this.actions.clear(); @@ -2914,10 +2923,12 @@ OO.ui.Dialog.prototype.getTeardownProcess = function ( data ) { * @inheritdoc */ OO.ui.Dialog.prototype.initialize = function () { + var titleId; + // Parent method OO.ui.Dialog.parent.prototype.initialize.call( this ); - var titleId = OO.ui.generateElementId(); + titleId = OO.ui.generateElementId(); // Properties this.title = new OO.ui.LabelWidget( { @@ -3543,12 +3554,14 @@ OO.ui.WindowManager.prototype.clearWindows = function () { * @chainable */ OO.ui.WindowManager.prototype.updateWindowSize = function ( win ) { + var isFullscreen; + // Bypass for non-current, and thus invisible, windows if ( win !== this.currentWindow ) { return; } - var isFullscreen = win.getSize() === 'full'; + isFullscreen = win.getSize() === 'full'; this.$element.toggleClass( 'oo-ui-windowManager-fullscreen', isFullscreen ); this.$element.toggleClass( 'oo-ui-windowManager-floating', !isFullscreen ); @@ -3567,14 +3580,14 @@ OO.ui.WindowManager.prototype.updateWindowSize = function ( win ) { * @chainable */ OO.ui.WindowManager.prototype.toggleGlobalEvents = function ( on ) { - on = on === undefined ? !!this.globalEvents : !!on; - var scrollWidth, bodyMargin, $body = $( this.getElementDocument().body ), // We could have multiple window managers open so only modify // the body css at the bottom of the stack stackDepth = $body.data( 'windowManagerGlobalEvents' ) || 0 ; + on = on === undefined ? !!this.globalEvents : !!on; + if ( on ) { if ( !this.globalEvents ) { $( this.getElementWindow() ).on( { @@ -4087,11 +4100,11 @@ OO.ui.ToolFactory.prototype.extract = function ( collection, used ) { * @constructor */ OO.ui.ToolGroupFactory = function OoUiToolGroupFactory() { + var i, l, defaultClasses; // Parent constructor OO.Factory.call( this ); - var i, l, - defaultClasses = this.constructor.static.getDefaultClasses(); + defaultClasses = this.constructor.static.getDefaultClasses(); // Register default toolgroups for ( i = 0, l = defaultClasses.length; i < l; i++ ) { @@ -4160,9 +4173,17 @@ OO.ui.Theme.prototype.getElementClasses = function ( /* element */ ) { * @return {Object.} Categorized class names with `on` and `off` lists */ OO.ui.Theme.prototype.updateElementClasses = function ( element ) { - var classes = this.getElementClasses( element ); + var $elements = $( [] ), + classes = this.getElementClasses( element ); + + if ( element.$icon ) { + $elements = $elements.add( element.$icon ); + } + if ( element.$indicator ) { + $elements = $elements.add( element.$indicator ); + } - element.$element + $elements .removeClass( classes.off.join( ' ' ) ) .addClass( classes.on.join( ' ' ) ); }; @@ -4277,7 +4298,8 @@ OO.ui.mixin.TabIndexedElement.prototype.updateTabIndex = function () { // Do not index over disabled elements this.$tabIndexed.attr( { tabindex: this.isDisabled() ? -1 : this.tabIndex, - // ChromeVox and NVDA do not seem to inherit this from parent elements + // Support: ChromeVox and NVDA + // These do not seem to inherit aria-disabled from parent elements 'aria-disabled': this.isDisabled().toString() } ); } else { @@ -4320,7 +4342,6 @@ OO.ui.mixin.TabIndexedElement.prototype.getTabIndex = function () { * @cfg {jQuery} [$button] The button element created by the class. * If this configuration is omitted, the button element will use a generated ``. * @cfg {boolean} [framed=true] Render the button with a frame - * @cfg {string} [accessKey] Button's access key */ OO.ui.mixin.ButtonElement = function OoUiMixinButtonElement( config ) { // Configuration initialization @@ -4329,7 +4350,6 @@ OO.ui.mixin.ButtonElement = function OoUiMixinButtonElement( config ) { // Properties this.$button = null; this.framed = null; - this.accessKey = null; this.active = false; this.onMouseUpHandler = this.onMouseUp.bind( this ); this.onMouseDownHandler = this.onMouseDown.bind( this ); @@ -4341,7 +4361,6 @@ OO.ui.mixin.ButtonElement = function OoUiMixinButtonElement( config ) { // Initialization this.$element.addClass( 'oo-ui-buttonElement' ); this.toggleFramed( config.framed === undefined || config.framed ); - this.setAccessKey( config.accessKey ); this.setButtonElement( config.$button || $( '' ) ); }; @@ -4399,7 +4418,7 @@ OO.ui.mixin.ButtonElement.prototype.setButtonElement = function ( $button ) { this.$button = $button .addClass( 'oo-ui-buttonElement-button' ) - .attr( { role: 'button', accesskey: this.accessKey } ) + .attr( { role: 'button' } ) .on( { mousedown: this.onMouseDownHandler, keydown: this.onKeyDownHandler, @@ -4532,29 +4551,6 @@ OO.ui.mixin.ButtonElement.prototype.toggleFramed = function ( framed ) { return this; }; -/** - * Set the button's access key. - * - * @param {string} accessKey Button's access key, use empty string to remove - * @chainable - */ -OO.ui.mixin.ButtonElement.prototype.setAccessKey = function ( accessKey ) { - accessKey = typeof accessKey === 'string' && accessKey.length ? accessKey : null; - - if ( this.accessKey !== accessKey ) { - if ( this.$button ) { - if ( accessKey !== null ) { - this.$button.attr( 'accesskey', accessKey ); - } else { - this.$button.removeAttr( 'accesskey' ); - } - } - this.accessKey = accessKey; - } - - return this; -}; - /** * Set the button to its 'active' state. * @@ -4716,7 +4712,7 @@ OO.ui.mixin.GroupElement.prototype.aggregate = function ( events ) { item = this.items[ i ]; if ( item.connect && item.disconnect ) { remove = {}; - remove[ itemEvent ] = [ 'emit', this.aggregateItemEvents[itemEvent], item ]; + remove[ itemEvent ] = [ 'emit', this.aggregateItemEvents[ itemEvent ], item ]; item.disconnect( this, remove ); } } @@ -4759,7 +4755,7 @@ OO.ui.mixin.GroupElement.prototype.addItems = function ( items, index ) { item = items[ i ]; // Check if item exists then remove it first, effectively "moving" it - currentIndex = $.inArray( item, this.items ); + currentIndex = this.items.indexOf( item ); if ( currentIndex >= 0 ) { this.removeItems( [ item ] ); // Adjust index to compensate for removal @@ -4808,7 +4804,7 @@ OO.ui.mixin.GroupElement.prototype.removeItems = function ( items ) { // Remove specific items for ( i = 0, len = items.length; i < len; i++ ) { item = items[ i ]; - index = $.inArray( item, this.items ); + index = this.items.indexOf( item ); if ( index !== -1 ) { if ( item.connect && item.disconnect && @@ -4932,13 +4928,13 @@ OO.ui.mixin.DraggableElement.prototype.onDragStart = function ( e ) { // Define drop effect dataTransfer.dropEffect = 'none'; dataTransfer.effectAllowed = 'move'; + // Support: Firefox // We must set up a dataTransfer data property or Firefox seems to // ignore the fact the element is draggable. try { dataTransfer.setData( 'application-x/OOjs-UI-draggable', this.getIndex() ); } catch ( err ) { - // The above is only for firefox. No need to set a catch clause - // if it fails, move on. + // The above is only for Firefox. Move on if it fails. } // Add dragging class this.$element.addClass( 'oo-ui-draggableElement-dragging' ); @@ -5046,8 +5042,8 @@ OO.ui.mixin.DraggableGroupElement = function OoUiMixinDraggableGroupElement( con itemDragEnd: 'onItemDragEnd' } ); this.$element.on( { - dragover: $.proxy( this.onDragOver, this ), - dragleave: $.proxy( this.onDragLeave, this ) + dragover: this.onDragOver.bind( this ), + dragleave: this.onDragLeave.bind( this ) } ); // Initialize @@ -5377,6 +5373,8 @@ OO.ui.mixin.IconElement.prototype.setIconElement = function ( $icon ) { if ( this.iconTitle !== null ) { this.$icon.attr( 'title', this.iconTitle ); } + + this.updateThemeClasses(); }; /** @@ -5546,6 +5544,8 @@ OO.ui.mixin.IndicatorElement.prototype.setIndicatorElement = function ( $indicat if ( this.indicatorTitle !== null ) { this.$indicator.attr( 'title', this.indicatorTitle ); } + + this.updateThemeClasses(); }; /** @@ -6514,12 +6514,21 @@ OO.ui.mixin.TitledElement.prototype.getTitle = function () { * {@link OO.ui.mixin.ClippableElement#clip} to make sure it's still * clipping correctly. * + * The dimensions of #$clippableContainer will be compared to the boundaries of the + * nearest scrollable container. If #$clippableContainer is too tall and/or too wide, + * then #$clippable will be given a fixed reduced height and/or width and will be made + * scrollable. By default, #$clippable and #$clippableContainer are the same element, + * but you can build a static footer by setting #$clippableContainer to an element that contains + * #$clippable and the footer. + * * @abstract * @class * * @constructor * @param {Object} [config] Configuration options - * @cfg {jQuery} [$clippable] Nodes to clip, assigned to #$clippable, omit to use #$element + * @cfg {jQuery} [$clippable] Node to clip, assigned to #$clippable, omit to use #$element + * @cfg {jQuery} [$clippableContainer] Node to keep visible, assigned to #$clippableContainer, + * omit to use #$clippable */ OO.ui.mixin.ClippableElement = function OoUiMixinClippableElement( config ) { // Configuration initialization @@ -6527,18 +6536,22 @@ OO.ui.mixin.ClippableElement = function OoUiMixinClippableElement( config ) { // Properties this.$clippable = null; + this.$clippableContainer = null; this.clipping = false; this.clippedHorizontally = false; this.clippedVertically = false; - this.$clippableContainer = null; + this.$clippableScrollableContainer = null; this.$clippableScroller = null; this.$clippableWindow = null; this.idealWidth = null; this.idealHeight = null; - this.onClippableContainerScrollHandler = this.clip.bind( this ); + this.onClippableScrollHandler = this.clip.bind( this ); this.onClippableWindowResizeHandler = this.clip.bind( this ); // Initialization + if ( config.$clippableContainer ) { + this.setClippableContainer( config.$clippableContainer ); + } this.setClippableElement( config.$clippable || this.$element ); }; @@ -6562,6 +6575,23 @@ OO.ui.mixin.ClippableElement.prototype.setClippableElement = function ( $clippab this.clip(); }; +/** + * Set clippable container. + * + * This is the container that will be measured when deciding whether to clip. When clipping, + * #$clippable will be resized in order to keep the clippable container fully visible. + * + * If the clippable container is unset, #$clippable will be used. + * + * @param {jQuery|null} $clippableContainer Container to keep visible, or null to unset + */ +OO.ui.mixin.ClippableElement.prototype.setClippableContainer = function ( $clippableContainer ) { + this.$clippableContainer = $clippableContainer; + if ( this.$clippable ) { + this.clip(); + } +}; + /** * Toggle clipping. * @@ -6576,13 +6606,13 @@ OO.ui.mixin.ClippableElement.prototype.toggleClipping = function ( clipping ) { if ( this.clipping !== clipping ) { this.clipping = clipping; if ( clipping ) { - this.$clippableContainer = $( this.getClosestScrollableElementContainer() ); + this.$clippableScrollableContainer = $( this.getClosestScrollableElementContainer() ); // If the clippable container is the root, we have to listen to scroll events and check // jQuery.scrollTop on the window because of browser inconsistencies - this.$clippableScroller = this.$clippableContainer.is( 'html, body' ) ? - $( OO.ui.Element.static.getWindow( this.$clippableContainer ) ) : - this.$clippableContainer; - this.$clippableScroller.on( 'scroll', this.onClippableContainerScrollHandler ); + this.$clippableScroller = this.$clippableScrollableContainer.is( 'html, body' ) ? + $( OO.ui.Element.static.getWindow( this.$clippableScrollableContainer ) ) : + this.$clippableScrollableContainer; + this.$clippableScroller.on( 'scroll', this.onClippableScrollHandler ); this.$clippableWindow = $( this.getElementWindow() ) .on( 'resize', this.onClippableWindowResizeHandler ); // Initial clip after visible @@ -6591,8 +6621,8 @@ OO.ui.mixin.ClippableElement.prototype.toggleClipping = function ( clipping ) { this.$clippable.css( { width: '', height: '', overflowX: '', overflowY: '' } ); OO.ui.Element.static.reconsiderScrollbars( this.$clippable[ 0 ] ); - this.$clippableContainer = null; - this.$clippableScroller.off( 'scroll', this.onClippableContainerScrollHandler ); + this.$clippableScrollableContainer = null; + this.$clippableScroller.off( 'scroll', this.onClippableScrollHandler ); this.$clippableScroller = null; this.$clippableWindow.off( 'resize', this.onClippableWindowResizeHandler ); this.$clippableWindow = null; @@ -6665,40 +6695,51 @@ OO.ui.mixin.ClippableElement.prototype.setIdealSize = function ( width, height ) * @chainable */ OO.ui.mixin.ClippableElement.prototype.clip = function () { + var $container, extraHeight, extraWidth, ccOffset, + $scrollableContainer, scOffset, scHeight, scWidth, + ccWidth, scrollerIsWindow, scrollTop, scrollLeft, + desiredWidth, desiredHeight, allotedWidth, allotedHeight, + naturalWidth, naturalHeight, clipWidth, clipHeight, + buffer = 7; // Chosen by fair dice roll + if ( !this.clipping ) { - // this.$clippableContainer and this.$clippableWindow are null, so the below will fail + // this.$clippableScrollableContainer and this.$clippableWindow are null, so the below will fail return this; } - var buffer = 7, // Chosen by fair dice roll - cOffset = this.$clippable.offset(), - $container = this.$clippableContainer.is( 'html, body' ) ? - this.$clippableWindow : this.$clippableContainer, - ccOffset = $container.offset() || { top: 0, left: 0 }, - ccHeight = $container.innerHeight() - buffer, - ccWidth = $container.innerWidth() - buffer, - cWidth = this.$clippable.outerWidth() + buffer, - scrollerIsWindow = this.$clippableScroller[0] === this.$clippableWindow[0], - scrollTop = scrollerIsWindow ? this.$clippableScroller.scrollTop() : 0, - scrollLeft = scrollerIsWindow ? this.$clippableScroller.scrollLeft() : 0, - desiredWidth = cOffset.left < 0 ? - cWidth + cOffset.left : - ( ccOffset.left + scrollLeft + ccWidth ) - cOffset.left, - desiredHeight = ( ccOffset.top + scrollTop + ccHeight ) - cOffset.top, - naturalWidth = this.$clippable.prop( 'scrollWidth' ), - naturalHeight = this.$clippable.prop( 'scrollHeight' ), - clipWidth = desiredWidth < naturalWidth, - clipHeight = desiredHeight < naturalHeight; + $container = this.$clippableContainer || this.$clippable; + extraHeight = $container.outerHeight() - this.$clippable.outerHeight(); + extraWidth = $container.outerWidth() - this.$clippable.outerWidth(); + ccOffset = $container.offset(); + $scrollableContainer = this.$clippableScrollableContainer.is( 'html, body' ) ? + this.$clippableWindow : this.$clippableScrollableContainer; + scOffset = $scrollableContainer.offset() || { top: 0, left: 0 }; + scHeight = $scrollableContainer.innerHeight() - buffer; + scWidth = $scrollableContainer.innerWidth() - buffer; + ccWidth = $container.outerWidth() + buffer; + scrollerIsWindow = this.$clippableScroller[ 0 ] === this.$clippableWindow[ 0 ]; + scrollTop = scrollerIsWindow ? this.$clippableScroller.scrollTop() : 0; + scrollLeft = scrollerIsWindow ? this.$clippableScroller.scrollLeft() : 0; + desiredWidth = ccOffset.left < 0 ? + ccWidth + ccOffset.left : + ( scOffset.left + scrollLeft + scWidth ) - ccOffset.left; + desiredHeight = ( scOffset.top + scrollTop + scHeight ) - ccOffset.top; + allotedWidth = desiredWidth - extraWidth; + allotedHeight = desiredHeight - extraHeight; + naturalWidth = this.$clippable.prop( 'scrollWidth' ); + naturalHeight = this.$clippable.prop( 'scrollHeight' ); + clipWidth = allotedWidth < naturalWidth; + clipHeight = allotedHeight < naturalHeight; if ( clipWidth ) { - this.$clippable.css( { overflowX: 'scroll', width: desiredWidth } ); + this.$clippable.css( { overflowX: 'scroll', width: Math.max( 0, allotedWidth ) } ); } else { - this.$clippable.css( { width: this.idealWidth || '', overflowX: '' } ); + this.$clippable.css( { width: this.idealWidth ? this.idealWidth - extraWidth : '', overflowX: '' } ); } if ( clipHeight ) { - this.$clippable.css( { overflowY: 'scroll', height: desiredHeight } ); + this.$clippable.css( { overflowY: 'scroll', height: Math.max( 0, allotedHeight ) } ); } else { - this.$clippable.css( { height: this.idealHeight || '', overflowY: '' } ); + this.$clippable.css( { height: this.idealHeight ? this.idealHeight - extraHeight : '', overflowY: '' } ); } // If we stopped clipping in at least one of the dimensions @@ -6712,6 +6753,113 @@ OO.ui.mixin.ClippableElement.prototype.clip = function () { return this; }; +/** + * AccessKeyedElement is mixed into other classes to provide an `accesskey` attribute. + * Accesskeys allow an user to go to a specific element by using + * a shortcut combination of a browser specific keys + the key + * set to the field. + * + * @example + * // AccessKeyedElement provides an 'accesskey' attribute to the + * // ButtonWidget class + * var button = new OO.ui.ButtonWidget( { + * label: 'Button with Accesskey', + * accessKey: 'k' + * } ); + * $( 'body' ).append( button.$element ); + * + * @abstract + * @class + * + * @constructor + * @param {Object} [config] Configuration options + * @cfg {jQuery} [$accessKeyed] The element to which the `accesskey` attribute is applied. + * If this config is omitted, the accesskey functionality is applied to $element, the + * element created by the class. + * @cfg {string|Function} [accessKey] The key or a function that returns the key. If + * this config is omitted, no accesskey will be added. + */ +OO.ui.mixin.AccessKeyedElement = function OoUiMixinAccessKeyedElement( config ) { + // Configuration initialization + config = config || {}; + + // Properties + this.$accessKeyed = null; + this.accessKey = null; + + // Initialization + this.setAccessKey( config.accessKey || null ); + this.setAccessKeyedElement( config.$accessKeyed || this.$element ); +}; + +/* Setup */ + +OO.initClass( OO.ui.mixin.AccessKeyedElement ); + +/* Static Properties */ + +/** + * The access key, a function that returns a key, or `null` for no accesskey. + * + * @static + * @inheritable + * @property {string|Function|null} + */ +OO.ui.mixin.AccessKeyedElement.static.accessKey = null; + +/* Methods */ + +/** + * Set the accesskeyed element. + * + * This method is used to retarget a AccessKeyedElement mixin so that its functionality applies to the specified element. + * If an element is already set, the mixin's effect on that element is removed before the new element is set up. + * + * @param {jQuery} $accessKeyed Element that should use the 'accesskeyes' functionality + */ +OO.ui.mixin.AccessKeyedElement.prototype.setAccessKeyedElement = function ( $accessKeyed ) { + if ( this.$accessKeyed ) { + this.$accessKeyed.removeAttr( 'accesskey' ); + } + + this.$accessKeyed = $accessKeyed; + if ( this.accessKey ) { + this.$accessKeyed.attr( 'accesskey', this.accessKey ); + } +}; + +/** + * Set accesskey. + * + * @param {string|Function|null} accesskey Key, a function that returns a key, or `null` for no accesskey + * @chainable + */ +OO.ui.mixin.AccessKeyedElement.prototype.setAccessKey = function ( accessKey ) { + accessKey = typeof accessKey === 'string' ? OO.ui.resolveMsg( accessKey ) : null; + + if ( this.accessKey !== accessKey ) { + if ( this.$accessKeyed ) { + if ( accessKey !== null ) { + this.$accessKeyed.attr( 'accesskey', accessKey ); + } else { + this.$accessKeyed.removeAttr( 'accesskey' ); + } + } + this.accessKey = accessKey; + } + + return this; +}; + +/** + * Get accesskey. + * + * @return {string} accessKey string + */ +OO.ui.mixin.AccessKeyedElement.prototype.getAccessKey = function () { + return this.accessKey; +}; + /** * Tools, together with {@link OO.ui.ToolGroup toolgroups}, constitute {@link OO.ui.Toolbar toolbars}. * Each tool is configured with a static name, title, and icon and is customized with the command to carry @@ -8105,7 +8253,7 @@ OO.ui.MessageDialog.prototype.getReadyProcess = function ( data ) { return action.getFlags().indexOf( 'primary' ) > -1; } ); if ( actions.length > 0 ) { - actions[0].$button.focus(); + actions[ 0 ].$button.focus(); } }, this ); }; @@ -8545,14 +8693,14 @@ OO.ui.ProcessDialog.prototype.showErrors = function ( errors ) { } this.$errorItems = $( items ); if ( recoverable ) { - abilities[this.currentAction] = true; + abilities[ this.currentAction ] = true; // Copy the flags from the first matching action actions = this.actions.get( { actions: this.currentAction } ); if ( actions.length ) { - this.retryButton.clearFlags().setFlags( actions[0].getFlags() ); + this.retryButton.clearFlags().setFlags( actions[ 0 ].getFlags() ); } } else { - abilities[this.currentAction] = false; + abilities[ this.currentAction ] = false; this.actions.setAbilities( abilities ); } if ( warning ) { @@ -8631,6 +8779,8 @@ OO.ui.ProcessDialog.prototype.getTeardownProcess = function ( data ) { * @throws {Error} An error is thrown if no widget is specified */ OO.ui.FieldLayout = function OoUiFieldLayout( fieldWidget, config ) { + var hasInputWidget, div, i; + // Allow passing positional parameters inside the config object if ( OO.isPlainObject( fieldWidget ) && config === undefined ) { config = fieldWidget; @@ -8642,8 +8792,7 @@ OO.ui.FieldLayout = function OoUiFieldLayout( fieldWidget, config ) { throw new Error( 'Widget not found' ); } - var hasInputWidget = fieldWidget.constructor.static.supportsSimpleLabel, - div, i; + hasInputWidget = fieldWidget.constructor.static.supportsSimpleLabel; // Configuration initialization config = $.extend( { align: 'left' }, config ); @@ -8705,10 +8854,10 @@ OO.ui.FieldLayout = function OoUiFieldLayout( fieldWidget, config ) { .append( this.fieldWidget.$element ); for ( i = 0; i < this.notices.length; i++ ) { - this.$messages.append( this.makeMessage( 'notice', this.notices[i] ) ); + this.$messages.append( this.makeMessage( 'notice', this.notices[ i ] ) ); } for ( i = 0; i < this.errors.length; i++ ) { - this.$messages.append( this.makeMessage( 'error', this.errors[i] ) ); + this.$messages.append( this.makeMessage( 'error', this.errors[ i ] ) ); } this.setAlignment( config.align ); @@ -9484,7 +9633,7 @@ OO.ui.BookletLayout.prototype.focusFirstFocusable = function () { } // Find all potentially focusable elements in the item // and check if they are focusable - items[i].$element + items[ i ].$element .find( 'input, select, textarea, button, object' ) /* jshint loopfunc:true */ .each( checkAndFocus ); @@ -9555,7 +9704,7 @@ OO.ui.BookletLayout.prototype.toggleOutline = function ( show ) { OO.ui.BookletLayout.prototype.getClosestPage = function ( page ) { var next, prev, level, pages = this.stackLayout.getItems(), - index = $.inArray( page, pages ); + index = pages.indexOf( page ); if ( index !== -1 ) { next = pages[ index + 1 ]; @@ -9655,7 +9804,7 @@ OO.ui.BookletLayout.prototype.addPages = function ( pages, index ) { if ( Object.prototype.hasOwnProperty.call( this.pages, name ) ) { // Correct the insertion index - currentIndex = $.inArray( this.pages[ name ], stackLayoutPages ); + currentIndex = stackLayoutPages.indexOf( this.pages[ name ] ); if ( currentIndex !== -1 && currentIndex + 1 < index ) { index--; } @@ -10004,7 +10153,7 @@ OO.ui.IndexLayout.prototype.focusFirstFocusable = function () { } // Find all potentially focusable elements in the item // and check if they are focusable - items[i].$element + items[ i ].$element .find( 'input, select, textarea, button, object' ) .each( checkAndFocus ); } @@ -10031,7 +10180,7 @@ OO.ui.IndexLayout.prototype.onTabSelectWidgetSelect = function ( item ) { OO.ui.IndexLayout.prototype.getClosestCard = function ( card ) { var next, prev, level, cards = this.stackLayout.getItems(), - index = $.inArray( card, cards ); + index = cards.indexOf( card ); if ( index !== -1 ) { next = cards[ index + 1 ]; @@ -10116,7 +10265,7 @@ OO.ui.IndexLayout.prototype.addCards = function ( cards, index ) { if ( Object.prototype.hasOwnProperty.call( this.cards, name ) ) { // Correct the insertion index - currentIndex = $.inArray( this.cards[ name ], stackLayoutCards ); + currentIndex = stackLayoutCards.indexOf( this.cards[ name ] ); if ( currentIndex !== -1 && currentIndex + 1 < index ) { index--; } @@ -10725,7 +10874,7 @@ OO.ui.StackLayout.prototype.removeItems = function ( items ) { // Mixin method OO.ui.mixin.GroupElement.prototype.removeItems.call( this, items ); - if ( $.inArray( this.currentItem, items ) !== -1 ) { + if ( items.indexOf( this.currentItem ) !== -1 ) { if ( this.items.length ) { this.setItem( this.items[ 0 ] ); } else { @@ -10765,7 +10914,7 @@ OO.ui.StackLayout.prototype.setItem = function ( item ) { if ( item !== this.currentItem ) { this.updateHiddenState( this.items, item ); - if ( $.inArray( item, this.items ) !== -1 ) { + if ( this.items.indexOf( item ) !== -1 ) { this.currentItem = item; this.emit( 'set', item ); } else { @@ -11335,8 +11484,9 @@ OO.ui.ListToolGroup.prototype.populate = function () { }; OO.ui.ListToolGroup.prototype.getExpandCollapseTool = function () { + var ExpandCollapseTool; if ( this.expandCollapseTool === undefined ) { - var ExpandCollapseTool = function () { + ExpandCollapseTool = function () { ExpandCollapseTool.parent.apply( this, arguments ); }; @@ -11957,8 +12107,8 @@ OO.ui.OutlineControlsWidget.prototype.setAbilities = function ( abilities ) { var ability; for ( ability in this.abilities ) { - if ( abilities[ability] !== undefined ) { - this.abilities[ability] = !!abilities[ability]; + if ( abilities[ ability ] !== undefined ) { + this.abilities[ ability ] = !!abilities[ ability ]; } } @@ -12153,6 +12303,7 @@ OO.mixinClass( OO.ui.ButtonGroupWidget, OO.ui.mixin.GroupElement ); * @mixins OO.ui.mixin.TitledElement * @mixins OO.ui.mixin.FlaggedElement * @mixins OO.ui.mixin.TabIndexedElement + * @mixins OO.ui.mixin.AccessKeyedElement * * @constructor * @param {Object} [config] Configuration options @@ -12175,6 +12326,7 @@ OO.ui.ButtonWidget = function OoUiButtonWidget( config ) { OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$button } ) ); OO.ui.mixin.FlaggedElement.call( this, config ); OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$button } ) ); + OO.ui.mixin.AccessKeyedElement.call( this, $.extend( {}, config, { $accessKeyed: this.$button } ) ); // Properties this.href = null; @@ -12204,6 +12356,7 @@ OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.LabelElement ); OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.TitledElement ); OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.FlaggedElement ); OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.TabIndexedElement ); +OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.AccessKeyedElement ); /* Methods */ @@ -12908,8 +13061,8 @@ OO.ui.CapsuleMultiSelectWidget.prototype.setItemsFromData = function ( datas ) { item = null; for ( j = 0; j < items.length; j++ ) { - if ( items[j].data === data && items[j].label === label ) { - item = items[j]; + if ( items[ j ].data === data && items[ j ].label === label ) { + item = items[ j ]; items.splice( j, 1 ); break; } @@ -12996,7 +13149,7 @@ OO.ui.CapsuleMultiSelectWidget.prototype.addItems = function ( items ) { } else { same = true; for ( i = 0, l = oldItems.length; same && i < l; i++ ) { - same = same && this.items[i] === oldItems[i]; + same = same && this.items[ i ] === oldItems[ i ]; } } if ( !same ) { @@ -13020,7 +13173,7 @@ OO.ui.CapsuleMultiSelectWidget.prototype.removeItems = function ( items ) { } else { same = true; for ( i = 0, l = oldItems.length; same && i < l; i++ ) { - same = same && this.items[i] === oldItems[i]; + same = same && this.items[ i ] === oldItems[ i ]; } } if ( !same ) { @@ -13100,7 +13253,7 @@ OO.ui.CapsuleMultiSelectWidget.prototype.onPopupFocusOut = function () { setTimeout( function () { if ( widget.isVisible() && - !OO.ui.contains( widget.$element[0], document.activeElement, true ) && + !OO.ui.contains( widget.$element[ 0 ], document.activeElement, true ) && ( !widget.$autoCloseIgnore || !widget.$autoCloseIgnore.has( document.activeElement ).length ) ) { widget.toggle( false ); @@ -13247,7 +13400,7 @@ OO.ui.CapsuleMultiSelectWidget.prototype.setDisabled = function ( disabled ) { if ( this.items ) { for ( i = 0, len = this.items.length; i < len; i++ ) { - this.items[i].updateDisabled(); + this.items[ i ].updateDisabled(); } } @@ -13552,16 +13705,21 @@ OO.ui.DropdownWidget.prototype.onKeyPress = function ( e ) { * @cfg {string} [placeholder] Text to display when no file is selected. * @cfg {string} [notsupported] Text to display when file support is missing in the browser. * @cfg {boolean} [droppable=true] Whether to accept files by drag and drop. + * @cfg {boolean} [dragDropUI=false] Whether to render the drag and drop UI. */ OO.ui.SelectFileWidget = function OoUiSelectFileWidget( config ) { - var dragHandler; + var dragHandler, + placeholderMsg = ( config && config.dragDropUI ) ? + 'ooui-selectfile-dragdrop-placeholder' : + 'ooui-selectfile-placeholder'; // Configuration initialization config = $.extend( { accept: null, - placeholder: OO.ui.msg( 'ooui-selectfile-placeholder' ), + placeholder: OO.ui.msg( placeholderMsg ), notsupported: OO.ui.msg( 'ooui-selectfile-not-supported' ), - droppable: true + droppable: true, + dragDropUI: false }, config ); // Parent constructor @@ -13578,6 +13736,8 @@ OO.ui.SelectFileWidget = function OoUiSelectFileWidget( config ) { OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$handle } ) ); // Properties + this.active = false; + this.dragDropUI = config.dragDropUI; this.isSupported = this.constructor.static.isSupported(); this.currentFile = null; if ( Array.isArray( config.accept ) ) { @@ -13624,7 +13784,15 @@ OO.ui.SelectFileWidget = function OoUiSelectFileWidget( config ) { .addClass( 'oo-ui-selectFileWidget' ) .append( this.$handle ); if ( config.droppable ) { - this.$element.addClass( 'oo-ui-selectFileWidget-droppable' ); + if ( config.dragDropUI ) { + this.$element.addClass( 'oo-ui-selectFileWidget-dragdrop-ui' ); + this.$element.on( { + mouseover: this.onMouseOver.bind( this ), + mouseleave: this.onMouseLeave.bind( this ) + } ); + } else { + this.$element.addClass( 'oo-ui-selectFileWidget-droppable' ); + } } }; @@ -13649,7 +13817,7 @@ OO.ui.SelectFileWidget.static.isSupported = function () { var $input; if ( OO.ui.SelectFileWidget.static.isSupportedCache === null ) { $input = $( '' ); - OO.ui.SelectFileWidget.static.isSupportedCache = $input[0].files !== undefined; + OO.ui.SelectFileWidget.static.isSupportedCache = $input[ 0 ].files !== undefined; } return OO.ui.SelectFileWidget.static.isSupportedCache; }; @@ -13758,7 +13926,7 @@ OO.ui.SelectFileWidget.prototype.isFileAcceptable = function ( file ) { mime = file.type; for ( i = 0; i < this.accept.length; i++ ) { - mimeTest = this.accept[i]; + mimeTest = this.accept[ i ]; if ( mimeTest === mime ) { return true; } else if ( mimeTest.substr( -2 ) === '/*' ) { @@ -13781,8 +13949,8 @@ OO.ui.SelectFileWidget.prototype.isFileAcceptable = function ( file ) { OO.ui.SelectFileWidget.prototype.onFileSelected = function ( e ) { var file = null; - if ( e.target.files && e.target.files[0] ) { - file = e.target.files[0]; + if ( e.target.files && e.target.files[ 0 ] ) { + file = e.target.files[ 0 ]; if ( !this.isFileAcceptable( file ) ) { file = null; } @@ -13832,16 +14000,17 @@ OO.ui.SelectFileWidget.prototype.onDragEnterOrOver = function ( e ) { if ( this.isDisabled() || !this.isSupported ) { this.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' ); + this.setActive( false ); dt.dropEffect = 'none'; return false; } - if ( dt && dt.files && dt.files[0] ) { - file = dt.files[0]; + if ( dt && dt.files && dt.files[ 0 ] ) { + file = dt.files[ 0 ]; if ( !this.isFileAcceptable( file ) ) { file = null; } - } else if ( dt && dt.types && $.inArray( 'Files', dt.types ) ) { + } else if ( dt && dt.types && dt.types.indexOf( 'Files' ) !== -1 ) { // We know we have files so set 'file' to something truthy, we just // can't know any details about them. // * https://bugzilla.mozilla.org/show_bug.cgi?id=640534 @@ -13849,8 +14018,10 @@ OO.ui.SelectFileWidget.prototype.onDragEnterOrOver = function ( e ) { } if ( file ) { this.$element.addClass( 'oo-ui-selectFileWidget-canDrop' ); + this.setActive( true ); } else { this.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' ); + this.setActive( false ); dt.dropEffect = 'none'; } @@ -13865,6 +14036,7 @@ OO.ui.SelectFileWidget.prototype.onDragEnterOrOver = function ( e ) { */ OO.ui.SelectFileWidget.prototype.onDragLeave = function () { this.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' ); + this.setActive( false ); }; /** @@ -13880,13 +14052,14 @@ OO.ui.SelectFileWidget.prototype.onDrop = function ( e ) { e.preventDefault(); e.stopPropagation(); this.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' ); + this.setActive( false ); if ( this.isDisabled() || !this.isSupported ) { return false; } - if ( dt && dt.files && dt.files[0] ) { - file = dt.files[0]; + if ( dt && dt.files && dt.files[ 0 ] ) { + file = dt.files[ 0 ]; if ( !this.isFileAcceptable( file ) ) { file = null; } @@ -13898,6 +14071,26 @@ OO.ui.SelectFileWidget.prototype.onDrop = function ( e ) { return false; }; +/** + * Handle mouse over events. + * + * @private + * @param {jQuery.Event} e Mouse over event + */ +OO.ui.SelectFileWidget.prototype.onMouseOver = function () { + this.setActive( true ); +}; + +/** + * Handle mouse leave events. + * + * @private + * @param {jQuery.Event} e Mouse over event + */ +OO.ui.SelectFileWidget.prototype.onMouseLeave = function () { + this.setActive( false ); +}; + /** * @inheritdoc */ @@ -13909,6 +14102,20 @@ OO.ui.SelectFileWidget.prototype.setDisabled = function ( state ) { return this; }; +/** + * Set 'active' (hover) state, only matters for widgets with `dragDropUI: true`. + * + * @param {boolean} value Whether widget is active + * @chainable + */ +OO.ui.SelectFileWidget.prototype.setActive = function ( value ) { + if ( this.dragDropUI ) { + this.active = value; + this.updateThemeClasses(); + } + return this; +}; + /** * IconWidget is a generic widget for {@link OO.ui.mixin.IconElement icons}. In general, IconWidgets should be used with OO.ui.LabelWidget, * which creates a label that identifies the icon’s function. See the [OOjs UI documentation on MediaWiki] [1] @@ -14030,11 +14237,14 @@ OO.ui.IndicatorWidget.static.tagName = 'span'; * @extends OO.ui.Widget * @mixins OO.ui.mixin.FlaggedElement * @mixins OO.ui.mixin.TabIndexedElement + * @mixins OO.ui.mixin.TitledElement + * @mixins OO.ui.mixin.AccessKeyedElement * * @constructor * @param {Object} [config] Configuration options * @cfg {string} [name=''] The value of the input’s HTML `name` attribute. * @cfg {string} [value=''] The value of the input. + * @cfg {string} [accessKey=''] The access key of the input. * @cfg {Function} [inputFilter] The name of an input filter function. Input filters modify the value of an input * before it is accepted. */ @@ -14053,6 +14263,8 @@ OO.ui.InputWidget = function OoUiInputWidget( config ) { // Mixin constructors OO.ui.mixin.FlaggedElement.call( this, config ); OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$input } ) ); + OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$input } ) ); + OO.ui.mixin.AccessKeyedElement.call( this, $.extend( {}, config, { $accessKeyed: this.$input } ) ); // Events this.$input.on( 'keydown mouseup cut paste change input select', this.onEdit.bind( this ) ); @@ -14066,6 +14278,7 @@ OO.ui.InputWidget = function OoUiInputWidget( config ) { .addClass( 'oo-ui-inputWidget' ) .append( this.$input ); this.setValue( config.value ); + this.setAccessKey( config.accessKey ); }; /* Setup */ @@ -14073,6 +14286,8 @@ OO.ui.InputWidget = function OoUiInputWidget( config ) { OO.inheritClass( OO.ui.InputWidget, OO.ui.Widget ); OO.mixinClass( OO.ui.InputWidget, OO.ui.mixin.FlaggedElement ); OO.mixinClass( OO.ui.InputWidget, OO.ui.mixin.TabIndexedElement ); +OO.mixinClass( OO.ui.InputWidget, OO.ui.mixin.TitledElement ); +OO.mixinClass( OO.ui.InputWidget, OO.ui.mixin.AccessKeyedElement ); /* Static Properties */ @@ -14166,6 +14381,30 @@ OO.ui.InputWidget.prototype.setValue = function ( value ) { return this; }; +/** + * Set the input's access key. + * FIXME: This is the same code as in OO.ui.mixin.ButtonElement, maybe find a better place for it? + * + * @param {string} accessKey Input's access key, use empty string to remove + * @chainable + */ +OO.ui.InputWidget.prototype.setAccessKey = function ( accessKey ) { + accessKey = typeof accessKey === 'string' && accessKey.length ? accessKey : null; + + if ( this.accessKey !== accessKey ) { + if ( this.$input ) { + if ( accessKey !== null ) { + this.$input.attr( 'accesskey', accessKey ); + } else { + this.$input.removeAttr( 'accesskey' ); + } + } + this.accessKey = accessKey; + } + + return this; +}; + /** * Clean up incoming value. * @@ -14558,13 +14797,14 @@ OO.ui.CheckboxInputWidget.prototype.restorePreInfuseState = function ( state ) { * @constructor * @param {Object} [config] Configuration options * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: … }` + * @cfg {Object} [dropdown] Configuration options for {@link OO.ui.DropdownWidget DropdownWidget} */ OO.ui.DropdownInputWidget = function OoUiDropdownInputWidget( config ) { // Configuration initialization config = config || {}; // Properties (must be done before parent constructor which calls #setDisabled) - this.dropdownWidget = new OO.ui.DropdownWidget(); + this.dropdownWidget = new OO.ui.DropdownWidget( config.dropdown ); // Parent constructor OO.ui.DropdownInputWidget.parent.call( this, config ); @@ -15254,7 +15494,7 @@ OO.ui.TextInputWidget.prototype.installParentChangeDetector = function () { } // Find topmost node in the tree - topmostNode = this.$element[0]; + topmostNode = this.$element[ 0 ]; while ( topmostNode.parentNode ) { topmostNode = topmostNode.parentNode; } @@ -15288,7 +15528,7 @@ OO.ui.TextInputWidget.prototype.installParentChangeDetector = function () { }; // Create a fake parent and observe it - fakeParentNode = $( '
' ).append( topmostNode )[0]; + fakeParentNode = $( '
' ).append( topmostNode )[ 0 ]; mutationObserver.observe( fakeParentNode, { childList: true } ); } else { // Using the DOMNodeInsertedIntoDocument event is much nicer and less magical, and works for @@ -15402,6 +15642,23 @@ OO.ui.TextInputWidget.prototype.select = function () { return this; }; +/** + * Focus the input and move the cursor to the end. + */ +OO.ui.TextInputWidget.prototype.moveCursorToEnd = function () { + var textRange, + element = this.$input[ 0 ]; + this.focus(); + if ( element.selectionStart !== undefined ) { + element.selectionStart = element.selectionEnd = element.value.length; + } else if ( element.createTextRange ) { + // IE 8 and below + textRange = element.createTextRange(); + textRange.collapse( false ); + textRange.select(); + } +}; + /** * Set the validation pattern. * @@ -15457,8 +15714,10 @@ OO.ui.TextInputWidget.prototype.setValidityFlag = function ( isValid ) { * @return {jQuery.Promise} A promise that resolves to a boolean `true` if the value is valid. */ OO.ui.TextInputWidget.prototype.isValid = function () { + var result; + if ( this.validate instanceof Function ) { - var result = this.validate( this.getValue() ); + result = this.validate( this.getValue() ); if ( $.isFunction( result.promise ) ) { return result.promise(); } else { @@ -15574,6 +15833,7 @@ OO.ui.TextInputWidget.prototype.updateSearchIndicator = function () { * @chainable */ OO.ui.TextInputWidget.prototype.positionLabel = function () { + var after, rtl, property; // Clear old values this.$input // Clear old values if present @@ -15589,9 +15849,9 @@ OO.ui.TextInputWidget.prototype.positionLabel = function () { return; } - var after = this.labelPosition === 'after', - rtl = this.$element.css( 'direction' ) === 'rtl', - property = after === rtl ? 'padding-left' : 'padding-right'; + after = this.labelPosition === 'after'; + rtl = this.$element.css( 'direction' ) === 'rtl'; + property = after === rtl ? 'padding-left' : 'padding-right'; this.$input.css( property, this.$label.outerWidth( true ) ); @@ -16194,6 +16454,7 @@ OO.mixinClass( OO.ui.DecoratedOptionWidget, OO.ui.mixin.IndicatorElement ); * @extends OO.ui.DecoratedOptionWidget * @mixins OO.ui.mixin.ButtonElement * @mixins OO.ui.mixin.TabIndexedElement + * @mixins OO.ui.mixin.TitledElement * * @constructor * @param {Object} [config] Configuration options @@ -16207,6 +16468,7 @@ OO.ui.ButtonOptionWidget = function OoUiButtonOptionWidget( config ) { // Mixin constructors OO.ui.mixin.ButtonElement.call( this, config ); + OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$button } ) ); OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$button, tabIndex: -1 @@ -16222,6 +16484,7 @@ OO.ui.ButtonOptionWidget = function OoUiButtonOptionWidget( config ) { OO.inheritClass( OO.ui.ButtonOptionWidget, OO.ui.DecoratedOptionWidget ); OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.ButtonElement ); +OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.TitledElement ); OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.TabIndexedElement ); /* Static Properties */ @@ -16626,6 +16889,7 @@ OO.ui.TabOptionWidget.static.highlightable = false; * [3]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Popups#containerExample * @cfg {number} [containerPadding=10] Padding between the popup and its container, specified as a number of pixels. * @cfg {jQuery} [$content] Content to append to the popup's body + * @cfg {jQuery} [$footer] Content to append to the popup's footer * @cfg {boolean} [autoClose=false] Automatically close the popup when it loses focus. * @cfg {jQuery} [$autoCloseIgnore] Elements that will not close the popup when clicked. * This config option is only relevant if #autoClose is set to `true`. See the [OOjs UI docs on MediaWiki][2] @@ -16644,14 +16908,18 @@ OO.ui.PopupWidget = function OoUiPopupWidget( config ) { // Properties (must be set before ClippableElement constructor call) this.$body = $( '
' ); + this.$popup = $( '
' ); // Mixin constructors OO.ui.mixin.LabelElement.call( this, config ); - OO.ui.mixin.ClippableElement.call( this, $.extend( {}, config, { $clippable: this.$body } ) ); + OO.ui.mixin.ClippableElement.call( this, $.extend( {}, config, { + $clippable: this.$body, + $clippableContainer: this.$popup + } ) ); // Properties - this.$popup = $( '
' ); this.$head = $( '
' ); + this.$footer = $( '
' ); this.$anchor = $( '
' ); // If undefined, will be computed lazily in updateDimensions() this.$container = config.$container; @@ -16677,12 +16945,16 @@ OO.ui.PopupWidget = function OoUiPopupWidget( config ) { this.$head .addClass( 'oo-ui-popupWidget-head' ) .append( this.$label, this.closeButton.$element ); + this.$footer.addClass( 'oo-ui-popupWidget-footer' ); if ( !config.head ) { this.$head.addClass( 'oo-ui-element-hidden' ); } + if ( !config.$footer ) { + this.$footer.addClass( 'oo-ui-element-hidden' ); + } this.$popup .addClass( 'oo-ui-popupWidget-popup' ) - .append( this.$head, this.$body ); + .append( this.$head, this.$body, this.$footer ); this.$element .addClass( 'oo-ui-popupWidget' ) .append( this.$popup, this.$anchor ); @@ -16690,6 +16962,9 @@ OO.ui.PopupWidget = function OoUiPopupWidget( config ) { if ( config.$content instanceof jQuery ) { this.$body.append( config.$content ); } + if ( config.$footer instanceof jQuery ) { + this.$footer.append( config.$footer ); + } if ( config.padded ) { this.$body.addClass( 'oo-ui-popupWidget-body-padded' ); } @@ -16821,9 +17096,10 @@ OO.ui.PopupWidget.prototype.hasAnchor = function () { * @inheritdoc */ OO.ui.PopupWidget.prototype.toggle = function ( show ) { + var change; show = show === undefined ? !this.isVisible() : !!show; - var change = show !== this.isVisible(); + change = show !== this.isVisible(); // Parent method OO.ui.PopupWidget.parent.prototype.toggle.call( this, show ); @@ -17778,7 +18054,7 @@ OO.ui.SelectWidget.prototype.getItemFromLabel = function ( label, prefix ) { filter = this.getItemMatcher( label, true ); for ( i = 0; i < len; i++ ) { - item = this.items[i]; + item = this.items[ i ]; if ( item instanceof OO.ui.OptionWidget && item.isSelectable() && filter( item ) ) { return item; } @@ -17788,7 +18064,7 @@ OO.ui.SelectWidget.prototype.getItemFromLabel = function ( label, prefix ) { found = null; filter = this.getItemMatcher( label, false ); for ( i = 0; i < len; i++ ) { - item = this.items[i]; + item = this.items[ i ]; if ( item instanceof OO.ui.OptionWidget && item.isSelectable() && filter( item ) ) { if ( found ) { return null; @@ -17935,7 +18211,7 @@ OO.ui.SelectWidget.prototype.getRelativeSelectableItem = function ( item, direct } if ( item instanceof OO.ui.OptionWidget ) { - currentIndex = $.inArray( item, this.items ); + currentIndex = this.items.indexOf( item ); nextIndex = ( currentIndex + increase + len ) % len; } else { // If no item is selected and moving forward, start at the beginning. @@ -18305,7 +18581,7 @@ OO.ui.MenuSelectWidget.prototype.updateItemVisibility = function () { filter = showAll ? null : this.getItemMatcher( this.$input.val() ); for ( i = 0; i < len; i++ ) { - item = this.items[i]; + item = this.items[ i ]; if ( item instanceof OO.ui.OptionWidget ) { item.toggle( showAll || filter( item ) ); } @@ -18440,10 +18716,10 @@ OO.ui.MenuSelectWidget.prototype.clearItems = function () { * @inheritdoc */ OO.ui.MenuSelectWidget.prototype.toggle = function ( visible ) { - visible = ( visible === undefined ? !this.visible : !!visible ) && !!this.items.length; + var i, len, change; - var i, len, - change = visible !== this.isVisible(); + visible = ( visible === undefined ? !this.visible : !!visible ) && !!this.items.length; + change = visible !== this.isVisible(); // Parent method OO.ui.MenuSelectWidget.parent.prototype.toggle.call( this, visible ); @@ -18543,9 +18819,10 @@ OO.ui.FloatingMenuSelectWidget.prototype.onWindowResize = function () { * @inheritdoc */ OO.ui.FloatingMenuSelectWidget.prototype.toggle = function ( visible ) { + var change; visible = visible === undefined ? !this.isVisible() : !!visible; - var change = visible !== this.isVisible(); + change = visible !== this.isVisible(); if ( change && visible ) { // Make sure the width is set before the parent method runs. diff --git a/resources/lib/oojs-ui/themes/apex/icons-editing-advanced.json b/resources/lib/oojs-ui/themes/apex/icons-editing-advanced.json index 8fdc5051f9..f7b38628bc 100644 --- a/resources/lib/oojs-ui/themes/apex/icons-editing-advanced.json +++ b/resources/lib/oojs-ui/themes/apex/icons-editing-advanced.json @@ -5,6 +5,10 @@ "alignCentre": { "file": "images/icons/align-center.svg" }, "alignLeft": { "file": "images/icons/align-float-left.svg" }, "alignRight": { "file": "images/icons/align-float-right.svg" }, + "calendar": { "file": { + "ltr": "images/icons/calendar-ltr.svg", + "rtl": "images/icons/calendar-rtl.svg" + } }, "find": { "file": { "ltr": "images/icons/find-ltr.svg", "rtl": "images/icons/find-rtl.svg" diff --git a/resources/lib/oojs-ui/themes/apex/icons.json b/resources/lib/oojs-ui/themes/apex/icons.json index 2c5f858063..92791d66f6 100644 --- a/resources/lib/oojs-ui/themes/apex/icons.json +++ b/resources/lib/oojs-ui/themes/apex/icons.json @@ -2,12 +2,12 @@ "prefix": "oo-ui-icon", "intro": "@import '../../../../src/styles/common';", "images": { - "circle": { "file": "images/icons/circle.svg" }, "add": { "file": "images/icons/add.svg" }, "advanced": { "file": "images/icons/advanced.svg" }, - "cancel": { "file": "images/icons/cancel.svg" }, "alert": { "file": "images/icons/alert.svg" }, + "cancel": { "file": "images/icons/cancel.svg" }, "check": { "file": "images/icons/check.svg" }, + "circle": { "file": "images/icons/circle.svg" }, "close": { "file": "images/icons/close.svg" }, "code": { "file": "images/icons/code.svg" }, "collapse": { "file": "images/icons/collapse.svg" }, diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/calendar-ltr.png b/resources/lib/oojs-ui/themes/apex/images/icons/calendar-ltr.png new file mode 100644 index 0000000000000000000000000000000000000000..8b3ed72fc0047ac7267a9fbf1f6674b91da7c7e9 GIT binary patch literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEX7WqAsj$Z!;#Vf4nJ za0`PlBg3pYARXnNE{-7{oo}Z&@;MlYxXh0#JsrxDUTApNdSP4xYd71{RY?!`Khan7 zP5-2x>G(r6_({Y81}l{XY*EjPSWOytm7krW?vi`%Q>jzQbE(vMyz`2lyymS~QY)(J zthMXOk + + + diff --git a/resources/lib/oojs-ui/themes/apex/images/icons/calendar-rtl.png b/resources/lib/oojs-ui/themes/apex/images/icons/calendar-rtl.png new file mode 100644 index 0000000000000000000000000000000000000000..8ec5023b97efe9c2dfe85b510923268ced0964e2 GIT binary patch literal 216 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEX7WqAsj$Z!;#Vf4nJ za0`PlBg3pYARSenE{-7{oo}b?=4~+GVeR*4t~GOHa!WLv!g)hq*uk+SXvUufj!#s? zrwPyh)aCGS`j-Yao(<{K#B=$354?$yYS7%Ye+BEoM`!L-a+`44GE7zAurp-Je82WV zpuX!DE!9N|^SeC?|1rcBv2xvLFm;;{d`$1XQ + + + diff --git a/resources/lib/oojs-ui/themes/mediawiki/icons-editing-advanced.json b/resources/lib/oojs-ui/themes/mediawiki/icons-editing-advanced.json index 0e1a8a1040..ef368c23fc 100644 --- a/resources/lib/oojs-ui/themes/mediawiki/icons-editing-advanced.json +++ b/resources/lib/oojs-ui/themes/mediawiki/icons-editing-advanced.json @@ -11,6 +11,10 @@ "alignCentre": { "file": "images/icons/align-center.svg" }, "alignLeft": { "file": "images/icons/align-float-left.svg" }, "alignRight": { "file": "images/icons/align-float-right.svg" }, + "calendar": { "file": { + "ltr": "images/icons/calendar-ltr.svg", + "rtl": "images/icons/calendar-rtl.svg" + } }, "find": { "file": { "ltr": "images/icons/find-ltr.svg", "rtl": "images/icons/find-rtl.svg" diff --git a/resources/lib/oojs-ui/themes/mediawiki/icons.json b/resources/lib/oojs-ui/themes/mediawiki/icons.json index f351b5b697..a79b329539 100644 --- a/resources/lib/oojs-ui/themes/mediawiki/icons.json +++ b/resources/lib/oojs-ui/themes/mediawiki/icons.json @@ -1,6 +1,6 @@ { "selectorWithoutVariant": ".oo-ui-icon-{name}", - "selectorWithVariant": ".oo-ui-image-{variant} .oo-ui-icon-{name}, .oo-ui-image-{variant}.oo-ui-icon-{name}", + "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}", "intro": "@import '../../../../src/styles/common';", "variants": { "invert": { diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr-invert.png b/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr-invert.png new file mode 100644 index 0000000000000000000000000000000000000000..330a53d3ec260368d3ee8435c5be32074f03ff3b GIT binary patch literal 255 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEX7WqAsj$Z!;#Vf4nJ za0`PlBg3pYARP-mT^vI^I^Ry&$jf9Xz*3$o6tsf%BDbtS5SOIr1+I8j*F7Hj{ZHbn zKF%>nnD}6#UPR + + + diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr.png b/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr.png new file mode 100644 index 0000000000000000000000000000000000000000..8b3ed72fc0047ac7267a9fbf1f6674b91da7c7e9 GIT binary patch literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEX7WqAsj$Z!;#Vf4nJ za0`PlBg3pYARXnNE{-7{oo}Z&@;MlYxXh0#JsrxDUTApNdSP4xYd71{RY?!`Khan7 zP5-2x>G(r6_({Y81}l{XY*EjPSWOytm7krW?vi`%Q>jzQbE(vMyz`2lyymS~QY)(J zthMXOk + + + diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.png b/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.png new file mode 100644 index 0000000000000000000000000000000000000000..2f9c5baf0da8a84b108b2931e9dfa3f26c0b8501 GIT binary patch literal 239 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEX7WqAsj$Z!;#Vf4nJ za0`PlBg3pYARQAuT^vI^I^Ry&%gbaa(k#26@t>JvlXUCGj0?I2%xMg_MP4lNXeqGI z6!>X%`sC;CZie3fhre|`aWJY?AS6pJ1KmFtm)woyk3~$6U z7#vQ7gw#FaapK4?wr9(^y0dH5C9Pkl@bP0l+XkK21!<6 literal 0 HcmV?d00001 diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.svg b/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.svg new file mode 100644 index 0000000000..f7202a98d2 --- /dev/null +++ b/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.svg @@ -0,0 +1,4 @@ + + + + diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl.png b/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl.png new file mode 100644 index 0000000000000000000000000000000000000000..8ec5023b97efe9c2dfe85b510923268ced0964e2 GIT binary patch literal 216 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEX7WqAsj$Z!;#Vf4nJ za0`PlBg3pYARSenE{-7{oo}b?=4~+GVeR*4t~GOHa!WLv!g)hq*uk+SXvUufj!#s? zrwPyh)aCGS`j-Yao(<{K#B=$354?$yYS7%Ye+BEoM`!L-a+`44GE7zAurp-Je82WV zpuX!DE!9N|^SeC?|1rcBv2xvLFm;;{d`$1XQ + + + diff --git a/resources/lib/oojs-ui/themes/mediawiki/indicators.json b/resources/lib/oojs-ui/themes/mediawiki/indicators.json index 3d66337c67..5a8325855c 100644 --- a/resources/lib/oojs-ui/themes/mediawiki/indicators.json +++ b/resources/lib/oojs-ui/themes/mediawiki/indicators.json @@ -1,6 +1,6 @@ { "selectorWithoutVariant": ".oo-ui-indicator-{name}", - "selectorWithVariant": ".oo-ui-image-{variant} .oo-ui-indicator-{name}, .oo-ui-image-{variant}.oo-ui-indicator-{name}", + "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-indicator-{name}", "intro": "@import '../../../../src/styles/common';", "variants": { "invert": { -- 2.20.1