Bmansurov has uploaded a new change for review.
https://gerrit.wikimedia.org/r/277829
Change subject: Promot structured language overlay to stable
......................................................................
Promot structured language overlay to stable
Also:
* Remove the simpler language overlay.
* Rename the structured overlay to just overlay.
Bug: T129274
Change-Id: Iaecb838417fdd312dd08c4c54ba7bbdf34c3f1f7
---
M extension.json
M i18n/en.json
M i18n/qqq.json
D resources/mobile.languages.structured/LanguageOverlay.hogan
D resources/mobile.languages.structured/LanguageOverlay.js
M resources/mobile.languages/LanguageOverlay.hogan
M resources/mobile.languages/LanguageOverlay.js
R resources/mobile.languages/LanguageOverlay.less
R resources/mobile.languages/magnifying-glass.svg
R resources/mobile.languages/util.js
M resources/skins.minerva.scripts/init.js
M tests/qunit/mobile.languages.structured/test_LanguageOverlay.js
M tests/qunit/mobile.languages.structured/test_util.js
D tests/qunit/mobile.languages/test_LanguageOverlay.js
14 files changed, 200 insertions(+), 600 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/MobileFrontend
refs/changes/29/277829/1
diff --git a/extension.json b/extension.json
index 6c8e485..3b1c898 100644
--- a/extension.json
+++ b/extension.json
@@ -1180,46 +1180,24 @@
"mobile.languages": {
"class": "MFResourceLoaderParsedMessageModule",
"dependencies": [
- "mobile.overlays",
- "mobile.settings",
- "mobile.browser"
- ],
- "scripts": [
- "resources/mobile.languages/LanguageOverlay.js"
- ],
- "templates": {
- "LanguageOverlay.hogan":
"resources/mobile.languages/LanguageOverlay.hogan"
- },
- "messages": {
- "0": "mobile-frontend-language-heading",
- "1": "mobile-frontend-language-header",
- "mobile-frontend-language-variant-header": [
- "parse"
- ],
- "2": "mobile-frontend-language-site-choose"
- }
- },
- "mobile.languages.structured": {
- "class": "MFResourceLoaderParsedMessageModule",
- "dependencies": [
"mediawiki.storage",
"mobile.overlays"
],
"scripts": [
- "resources/mobile.languages.structured/util.js",
-
"resources/mobile.languages.structured/LanguageOverlay.js"
+ "resources/mobile.languages/util.js",
+ "resources/mobile.languages/LanguageOverlay.js"
],
"styles": [
-
"resources/mobile.languages.structured/LanguageOverlay.less"
+
"resources/mobile.languages/LanguageOverlay.less"
],
"templates": {
- "LanguageOverlay.hogan":
"resources/mobile.languages.structured/LanguageOverlay.hogan"
+ "LanguageOverlay.hogan":
"resources/mobile.languages/LanguageOverlay.hogan"
},
"messages": [
"mobile-frontend-language-heading",
-
"mobile-frontend-languages-structured-overlay-preferred-languages-header",
-
"mobile-frontend-languages-structured-overlay-all-languages-header",
-
"mobile-frontend-languages-structured-overlay-search-input-placeholder"
+
"mobile-frontend-languages-overlay-preferred-languages-header",
+
"mobile-frontend-languages-overlay-all-languages-header",
+
"mobile-frontend-languages-overlay-search-input-placeholder"
]
},
"mobile.issues": {
@@ -1966,28 +1944,6 @@
"buckets": {
"control": 0.97,
"A": 0.03
- }
- },
- "@languageOverlay": "controls which language overlay
shows in stable",
- "languageOverlay": {
- "name": "languageOverlay",
- "enabled": false,
- "buckets": {
- "@control": "the ratio of users that
see the simpler overlay",
- "control": 1,
- "@A": "the ratio of users that see the
structured overlay",
- "A": 0
- }
- },
- "@languageOverlayBeta": "controls which language
overlay shows in beta",
- "languageOverlayBeta": {
- "name": "languageOverlayBeta",
- "enabled": false,
- "buckets": {
- "@control": "the ratio of users that
see the simpler overlay",
- "control": 1,
- "@A": "the ratio of users that see the
structured overlay",
- "A": 0
}
},
"_merge_strategy": "array_plus_2d"
diff --git a/i18n/en.json b/i18n/en.json
index 20c22c8..df35d0f 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -177,10 +177,7 @@
"mobile-frontend-image-uploading": "'''Uploading''' image...",
"mobile-frontend-images-status": "Images",
"mobile-frontend-language-article-heading": "Read in another language",
- "mobile-frontend-language-header": "This page is available in $1
{{PLURAL:$1|language|languages}}",
"mobile-frontend-language-heading": "<strong>Languages</strong>",
- "mobile-frontend-language-site-choose": "Search language",
- "mobile-frontend-language-variant-header": "Choose
{{#language:{{CONTENTLANG}}}} variant",
"mobile-frontend-languages-404-desc": "A valid title must be
specified.",
"mobile-frontend-languages-404-title": "Languages error",
"mobile-frontend-languages-header": "Languages",
@@ -188,9 +185,9 @@
"mobile-frontend-languages-nonexistent-title": "The page \"$1\" does
not exist.",
"mobile-frontend-languages-text": "$1 is available in $2
{{PLURAL:$2|language|languages}}.",
"mobile-frontend-languages-variant-header":
"{{#language:{{CONTENTLANG}}}} variants",
-
"mobile-frontend-languages-structured-overlay-preferred-languages-header":
"Preferred languages",
- "mobile-frontend-languages-structured-overlay-all-languages-header":
"All languages",
-
"mobile-frontend-languages-structured-overlay-search-input-placeholder":
"Search for a language",
+ "mobile-frontend-languages-overlay-preferred-languages-header":
"Preferred languages",
+ "mobile-frontend-languages-overlay-all-languages-header": "All
languages",
+ "mobile-frontend-languages-overlay-search-input-placeholder": "Search
for a language",
"mobile-frontend-last-modified-date": "Last edited on $1, at $2",
"mobile-frontend-last-modified-days": "Last edited {{PLURAL:$1|$1
day|$1 days}} ago",
"mobile-frontend-last-modified-hours": "Last edited {{PLURAL:$1|$1
hour|$1 hours}} ago",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index b5b999f..27524ae 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -175,10 +175,7 @@
"mobile-frontend-image-uploading": "A message telling the user that an
image is being uploaded.",
"mobile-frontend-images-status": "On settings page label for turning
on/off images.\n{{Identical|Image}}",
"mobile-frontend-language-article-heading": "Button label prompting
reader to read in another language. The button is only visible when at least
one other language is available. Found at bottom of page.",
- "mobile-frontend-language-header": "Header at top of language selection
overlay describing number of languages that it is possible to read the page
in\n* $1 - number of languages",
"mobile-frontend-language-heading": "The title for the list of
languages for a page.\n{{Identical|Language}}",
- "mobile-frontend-language-site-choose": "Header for overlay when click
on language on settings page",
- "mobile-frontend-language-variant-header": "Header at top of language
selection overlay prompting a user to select variant of the current
language.\n\nSee also:\n* {{msg-mw|Mobile-frontend-languages-variant-header}}",
"mobile-frontend-languages-404-desc": "The title for this message is
{{msg-mw|Mobile-frontend-languages-404-title}}.",
"mobile-frontend-languages-404-title": "Used as title for the
description {{msg-mw|Mobile-frontend-languages-404-desc}}.",
"mobile-frontend-languages-header": "{{Identical|Language}}",
@@ -186,9 +183,9 @@
"mobile-frontend-languages-nonexistent-title": "Shown as error message
on [[Special:MobileLanguages]] when the title parameter given does not map to
an existing page.\n\nParameters:\n* $1 - page title",
"mobile-frontend-languages-text": "Parameters:\n* $1 - page title\n* $2
- number of languages\nSee also:\n*
{{msg-mw|Mobile-frontend-languages-header|page title}}",
"mobile-frontend-languages-variant-header": "See also:\n*
{{msg-mw|Mobile-frontend-language-variant-header}}",
-
"mobile-frontend-languages-structured-overlay-preferred-languages-header":
"Title of the preferred languages in the structured language overlay. The text
will be upper-cased with JS and CSS.",
- "mobile-frontend-languages-structured-overlay-all-languages-header":
"Title of all languages in the structured language overlay. The text will be
upper-cased with JS and CSS.",
-
"mobile-frontend-languages-structured-overlay-search-input-placeholder":
"Instructional text for the language overlay search input box",
+ "mobile-frontend-languages-overlay-preferred-languages-header": "Title
of the preferred languages in the structured language overlay. The text will be
upper-cased with JS and CSS.",
+ "mobile-frontend-languages-overlay-all-languages-header": "Title of all
languages in the structured language overlay. The text will be upper-cased with
JS and CSS.",
+ "mobile-frontend-languages-overlay-search-input-placeholder":
"Instructional text for the language overlay search input box",
"mobile-frontend-last-modified-date": "Text that displays the date the
page was last modified. Parameters:\n* $1 - date\n* $2 -
time\n{{Related|Mobile-frontend-last-modified}}",
"mobile-frontend-last-modified-days": "Text displayed on page to show
how long ago the page was updated. Parameters:\n* $1 - number of
days\n{{Related|Mobile-frontend-last-modified}}",
"mobile-frontend-last-modified-hours": "Text displayed on page to show
how long ago the page was updated. Parameters:\n* $1 - number of
hours\n{{Related|Mobile-frontend-last-modified}}",
diff --git a/resources/mobile.languages.structured/LanguageOverlay.hogan
b/resources/mobile.languages.structured/LanguageOverlay.hogan
deleted file mode 100644
index 3537632..0000000
--- a/resources/mobile.languages.structured/LanguageOverlay.hogan
+++ /dev/null
@@ -1,72 +0,0 @@
-<div class="panel">
- <div class="panel-body">
- <input type="search" class="search"
placeholder="{{inputPlaceholder}}">
- </div>
-</div>
-
-<div class="overlay-content-body">
- {{#preferredLanguagesCount}}
- <h3 class="list-header">{{preferredLanguagesHeader}}</h3>
- <ol class="site-link-list preferred-languages">
- {{#preferredLanguages}}
- <li>
- <a href="{{url}}" class="{{lang}}"
hreflang="{{lang}}" lang="{{lang}}">
- <div>
- <span
class="lang">{{lang}}</span>
- </div>
- <div>
- <span
class="langname">{{langname}}</span>
- {{#title}}
- <span
class="title">{{title}}</span>
- {{/title}}
- </div>
- </a>
- </li>
- {{/preferredLanguages}}
- </ol>
- {{/preferredLanguagesCount}}
-
- {{#allLanguagesCount}}
- <h3
class="list-header">{{allLanguagesHeader}}<span>{{allLanguagesCount}}</span></h3>
- <ul class="site-link-list all-languages">
- {{#allLanguages}}
- <li
{{#hasVariants}}class="has-variants"{{/hasVariants}}>
- {{#hasVariants}}<h3
class="list-header">{{variantsHeader}}</h3>{{/hasVariants}}
- {{#url}}{{! this test is important because
variants may exist, but not the parent language }}
- <a href="{{url}}" class="{{lang}}"
hreflang="{{lang}}" lang="{{lang}}">
- <div>
- <span
class="lang">{{lang}}</span>
- </div>
- <div>
- <span
class="langname">{{langname}}</span>
- {{#title}}
- <span
class="title">{{title}}</span>
- {{/title}}
- </div>
- </a>
- {{/url}}
- {{#hasVariants}}
- <ul class="variants">
- {{#variants}}
- <li>
- <a href="{{url}}"
class="{{lang}}" hreflang="{{lang}}" lang="{{lang}}">
- <div>
- <span
class="lang">{{lang}}</span>
- <span
class="variant">{{variant}}</span>
- </div>
- <div>
- <span
class="langname">{{langname}}</span>
-
{{#title}}
-
<span class="title">{{title}}</span>
-
{{/title}}
- </div>
- </a>
- </li>
- {{/variants}}
- </ul>
- {{/hasVariants}}
- </li>
- {{/allLanguages}}
- </ul>
- {{/allLanguagesCount}}
-</div>
diff --git a/resources/mobile.languages.structured/LanguageOverlay.js
b/resources/mobile.languages.structured/LanguageOverlay.js
deleted file mode 100644
index df86106..0000000
--- a/resources/mobile.languages.structured/LanguageOverlay.js
+++ /dev/null
@@ -1,163 +0,0 @@
-( function ( M, $ ) {
-
- var Overlay = M.require( 'mobile.overlays/Overlay' ),
- util = M.require( 'mobile.languages.structured/util' );
-
- /**
- * Overlay displaying a structured list of languages for a page
- *
- * @class LanguageOverlay
- * @extends Overlay
- */
- function LanguageOverlay( options ) {
- var languages;
-
- if ( options.languages && options.languages.length ) {
- languages = util.getStructuredLanguages(
options.languages, util.getFrequentlyUsedLanguages(), options.deviceLanguage );
- options.allLanguages = languages.all;
- options.allLanguagesCount = languages.all.length;
- options.preferredLanguages = languages.preferred;
- options.preferredLanguagesCount =
languages.preferred.length;
- }
-
- Overlay.call( this, options );
- }
-
- OO.mfExtend( LanguageOverlay, Overlay, {
- /** @inheritdoc */
- className: Overlay.prototype.className + ' language-overlay',
- defaults: $.extend( {}, Overlay.prototype.defaults, {
- heading: mw.msg( 'mobile-frontend-language-heading' ),
- inputPlaceholder: mw.msg(
'mobile-frontend-languages-structured-overlay-search-input-placeholder' ),
- // we can't rely on CSS only to uppercase the headings.
See
https://stackoverflow.com/questions/3777443/css-text-transform-not-working-properly-for-turkish-characters
- allLanguagesHeader: mw.msg(
'mobile-frontend-languages-structured-overlay-all-languages-header'
).toLocaleUpperCase(),
- preferredLanguagesHeader: mw.msg(
'mobile-frontend-languages-structured-overlay-preferred-languages-header'
).toLocaleUpperCase()
- } ),
- /** @inheritdoc */
- templatePartials: $.extend( {},
Overlay.prototype.templatePartials, {
- content: mw.template.get(
'mobile.languages.structured', 'LanguageOverlay.hogan' )
- } ),
- /** @inheritdoc */
- events: $.extend( {}, Overlay.prototype.events, {
- 'click a': 'onLinkClick',
- 'input .search': 'onSearchInput'
- } ),
- /** @inheritdoc */
- postRender: function () {
- Overlay.prototype.postRender.apply( this );
-
- // cache
- this.$searchInput = this.$( 'input.search' );
- this.$siteLinksList = this.$( '.site-link-list' );
- this.$languageItems = this.$siteLinksList.find( 'a' );
- this.$subheaders = this.$( 'h3' );
-
- if ( this.options.languageSwitcherSchema ) {
- this.options.languageSwitcherSchema.log( {
- event: 'languageListLoaded',
- languageOverlayVersion:
'structured-overlay',
- languageCount:
this.$languageItems.length
- } );
- }
- },
- /** @inheritdoc */
- onExit: function () {
- if ( this.options.languageSwitcherSchema ) {
- this.options.languageSwitcherSchema.log( {
- event: 'exitModal',
- exitModal: 'dismissed',
- searchInputHasQuery:
this.$searchInput.val().length > 0,
- languageCount:
this.$siteLinksList.children( ':visible' ).length
- } );
- // stop logging when the user decides to close
the modal
- this.options.languageSwitcherSchema.stopLogging
= true;
- }
-
- Overlay.prototype.onExit.apply( this, arguments );
- },
- /**
- * Article link click event handler
- * @param {jQuery.Event} ev
- */
- onLinkClick: function ( ev ) {
- var $link = this.$( ev.currentTarget ),
- lang = $link.attr( 'lang' ),
- searchInputHasQuery =
this.$searchInput.val().length > 0,
- $visibleListItems =
this.$siteLinksList.children( ':visible' ),
- index;
-
- util.saveLanguageUsageCount( lang,
util.getFrequentlyUsedLanguages() );
-
- // find the index of the clicked language in the list
of visible results
- $.each( $visibleListItems, function ( i, item ) {
- index = i + 1;
- if ( $( item ).hasClass( lang ) ) {
- return false;
- }
- } );
-
- if ( this.options.languageSwitcherSchema ) {
- this.options.languageSwitcherSchema.log( {
- event: 'exitModal',
- exitModal: 'tapped-on-result',
- languageTapped: lang,
- positionOfLanguageTapped: index,
- searchInputHasQuery:
searchInputHasQuery,
- languageCount: $visibleListItems.length
- } );
- }
- },
-
- /**
- * Search input handler
- * @param {jQuery.Event} ev Event object.
- */
- onSearchInput: function ( ev ) {
- this.filterLanguages( $( ev.target
).val().toLowerCase() );
-
- // log when the first search character is entered
- if ( this.options.languageSwitcherSchema ) {
- if ( !this.hasFirstSearchBeenLogged ) {
-
this.options.languageSwitcherSchema.log( {
- event: 'startLanguageSearch'
- } );
- this.hasFirstSearchBeenLogged = true;
- }
- }
- },
-
- /**
- * Filter the language list to only show languages that match
the current search term.
- *
- * @param {String} val of search term (lowercase).
- */
- filterLanguages: function ( val ) {
- var filteredList = [];
-
- if ( val && this.options.languages ) {
- $.each( this.options.languages, function ( i,
language ) {
- // search by language code or language
name
- if (
language.langname.toLowerCase().indexOf( val ) > -1 ||
-
language.lang.toLowerCase().indexOf( val ) > -1
- ) {
- filteredList.push(
language.lang );
- }
- } );
-
- this.$languageItems.addClass( 'hidden' );
- if ( filteredList.length ) {
- this.$siteLinksList.find( '.' +
filteredList.join( ',.' ) ).removeClass( 'hidden' );
- }
- this.$siteLinksList.addClass( 'filtered' );
- this.$subheaders.addClass( 'hidden' );
- } else {
- this.$languageItems.removeClass( 'hidden' );
- this.$siteLinksList.removeClass( 'filtered' );
- this.$subheaders.removeClass( 'hidden' );
- }
- }
- } );
-
- M.define( 'mobile.languages.structured/LanguageOverlay',
LanguageOverlay );
-
-}( mw.mobileFrontend, jQuery ) );
diff --git a/resources/mobile.languages/LanguageOverlay.hogan
b/resources/mobile.languages/LanguageOverlay.hogan
index bcc4e05..3537632 100644
--- a/resources/mobile.languages/LanguageOverlay.hogan
+++ b/resources/mobile.languages/LanguageOverlay.hogan
@@ -1,25 +1,72 @@
<div class="panel">
- <input type="search" class="search" placeholder="{{placeholder}}">
+ <div class="panel-body">
+ <input type="search" class="search"
placeholder="{{inputPlaceholder}}">
+ </div>
</div>
-{{#variantHeader}}
-<h3 class="list-header">{{{variantHeader}}}</h3>
-<ul class="site-link-list">
- {{#variants}}
- <li>
- <a href="{{url}}" hreflang="{{lang}}"
lang="{{lang}}">{{langname}}</a>
- </li>
- {{/variants}}
-</ul>
-{{/variantHeader}}
-{{#header}}
-{{#variantHeader}}
-<h3 class="list-header">{{{header}}}</h3>
-{{/variantHeader}}
-<ul class="site-link-list">
- {{#languages}}
- <li>
- <a href="{{url}}" hreflang="{{lang}}"
lang="{{lang}}"><span>{{langname}}</span>{{#title}} | {{title}}{{/title}}</a>
- </li>
- {{/languages}}
-</ul>
-{{/header}}
+
+<div class="overlay-content-body">
+ {{#preferredLanguagesCount}}
+ <h3 class="list-header">{{preferredLanguagesHeader}}</h3>
+ <ol class="site-link-list preferred-languages">
+ {{#preferredLanguages}}
+ <li>
+ <a href="{{url}}" class="{{lang}}"
hreflang="{{lang}}" lang="{{lang}}">
+ <div>
+ <span
class="lang">{{lang}}</span>
+ </div>
+ <div>
+ <span
class="langname">{{langname}}</span>
+ {{#title}}
+ <span
class="title">{{title}}</span>
+ {{/title}}
+ </div>
+ </a>
+ </li>
+ {{/preferredLanguages}}
+ </ol>
+ {{/preferredLanguagesCount}}
+
+ {{#allLanguagesCount}}
+ <h3
class="list-header">{{allLanguagesHeader}}<span>{{allLanguagesCount}}</span></h3>
+ <ul class="site-link-list all-languages">
+ {{#allLanguages}}
+ <li
{{#hasVariants}}class="has-variants"{{/hasVariants}}>
+ {{#hasVariants}}<h3
class="list-header">{{variantsHeader}}</h3>{{/hasVariants}}
+ {{#url}}{{! this test is important because
variants may exist, but not the parent language }}
+ <a href="{{url}}" class="{{lang}}"
hreflang="{{lang}}" lang="{{lang}}">
+ <div>
+ <span
class="lang">{{lang}}</span>
+ </div>
+ <div>
+ <span
class="langname">{{langname}}</span>
+ {{#title}}
+ <span
class="title">{{title}}</span>
+ {{/title}}
+ </div>
+ </a>
+ {{/url}}
+ {{#hasVariants}}
+ <ul class="variants">
+ {{#variants}}
+ <li>
+ <a href="{{url}}"
class="{{lang}}" hreflang="{{lang}}" lang="{{lang}}">
+ <div>
+ <span
class="lang">{{lang}}</span>
+ <span
class="variant">{{variant}}</span>
+ </div>
+ <div>
+ <span
class="langname">{{langname}}</span>
+
{{#title}}
+
<span class="title">{{title}}</span>
+
{{/title}}
+ </div>
+ </a>
+ </li>
+ {{/variants}}
+ </ul>
+ {{/hasVariants}}
+ </li>
+ {{/allLanguages}}
+ </ul>
+ {{/allLanguagesCount}}
+</div>
diff --git a/resources/mobile.languages/LanguageOverlay.js
b/resources/mobile.languages/LanguageOverlay.js
index 376a1e8..c5b0856 100644
--- a/resources/mobile.languages/LanguageOverlay.js
+++ b/resources/mobile.languages/LanguageOverlay.js
@@ -1,161 +1,111 @@
( function ( M, $ ) {
var Overlay = M.require( 'mobile.overlays/Overlay' ),
- settings = M.require( 'mobile.settings/settings' );
+ util = M.require( 'mobile.languages/util' );
/**
- * Overlay displaying list of languages for a page
+ * Overlay displaying a structured list of languages for a page
+ *
* @class LanguageOverlay
* @extends Overlay
*/
function LanguageOverlay( options ) {
- var langMap;
+ var languages;
if ( options.languages && options.languages.length ) {
- options.header = mw.msg(
'mobile-frontend-language-header', options.languages.length );
+ languages = util.getStructuredLanguages(
options.languages, util.getFrequentlyUsedLanguages(), options.deviceLanguage );
+ options.allLanguages = languages.all;
+ options.allLanguagesCount = languages.all.length;
+ options.preferredLanguages = languages.preferred;
+ options.preferredLanguagesCount =
languages.preferred.length;
}
- if ( options.variants && options.variants.length ) {
- options.variantHeader = mw.msg(
'mobile-frontend-language-variant-header' );
- }
- langMap = settings.get( 'langMap' );
- this.languageMap = langMap ? $.parseJSON( langMap ) : {};
- if ( options.currentLanguage ) {
- this.trackLanguage( options.currentLanguage );
- }
- options = this._sortLanguages( options );
- Overlay.apply( this, arguments );
+
+ Overlay.call( this, options );
}
OO.mfExtend( LanguageOverlay, Overlay, {
- /**
- * @inheritdoc
- * @cfg {Object} defaults Default options hash.
- * @cfg {String} defaults.heading The title for the list of
languages for a page.
- * @cfg {String} defaults.placeholder Placeholder text for the
search input.
- * @cfg {Object} defaults.languages a list of languages with
keys {langname, lang, title, url}
- */
+ /** @inheritdoc */
+ className: Overlay.prototype.className + ' language-overlay',
defaults: $.extend( {}, Overlay.prototype.defaults, {
heading: mw.msg( 'mobile-frontend-language-heading' ),
- placeholder: mw.msg(
'mobile-frontend-language-site-choose' )
+ inputPlaceholder: mw.msg(
'mobile-frontend-languages-overlay-search-input-placeholder' ),
+ // we can't rely on CSS only to uppercase the headings.
See
https://stackoverflow.com/questions/3777443/css-text-transform-not-working-properly-for-turkish-characters
+ allLanguagesHeader: mw.msg(
'mobile-frontend-languages-overlay-all-languages-header' ).toLocaleUpperCase(),
+ preferredLanguagesHeader: mw.msg(
'mobile-frontend-languages-overlay-preferred-languages-header'
).toLocaleUpperCase()
} ),
- /**
- * @inheritdoc
- */
- className: 'language-overlay overlay',
- /**
- * @inheritdoc
- */
+ /** @inheritdoc */
templatePartials: $.extend( {},
Overlay.prototype.templatePartials, {
content: mw.template.get( 'mobile.languages',
'LanguageOverlay.hogan' )
} ),
- /**
- * @inheritdoc
- */
+ /** @inheritdoc */
events: $.extend( {}, Overlay.prototype.events, {
- 'click ul a': 'onLinkClick',
+ 'click a': 'onLinkClick',
'input .search': 'onSearchInput'
} ),
/** @inheritdoc */
postRender: function () {
Overlay.prototype.postRender.apply( this );
- this.options.languageSwitcherSchema.log( {
- event: 'languageListLoaded',
- languageOverlayVersion: 'simpler-overlay',
- languageCount: this.$( '.site-link-list li'
).length
- } );
+
+ // cache
+ this.$searchInput = this.$( 'input.search' );
+ this.$siteLinksList = this.$( '.site-link-list' );
+ this.$languageItems = this.$siteLinksList.find( 'a' );
+ this.$subheaders = this.$( 'h3' );
+
+ if ( this.options.languageSwitcherSchema ) {
+ this.options.languageSwitcherSchema.log( {
+ event: 'languageListLoaded',
+ languageOverlayVersion:
'structured-overlay',
+ languageCount:
this.$languageItems.length
+ } );
+ }
},
/** @inheritdoc */
onExit: function () {
- this.options.languageSwitcherSchema.log( {
- event: 'exitModal',
- exitModal: 'dismissed',
- searchInputHasQuery: this.$( 'input.search'
).val().length > 0,
- languageCount: this.$( '.site-link-list'
).children( ':visible' ).length
- } );
- // stop logging when the user decides to close the modal
- this.options.languageSwitcherSchema.stopLogging = true;
+ if ( this.options.languageSwitcherSchema ) {
+ this.options.languageSwitcherSchema.log( {
+ event: 'exitModal',
+ exitModal: 'dismissed',
+ searchInputHasQuery:
this.$searchInput.val().length > 0,
+ languageCount:
this.$siteLinksList.children( ':visible' ).length
+ } );
+ // stop logging when the user decides to close
the modal
+ this.options.languageSwitcherSchema.stopLogging
= true;
+ }
+
Overlay.prototype.onExit.apply( this, arguments );
},
/**
- * Sorts the provided languages based on previous usage and
tags them
- * with a property preferred for template usage
- * @private
- * @param {Object} options
- */
- _sortLanguages: function ( options ) {
- var langMap = this.languageMap;
- options.languages = options.languages.sort( function (
a, b ) {
- var x = langMap[ a.lang ] || 0,
- y = langMap[ b.lang ] || 0;
- if ( x === y ) {
- return a.langname < b.langname ? -1 : 1;
- } else {
- return x > y ? -1 : 1;
- }
- } );
- return options;
- },
- /**
- * Track locally the language of the user for future renders.
- * @param {String} languageCode to track
- */
- trackLanguage: function ( languageCode ) {
- var count,
- langMap = this.languageMap || {};
-
- if ( langMap ) {
- count = langMap[ languageCode ] || 0;
- count += 1;
- // cap at 100 as this is enough data to work on
- langMap[ languageCode ] = count > 100 ? 100 :
count;
- }
-
- this.languageMap = langMap;
- // Attempt to store the map. mw.storage might fail but
it's not essential so we don't care.
- settings.save( 'langMap', JSON.stringify( langMap ) );
- },
-
- /**
- * Filter the language list to only show languages that match
the current search term.
- * @param {String} val of search term (lowercase).
- */
- filterLists: function ( val ) {
- var $items = this.$( '.site-link-list li' ),
- $subheaders = this.$( 'h3' );
-
- if ( val ) {
- $subheaders.hide();
- $items.each( function () {
- var $item = $( this );
- if ( $item.find( 'span'
).text().toLowerCase().indexOf( val ) > -1 ) {
- $item.show();
- } else {
- $item.hide();
- }
- } );
- } else {
- $subheaders.show();
- $items.show();
- }
- },
-
- /**
- * Language link click handler
- * @param {jQuery.Event} ev Event object.
+ * Article link click event handler
+ * @param {jQuery.Event} ev
*/
onLinkClick: function ( ev ) {
var $link = this.$( ev.currentTarget ),
- lang = $link.attr( 'lang' );
+ lang = $link.attr( 'lang' ),
+ searchInputHasQuery =
this.$searchInput.val().length > 0,
+ $visibleListItems =
this.$siteLinksList.children( ':visible' ),
+ index;
- this.options.languageSwitcherSchema.log( {
- event: 'exitModal',
- exitModal: 'tapped-on-result',
- languageTapped: lang,
- positionOfLanguageTapped: $link.parents( 'li'
).index() + 1,
- searchInputHasQuery: this.$( 'input.search'
).val().length > 0,
- languageCount: this.$( '.site-link-list'
).children( ':visible' ).length
+ util.saveLanguageUsageCount( lang,
util.getFrequentlyUsedLanguages() );
+
+ // find the index of the clicked language in the list
of visible results
+ $.each( $visibleListItems, function ( i, item ) {
+ index = i + 1;
+ if ( $( item ).hasClass( lang ) ) {
+ return false;
+ }
} );
- this.trackLanguage( lang );
+
+ if ( this.options.languageSwitcherSchema ) {
+ this.options.languageSwitcherSchema.log( {
+ event: 'exitModal',
+ exitModal: 'tapped-on-result',
+ languageTapped: lang,
+ positionOfLanguageTapped: index,
+ searchInputHasQuery:
searchInputHasQuery,
+ languageCount: $visibleListItems.length
+ } );
+ }
},
/**
@@ -163,14 +113,48 @@
* @param {jQuery.Event} ev Event object.
*/
onSearchInput: function ( ev ) {
+ this.filterLanguages( $( ev.target
).val().toLowerCase() );
+
// log when the first search character is entered
- if ( !this.hasFirstSearchBeenLogged ) {
- this.options.languageSwitcherSchema.log( {
- event: 'startLanguageSearch'
- } );
- this.hasFirstSearchBeenLogged = true;
+ if ( this.options.languageSwitcherSchema ) {
+ if ( !this.hasFirstSearchBeenLogged ) {
+
this.options.languageSwitcherSchema.log( {
+ event: 'startLanguageSearch'
+ } );
+ this.hasFirstSearchBeenLogged = true;
+ }
}
- this.filterLists( $( ev.target ).val().toLowerCase() );
+ },
+
+ /**
+ * Filter the language list to only show languages that match
the current search term.
+ *
+ * @param {String} val of search term (lowercase).
+ */
+ filterLanguages: function ( val ) {
+ var filteredList = [];
+
+ if ( val && this.options.languages ) {
+ $.each( this.options.languages, function ( i,
language ) {
+ // search by language code or language
name
+ if (
language.langname.toLowerCase().indexOf( val ) > -1 ||
+
language.lang.toLowerCase().indexOf( val ) > -1
+ ) {
+ filteredList.push(
language.lang );
+ }
+ } );
+
+ this.$languageItems.addClass( 'hidden' );
+ if ( filteredList.length ) {
+ this.$siteLinksList.find( '.' +
filteredList.join( ',.' ) ).removeClass( 'hidden' );
+ }
+ this.$siteLinksList.addClass( 'filtered' );
+ this.$subheaders.addClass( 'hidden' );
+ } else {
+ this.$languageItems.removeClass( 'hidden' );
+ this.$siteLinksList.removeClass( 'filtered' );
+ this.$subheaders.removeClass( 'hidden' );
+ }
}
} );
diff --git a/resources/mobile.languages.structured/LanguageOverlay.less
b/resources/mobile.languages/LanguageOverlay.less
similarity index 100%
rename from resources/mobile.languages.structured/LanguageOverlay.less
rename to resources/mobile.languages/LanguageOverlay.less
diff --git a/resources/mobile.languages.structured/magnifying-glass.svg
b/resources/mobile.languages/magnifying-glass.svg
similarity index 100%
rename from resources/mobile.languages.structured/magnifying-glass.svg
rename to resources/mobile.languages/magnifying-glass.svg
diff --git a/resources/mobile.languages.structured/util.js
b/resources/mobile.languages/util.js
similarity index 98%
rename from resources/mobile.languages.structured/util.js
rename to resources/mobile.languages/util.js
index c61bb1f..839e98d 100644
--- a/resources/mobile.languages.structured/util.js
+++ b/resources/mobile.languages/util.js
@@ -203,6 +203,6 @@
util.saveFrequentlyUsedLanguages( frequentlyUsedLanguages );
};
- M.define( 'mobile.languages.structured/util', util );
+ M.define( 'mobile.languages/util', util );
}( mw.mobileFrontend, jQuery ) );
diff --git a/resources/skins.minerva.scripts/init.js
b/resources/skins.minerva.scripts/init.js
index 2b6136e..3f220b6 100644
--- a/resources/skins.minerva.scripts/init.js
+++ b/resources/skins.minerva.scripts/init.js
@@ -182,20 +182,12 @@
// Routes
overlayManager.add( /^\/media\/(.+)$/, loadImageOverlay );
overlayManager.add( /^\/languages$/, function () {
- var result = $.Deferred(),
- languageOverlayExperiment = context.isBetaGroupMember()
? experiments.languageOverlayBeta : experiments.languageOverlay,
- languageOverlayModule = 'mobile.languages';
+ var result = $.Deferred();
- if ( languageOverlayExperiment &&
- mw.experiments.getBucket( languageOverlayExperiment,
mw.user.sessionId() ) === 'A'
- ) {
- languageOverlayModule = 'mobile.languages.structured';
- }
-
- loader.loadModule( languageOverlayModule, true ).done( function
( loadingOverlay ) {
+ loader.loadModule( 'mobile.languages', true ).done( function (
loadingOverlay ) {
var PageGateway = M.require(
'mobile.startup/PageGateway' ),
gateway = new PageGateway( new mw.Api() ),
- LanguageOverlay = M.require(
languageOverlayModule + '/LanguageOverlay' );
+ LanguageOverlay = M.require(
'mobile.languages/LanguageOverlay' );
gateway.getPageLanguages( mw.config.get( 'wgPageName' )
).done( function ( data ) {
loadingOverlay.hide();
diff --git a/tests/qunit/mobile.languages.structured/test_LanguageOverlay.js
b/tests/qunit/mobile.languages.structured/test_LanguageOverlay.js
index 6f1c648..ec981fb 100644
--- a/tests/qunit/mobile.languages.structured/test_LanguageOverlay.js
+++ b/tests/qunit/mobile.languages.structured/test_LanguageOverlay.js
@@ -1,5 +1,5 @@
( function ( M ) {
- var LanguageOverlay = M.require(
'mobile.languages.structured/LanguageOverlay' ),
+ var LanguageOverlay = M.require( 'mobile.languages/LanguageOverlay' ),
apiLanguages = [
{
lang: 'ar',
diff --git a/tests/qunit/mobile.languages.structured/test_util.js
b/tests/qunit/mobile.languages.structured/test_util.js
index dd1239b..e9be600 100644
--- a/tests/qunit/mobile.languages.structured/test_util.js
+++ b/tests/qunit/mobile.languages.structured/test_util.js
@@ -1,7 +1,7 @@
( function ( M ) {
- var util = M.require( 'mobile.languages.structured/util' );
+ var util = M.require( 'mobile.languages/util' );
- QUnit.module( 'MobileFrontend: Structured LanguageOverlay', {
+ QUnit.module( 'MobileFrontend: LanguageOverlay', {
setup: function () {
if ( mw.eventLog ) {
this.sandbox.stub(
mw.eventLog.Schema.prototype, 'log' );
diff --git a/tests/qunit/mobile.languages/test_LanguageOverlay.js
b/tests/qunit/mobile.languages/test_LanguageOverlay.js
deleted file mode 100644
index 3e8bf29..0000000
--- a/tests/qunit/mobile.languages/test_LanguageOverlay.js
+++ /dev/null
@@ -1,138 +0,0 @@
-( function ( M, LanguageOverlay ) {
- var settings = M.require( 'mobile.settings/settings' ),
- schemaMobileWebLanguageSwitcher = M.require(
- 'mobile.loggingSchemas/schemaMobileWebLanguageSwitcher'
);
-
- QUnit.module( 'MobileFrontend: LanguageOverlay', {
- setup: function () {
- this.sandbox.stub( settings, 'get' ).withArgs(
'langMap' )
- .returns( '{}' );
- if ( mw.eventLog ) {
- this.sandbox.stub(
mw.eventLog.Schema.prototype, 'log' );
- }
- }
- } );
-
- QUnit.test( 'filterLanguages', 2, function ( assert ) {
- var overlay = new LanguageOverlay( {
- languageSwitcherSchema: schemaMobileWebLanguageSwitcher,
- languages: [
- {
- lang: 'en',
- langname: 'English',
- title: 'The dog',
- url: 'wiki/Dog'
- },
- {
- lang: 'fr',
- langname: 'French',
- title: 'Le chien',
- url: 'wiki/chien'
- },
- {
- lang: 'pt',
- langname: 'Portuguese',
- title: 'O cachorro',
- url: 'wiki/cachorro'
- }
- ]
- } );
- // Needed so we can make use of :visible
- overlay.show();
- overlay.filterLists( 'port' );
- assert.ok( overlay.$( '.site-link-list li' ).eq( 1 ).css(
'display' ) === 'none', 'French should be hidden.' );
- assert.ok( overlay.$( '.site-link-list li' ).eq( 2 ).css(
'display' ) !== 'none', 'Portuguese should be visible.' );
- overlay.hide();
- } );
-
- QUnit.test( 'Preferred Languages', 3, function ( assert ) {
- var overlay = new LanguageOverlay( {
- languageSwitcherSchema:
schemaMobileWebLanguageSwitcher,
- languages: [],
- currentLanguage: 'en'
- } );
- overlay.trackLanguage( 'de' );
- overlay.trackLanguage( 'fr' );
- overlay.trackLanguage( 'fr' );
- assert.strictEqual( overlay.languageMap.en, 1, 'Current
language automatically tracked.' );
- assert.strictEqual( overlay.languageMap.de, 1, 'Saved click on
language link' );
- assert.strictEqual( overlay.languageMap.fr, 2, 'Saved click on
language link' );
- } );
-
- QUnit.module( 'MobileFrontend: LanguageOverlay##_sortLanguages', {
- setup: function () {
- this.sandbox.stub( settings, 'get' ).withArgs(
'langMap' )
- .returns( '{ "es": 3, "za": 100, "fr": 50 }' );
- if ( mw.eventLog ) {
- this.sandbox.stub(
mw.eventLog.Schema.prototype, 'log' );
- }
- }
- } );
-
- QUnit.test( 'Languages get sorted by order', 2, function ( assert ) {
- var languages,
- overlay = new LanguageOverlay( {
- languageSwitcherSchema:
schemaMobileWebLanguageSwitcher,
- languages: [
- {
- lang: 'es'
- },
- {
- lang: 'za'
- },
- {
- lang: 'fr'
- }
- ]
- } );
- languages = overlay.options.languages;
- assert.strictEqual( languages[0].lang, 'za', 'Language with
highest score appears at top' );
- assert.strictEqual( languages[2].lang, 'es', 'Language with
lowest score at bottom' );
- } );
-
- QUnit.test( 'Languages get sorted by order (different scripts)', 7,
function ( assert ) {
- var languages,
- overlay = new LanguageOverlay( {
- languageSwitcherSchema:
schemaMobileWebLanguageSwitcher,
- languages: [
- {
- langname: 'French',
- lang: 'fr'
- },
- {
- langname: 'العربية',
- lang: 'ar'
- },
- {
- langname: 'oʻzbekcha/ўзбекча',
- lang: 'uz'
- },
- {
- langname: 'English',
- lang: 'en'
- },
- {
- langname: 'Deutsch',
- lang: 'de'
- },
- {
- langname: '한국어',
- lang: 'ko'
- },
- {
- langname: 'русский',
- lang: 'ru'
- }
- ]
- } );
- languages = overlay.options.languages;
- assert.strictEqual( languages[0].lang, 'fr', 'Language with
highest score appears at top' );
- assert.strictEqual( languages[1].lang, 'de', 'Alphabetical
order #1' );
- assert.strictEqual( languages[2].lang, 'en', 'Alphabetical
order #2' );
- assert.strictEqual( languages[3].lang, 'uz', 'Alphabetical
order #3' );
- assert.strictEqual( languages[4].lang, 'ru', 'Alphabetical
order #4' );
- assert.strictEqual( languages[5].lang, 'ar', 'Alphabetical
order #5' );
- assert.strictEqual( languages[6].lang, 'ko', 'Alphabetical
order #6' );
- } );
-
-} )( mw.mobileFrontend, mw.mobileFrontend.require(
'mobile.languages/LanguageOverlay' ) );
--
To view, visit https://gerrit.wikimedia.org/r/277829
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iaecb838417fdd312dd08c4c54ba7bbdf34c3f1f7
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: Bmansurov <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits