jenkins-bot has submitted this change and it was merged.
Change subject: Add Possibility to add categories to a page using oojs-ui
......................................................................
Add Possibility to add categories to a page using oojs-ui
Extend CategoryOverlay to add new categories to an article.
Rewrite SearchApi to handle prefixsearch only and provide a possibility
to abort a request. Moved clearSpinner and showSpinner to Overlay, too.
Change-Id: I844787f25f4769cdb6ff899a274763dd75b8046c
---
M i18n/en.json
M i18n/qqq.json
M includes/Resources.php
M javascripts/Overlay.js
A javascripts/modules/categories/CategoryAddOverlay.js
A javascripts/modules/categories/CategoryApi.js
A javascripts/modules/categories/CategoryLookupInputWidget.js
M javascripts/modules/categories/CategoryOverlay.js
M javascripts/modules/categories/init.js
M javascripts/modules/editor/EditorOverlayBase.js
M javascripts/modules/search/SearchApi.js
M javascripts/modules/talk/TalkOverlay.js
M less/Overlay.less
A less/modules/categories/categories.less
A templates/modules/categories/CategoryAddOverlay.hogan
A templates/modules/categories/CategoryAddOverlayHeader.hogan
A templates/modules/categories/CategoryButton.hogan
17 files changed, 516 insertions(+), 83 deletions(-)
Approvals:
Jdlrobson: Looks good to me, approved
jenkins-bot: Verified
diff --git a/i18n/en.json b/i18n/en.json
index c006695..5b3dd90 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -14,6 +14,13 @@
"mobile-frontend-categories-heading": "<strong>Categories</strong>",
"mobile-frontend-categories-subheading": "The page belongs to the
following categories:",
"mobile-frontend-categories-nocat": "This page doesn't belong to any
category, yet.",
+ "mobile-frontend-categories-add": "Add category",
+ "mobile-frontend-categories-search": "Search categories",
+ "mobile-frontend-categories-nomatch": "No category found for your
query. You should try another one.",
+ "mobile-frontend-categories-nodata": "There was an error. Have you
added some categories to save?",
+ "mobile-frontend-categories-summary": "Added categories",
+ "mobile-frontend-categories-add-heading": "<strong>Add new categories
to</strong><span> $1</span>",
+ "mobile-frontend-categories-add-wait": "Saving categories, please
wait.",
"mobile-frontend-changeslist-ip": "Anonymous user",
"mobile-frontend-changeslist-nocomment": "no edit summary",
"mobile-frontend-clear-search": "Clear",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 922475c..cab15a7 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -41,6 +41,13 @@
"mobile-frontend-categories-heading": "Title of the list of categories
this page is categorized in.\n{{Identical|Category}}",
"mobile-frontend-categories-subheading": "Introduction text for the
list of categories, the page belongs to.",
"mobile-frontend-categories-nocat": "Text to inform the user, that the
page doesn't belong to any category.",
+ "mobile-frontend-categories-add": "Button label to add a new category
to the page.",
+ "mobile-frontend-categories-search": "Placeholder text for 'add
category' function.",
+ "mobile-frontend-categories-nomatch": "Messages used to inform the
user, that no categories were found for the search query.",
+ "mobile-frontend-categories-nodata": "Error message to show, that there
aren't categories marked for save with the suggestion to add one.",
+ "mobile-frontend-categories-summary": "Summary text used when new
categories get saved.",
+ "mobile-frontend-categories-add-wait": "Text that displays while
categories are saved.\nSee also {{mw-msg|obile-frontend-editor-wait}}",
+ "mobile-frontend-categories-add-heading": "A heading saying for what
page categories can be added. All text should be wrapped in a STRONG tag except
the page title itself.\n\nParameters:\n* $1 - page title",
"mobile-frontend-changeslist-ip": "Label used in mobile
watchlist/history/recentchanges overview for IP (non-logged-in)
edits.\n{{Identical|Anonymous user}}",
"mobile-frontend-changeslist-nocomment": "Text to mark an empty edit
summary in mobile watchlist/history/recentchanges overview.",
"mobile-frontend-clear-search": "Tooltip for clear button that appears
when you type into search box.\n{{Identical|Clear}}",
diff --git a/includes/Resources.php b/includes/Resources.php
index 75fae5f..0e1da7b 100644
--- a/includes/Resources.php
+++ b/includes/Resources.php
@@ -710,18 +710,40 @@
'mobile.overlays',
'mobile.templates',
'mobile.loggingSchemas',
+ 'mobile.toast',
+ 'mobile.search',
+ // needed for saveHeader.hogan
+ 'mobile.editor.common',
+ 'oojs-ui',
),
'scripts' => array(
+ 'javascripts/modules/categories/CategoryApi.js',
+
'javascripts/modules/categories/CategoryLookupInputWidget.js',
'javascripts/modules/categories/CategoryOverlay.js',
+ 'javascripts/modules/categories/CategoryAddOverlay.js',
'javascripts/modules/categories/init.js',
+ ),
+ 'styles' => array(
+ 'less/modules/categories/categories.less',
),
'templates' => array(
'CategoryOverlay.hogan' =>
'templates/modules/categories/CategoryOverlay.hogan',
+ 'CategoryAddOverlay.hogan' =>
'templates/modules/categories/CategoryAddOverlay.hogan',
+ 'CategoryAddOverlayHeader.hogan' =>
+
'templates/modules/categories/CategoryAddOverlayHeader.hogan',
+ 'CategoryButton.hogan' =>
'templates/modules/categories/CategoryButton.hogan',
),
'messages' => array(
'mobile-frontend-categories-heading',
'mobile-frontend-categories-subheading',
'mobile-frontend-categories-nocat',
+ 'mobile-frontend-categories-add',
+ 'mobile-frontend-categories-nomatch',
+ 'mobile-frontend-categories-search',
+ 'mobile-frontend-categories-nodata',
+ 'mobile-frontend-categories-summary',
+ 'mobile-frontend-categories-add-heading',
+ 'mobile-frontend-categories-add-wait',
),
),
diff --git a/javascripts/Overlay.js b/javascripts/Overlay.js
index 52b876b..cdb80f7 100644
--- a/javascripts/Overlay.js
+++ b/javascripts/Overlay.js
@@ -78,6 +78,22 @@
*/
closeOnContentTap: false,
+ /**
+ * Shows the spinner right to the input field.
+ * @method
+ */
+ showSpinner: function () {
+ this.$spinner.removeClass( 'hidden' );
+ },
+
+ /**
+ * Hide the spinner near to the input field.
+ * @method
+ */
+ clearSpinner: function () {
+ this.$spinner.addClass( 'hidden' );
+ },
+
/** @inheritdoc */
initialize: function ( options ) {
this.isIos = browser.isIos();
@@ -91,6 +107,7 @@
$overlayContent = this.$overlayContent =
this.$( '.overlay-content' ),
startY;
+ this.$spinner = this.$( '.spinner' );
if ( this.isIos ) {
this.$el.addClass( 'overlay-ios' );
}
diff --git a/javascripts/modules/categories/CategoryAddOverlay.js
b/javascripts/modules/categories/CategoryAddOverlay.js
new file mode 100644
index 0000000..d413b4b
--- /dev/null
+++ b/javascripts/modules/categories/CategoryAddOverlay.js
@@ -0,0 +1,144 @@
+( function ( M, $ ) {
+
+ var CategoryAddOverlay,
+ Overlay = M.require( 'Overlay' ),
+ CategoryApi = M.require( 'modules/categories/CategoryApi' ),
+ CategoryLookupInputWidget = M.require(
'modules/categories/CategoryLookupInputWidget' ),
+ icons = M.require( 'icons' ),
+ toast = M.require( 'toast' );
+
+ /**
+ * Displays the list of categories for a page
+ * @class CategoryAddOverlay
+ * @extends Overlay
+ * @uses CategoryApi
+ */
+ CategoryAddOverlay = Overlay.extend( {
+ /**
+ * @inheritdoc
+ * @cfg {Object} defaults Default options hash.
+ * @cfg {String} defaults.waitMsg Text that displays while a
page edit is being saved.
+ * @cfg {String} defaults.waitIcon HTML of the icon that
displays while a page edit
+ * is being saved.
+ */
+ defaults: {
+ headerButtonsListClassName: 'overlay-action',
+ waitMsg: mw.msg( 'mobile-frontend-categories-add-wait'
),
+ waitIcon: icons.spinner( {
+ tagName: 'span'
+ } ).toHtmlString()
+ },
+ /**
+ * @inheritdoc
+ */
+ events: {
+ 'click .save': 'onSaveClick',
+ 'click .suggestion': 'onCategoryClick'
+ },
+ /**
+ * @inheritdoc
+ */
+ className: 'category-overlay overlay',
+ /**
+ * @inheritdoc
+ */
+ template: mw.template.get( 'mobile.categories',
'CategoryAddOverlay.hogan' ),
+ /**
+ * @inheritdoc
+ */
+ templatePartials: {
+ header: mw.template.get( 'mobile.categories',
'CategoryAddOverlayHeader.hogan' ),
+ saveHeader: mw.template.get( 'mobile.editor.common',
'saveHeader.hogan' )
+ },
+
+ /**
+ * @inheritdoc
+ */
+ initialize: function ( options ) {
+ options.heading = mw.msg(
'mobile-frontend-categories-add-heading', options.title );
+ Overlay.prototype.initialize.apply( this, arguments );
+ },
+
+ /**
+ * @inheritdoc
+ */
+ postRender: function ( options ) {
+ var input;
+
+ Overlay.prototype.postRender.apply( this, arguments );
+
+ this.$suggestions = this.$( '.category-suggestions' );
+ this.$saveButton = this.$( '.save' );
+ this.wgCategories = options.categories;
+ this.title = options.title;
+
+ this.api = new CategoryApi();
+ input = new CategoryLookupInputWidget( {
+ api: this.api,
+ suggestions: this.$suggestions,
+ categories: this.wgCategories,
+ saveButton: this.$saveButton
+ } );
+ this.$( '.category-add-input' ).append(
+ input.$element
+ );
+ },
+
+ /**
+ * Handle a click on an added category
+ * @method
+ * @param {jQuery.Event} ev
+ */
+ onCategoryClick: function ( ev ) {
+ $( ev.target ).detach();
+ if ( this.$( '.suggestion.mw-ui-progressive' ).length >
0 ) {
+ this.$saveButton.prop( 'disabled', false );
+ } else {
+ this.$saveButton.prop( 'disabled', true );
+ }
+ },
+
+ /**
+ * Handle the click on the save button. Builds a string of new
categories
+ * and add it to the article.
+ */
+ onSaveClick: function () {
+ var newCategories = '',
+ self = this;
+
+ // show the loading spinner and disable the safe button
+ // FIXME: Don't call a private method that is outside
the class.
+ this._showHidden( '.saving-header' );
+
+ // add wikitext to add to the page
+ $.each( $( '.mw-ui-progressive' ), function () {
+ var data = $( this ).data( 'title' );
+
+ if ( data ) {
+ // add the new categories in wikitext
markup
+ newCategories += '[[' + data + ']] ';
+ }
+ } );
+
+ // if there are no categories added, don't do anything
(the user shouldn't see the save button)
+ if ( newCategories.length === 0 ) {
+ toast.show( mw.msg(
'mobile-frontend-categories-nodata' ), 'toast error' );
+ } else {
+ // save the new categories
+ this.api.save( this.title, newCategories
).done( function () {
+ window.location.hash = '#/categories';
+ window.location.reload();
+ } ).fail( function () {
+ // FIXME: Don't call a private method
that is outside the class.
+ self._showHidden( '.initial-header' );
+ self.$safeButton.prop( 'disabled',
false );
+ // FIXME: Should be a better error
message
+ toast.show( mw.msg(
'mobile-frontend-categories-nodata' ), 'toast error' );
+ } );
+ }
+ }
+ } );
+
+ M.define( 'categories/CategoryAddOverlay', CategoryAddOverlay );
+
+}( mw.mobileFrontend, jQuery ) );
diff --git a/javascripts/modules/categories/CategoryApi.js
b/javascripts/modules/categories/CategoryApi.js
new file mode 100644
index 0000000..0159890
--- /dev/null
+++ b/javascripts/modules/categories/CategoryApi.js
@@ -0,0 +1,47 @@
+( function ( M ) {
+
+ var CategoryApi,
+ SearchApi = M.require( 'modules/search/SearchApi' );
+
+ /**
+ * Api for CategoryOverlay
+ * @class CategoryApi
+ * @extends Api
+ */
+ CategoryApi = SearchApi.extend( {
+ /**
+ * @inheritdoc
+ */
+ searchNamespace: 14,
+ /**
+ * @inheritdoc
+ */
+ getApiData: function ( query ) {
+ return {
+ action: 'query',
+ list: 'prefixsearch',
+ pssearch: query,
+ pslimit: 5,
+ psnamespace: this.searchNamespace
+ };
+ },
+
+ /**
+ * Saves the categories passed to this function to the page
+ * @param {String} title Title of the current page (to add the
categories to)
+ * @param {String} categories List of Categories to add
+ * @returns {jquery.Deferred}
+ */
+ save: function ( title, categories ) {
+ return this.postWithToken( 'edit', {
+ action: 'edit',
+ title: title,
+ appendtext: categories,
+ summary: mw.msg(
'mobile-frontend-categories-summary' )
+ } );
+ }
+ } );
+
+ M.define( 'modules/categories/CategoryApi', CategoryApi );
+
+}( mw.mobileFrontend, jQuery ) );
diff --git a/javascripts/modules/categories/CategoryLookupInputWidget.js
b/javascripts/modules/categories/CategoryLookupInputWidget.js
new file mode 100644
index 0000000..69544d0
--- /dev/null
+++ b/javascripts/modules/categories/CategoryLookupInputWidget.js
@@ -0,0 +1,85 @@
+( function ( M, $, OO ) {
+ /**
+ * @class CategoryLookupInputWidget
+ * @extends OO.ui.LookupElement
+ */
+ function CategoryLookupInputWidget( options ) {
+ this.$element = $( '<div>' );
+ this.api = options.api;
+ this.$suggestions = options.suggestions;
+ this.categories = options.categories;
+ this.$saveButton = options.saveButton;
+ options.placeholder = mw.msg(
'mobile-frontend-categories-search' );
+ OO.ui.TextInputWidget.call( this, options );
+ OO.ui.LookupElement.call( this, options );
+ }
+ OO.inheritClass( CategoryLookupInputWidget, OO.ui.TextInputWidget );
+ OO.mixinClass( CategoryLookupInputWidget, OO.ui.LookupElement );
+
+ /**
+ * Handle a click on a suggested item. Add it to the list of added
categories and show save button.
+ * @param {Object} data Data of the clicked element
+ */
+ CategoryLookupInputWidget.prototype.onLookupMenuItemChoose = function (
data ) {
+ this.$suggestions.append(
+ mw.template.get( 'mobile.categories',
'CategoryButton.hogan' ).render( {
+ title: data.data,
+ displayname: data.label
+ } )
+ );
+ this.$saveButton.prop( 'disabled', false );
+ };
+
+ /**
+ * Returns the result of the search request.
+ * @return {jQuery.Deferred}
+ */
+ CategoryLookupInputWidget.prototype.getLookupRequest = function () {
+ return this.api.search( this.value );
+ };
+
+ /**
+ * Get lookup cache item from server response data.
+ * @param {Mixed} response Response from server
+ * @return {Mixed} Cached result response
+ */
+ CategoryLookupInputWidget.prototype.getLookupCacheDataFromResponse =
function ( response ) {
+ var title = new mw.Title( this.value, 14 );
+
+ // add user input as a possible (actually not existing) category
+ response.results.unshift( {
+ title: title.toString(),
+ displayname: title.getNameText()
+ } );
+
+ return response;
+ };
+
+ /**
+ * Get a list of menu item widgets from the data stored by the lookup
request's done handler.
+ * @param {Mixed} data Cached result data, usually an array
+ * @return {OO.ui.MenuOptionWidget[]}
+ */
+ CategoryLookupInputWidget.prototype.getLookupMenuOptionsFromData =
function ( data ) {
+ var result = [],
+ self = this;
+
+ $.each( data.results, function ( i, value ) {
+ if (
+ !$( 'button[data-title="' + value.title + '"]'
).length &&
+ $.inArray( value.displayname, self.categories )
=== -1
+ ) {
+ result.push(
+ new OO.ui.MenuOptionWidget( {
+ data: value.title,
+ label: value.displayname
+ } )
+ );
+ }
+ } );
+ return result;
+ };
+
+ M.define( 'modules/categories/CategoryLookupInputWidget',
CategoryLookupInputWidget );
+
+}( mw.mobileFrontend, jQuery, OO ) );
diff --git a/javascripts/modules/categories/CategoryOverlay.js
b/javascripts/modules/categories/CategoryOverlay.js
index c4ae4d5..f4a144d 100644
--- a/javascripts/modules/categories/CategoryOverlay.js
+++ b/javascripts/modules/categories/CategoryOverlay.js
@@ -16,12 +16,26 @@
* categorized in.
* @cfg {String} defaults.subheading Introduction text for the
list of categories,
* the page belongs to.
+ * @cfg {Array} defaults.headerButtons Objects that will be
used as defaults for
+ * generating header buttons.
*/
defaults: {
heading: mw.msg( 'mobile-frontend-categories-heading' ),
- subheading: mw.msg(
'mobile-frontend-categories-subheading' )
+ subheading: mw.msg(
'mobile-frontend-categories-subheading' ),
+ headerButtonsListClassName: 'overlay-action',
+ headerButtons: [ {
+ href: '#/categories/add',
+ className: 'add continue hidden',
+ msg: mw.msg( 'mobile-frontend-categories-add' )
+ } ]
},
+ /**
+ * @inheritdoc
+ */
className: 'category-overlay overlay',
+ /**
+ * @inheritdoc
+ */
templatePartials: {
content: mw.template.get( 'mobile.categories',
'CategoryOverlay.hogan' )
},
@@ -45,6 +59,17 @@
} );
}
Overlay.prototype.initialize.apply( this, arguments );
+ },
+
+ /**
+ * @inheritdoc
+ */
+ postRender: function ( options ) {
+ Overlay.prototype.postRender.apply( this, arguments );
+
+ if ( !options.isAnon ) {
+ this.$( '.add' ).removeClass( 'hidden' );
+ }
}
} );
diff --git a/javascripts/modules/categories/init.js
b/javascripts/modules/categories/init.js
index 2d53486..c1e1861 100644
--- a/javascripts/modules/categories/init.js
+++ b/javascripts/modules/categories/init.js
@@ -2,8 +2,10 @@
var loader = M.require( 'loader' ),
MobileWebClickTracking = M.require(
'loggingSchemas/SchemaMobileWebClickTracking' ),
- uiSchema = new MobileWebClickTracking( {},
'MobileWebUIClickTracking' );
+ uiSchema = new MobileWebClickTracking( {},
'MobileWebUIClickTracking' ),
+ user = M.require( 'user' );
+ // categories overlay
M.overlayManager.add( /^\/categories$/, function () {
var result = $.Deferred();
@@ -12,7 +14,26 @@
loadingOverlay.hide();
result.resolve( new CategoryOverlay( {
- categories: mw.config.get( 'wgCategories' )
+ categories: mw.config.get( 'wgCategories' ),
+ isAnon: user.isAnon(),
+ title: M.getCurrentPage().title
+ } ) );
+ } );
+ return result;
+ } );
+
+ // add categories overlay
+ M.overlayManager.add( /^\/categories\/add$/, function () {
+ var result = $.Deferred();
+
+ loader.loadModule( 'mobile.categories', true ).done( function (
loadingOverlay ) {
+ var CategoryAddOverlay = M.require(
'categories/CategoryAddOverlay' );
+
+ loadingOverlay.hide();
+ result.resolve( new CategoryAddOverlay( {
+ categories: mw.config.get( 'wgCategories' ),
+ isAnon: user.isAnon(),
+ title: M.getCurrentPage().title
} ) );
} );
return result;
diff --git a/javascripts/modules/editor/EditorOverlayBase.js
b/javascripts/modules/editor/EditorOverlayBase.js
index 443d6d0..1dcbc5f 100644
--- a/javascripts/modules/editor/EditorOverlayBase.js
+++ b/javascripts/modules/editor/EditorOverlayBase.js
@@ -111,20 +111,6 @@
}
return this.schema.log( data );
},
- /**
- * Reveals a spinner at the top of the overlay.
- * @method
- */
- showSpinner: function () {
- this.$spinner.show();
- },
- /**
- * Hides a spinner at the top of the overlay.
- * @method
- */
- clearSpinner: function () {
- this.$spinner.hide();
- },
/**
* If this is a new article, require confirmation before saving.
@@ -259,7 +245,6 @@
if ( browser.isAndroid2() ) {
this.$el.addClass( 'android-2' );
}
- this.$spinner = self.$( '.spinner' );
// log edit attempt
this.log( 'attempt' );
diff --git a/javascripts/modules/search/SearchApi.js
b/javascripts/modules/search/SearchApi.js
index 526e3f3..7550c52 100644
--- a/javascripts/modules/search/SearchApi.js
+++ b/javascripts/modules/search/SearchApi.js
@@ -48,6 +48,36 @@
},
/**
+ * The namespace to search in.
+ * @type {Number}
+ */
+ searchNamespace: 0,
+
+ /**
+ * Get the data used to do the search query api call.
+ * @method
+ * @param {String} query to search for
+ * @return {Object}
+ */
+ getApiData: function ( query ) {
+ return {
+ action: 'query',
+ generator: 'prefixsearch',
+ gpssearch: query,
+ gpsnamespace: this.searchNamespace,
+ gpslimit: 15,
+ prop: 'pageimages',
+ piprop: 'thumbnail',
+ pithumbsize: mw.config.get(
'wgMFThumbnailSizes' ).tiny,
+ pilimit: 15,
+ redirects: '',
+ list: 'prefixsearch',
+ pssearch: query,
+ pslimit: 15
+ };
+ },
+
+ /**
* Perform a search for the given query.
* FIXME: remove filtering of redirects once the upstream bug
has been fixed:
* https://bugzilla.wikimedia.org/show_bug.cgi?id=73673
@@ -56,73 +86,91 @@
* @return {jQuery.Deferred}
*/
search: function ( query ) {
+ var result = $.Deferred(),
+ request,
+ self = this;
+
if ( !this.isCached( query ) ) {
- this.searchCache[query] = this.get( {
- action: 'query',
- generator: 'prefixsearch',
- gpssearch: query,
- gpsnamespace: 0,
- gpslimit: 15,
- prop: 'pageimages',
- piprop: 'thumbnail',
- pithumbsize: mw.config.get(
'wgMFThumbnailSizes' ).tiny,
- pilimit: 15,
- redirects: '',
- list: 'prefixsearch',
- pssearch: query,
- pslimit: 15
- } ).then( function ( data ) {
- var results = [],
- pages = {},
- redirects = {},
- pageIds = [];
+ request = this.get( this.getApiData( query ) )
+ .done( function ( data ) {
+ var results = [],
+ pages = {},
+ redirects = {},
+ pageIds = [];
- if ( data.query ) {
- // get redirects into an easily
searchable shape
- if ( data.query.redirects ) {
- $.each(
data.query.redirects, function ( i, redirect ) {
-
redirects[redirect.from] = redirect.to;
- } );
- }
- if ( data.query.pages &&
data.query.prefixsearch ) {
- // get results into an
easily searchable shape
- $.each(
data.query.pages, function ( i, result ) {
-
pages[result.title] = result;
- } );
-
- // We loop through the
prefixsearch results (rather than the pages
- // results) here in
order to maintain the correct order.
- $.each(
data.query.prefixsearch, function ( i, page ) {
- var info, title
= page.title,
- id =
page.pageid;
-
- // Is this a
redirect? If yes, get the target.
- if (
redirects[title] ) {
- id =
pages[redirects[title]].pageid;
- }
-
- if ( id &&
data.query.pages[id] ) {
- info =
data.query.pages[id];
- }
-
- if ( info &&
$.inArray( id, pageIds ) === -1 ) {
-
pageIds.push ( id );
-
results.push( {
-
id: info.pageid,
-
heading: highlightSearchTerm( info.title, query ),
-
title: info.title,
-
url: mw.util.getUrl( info.title ),
-
thumbnail: info.thumbnail
+ if ( data.query ) {
+ // get redirects into
an easily searchable shape
+ if (
data.query.redirects ) {
+ $.each(
data.query.redirects, function ( i, redirect ) {
+
redirects[redirect.from] = redirect.to;
+ } );
+ }
+ if (
data.query.prefixsearch ) {
+ // some
queryies (like CategoryApi) only have prefixsearch
+ if (
data.query.pages ) {
+ // get
results into an easily searchable shape
+ $.each(
data.query.pages, function ( i, result ) {
+
pages[result.title] = result;
} );
}
- } );
- }
- }
- return {
- query: query,
- results: results
- };
+ // We loop
through the prefixsearch results (rather than the pages
+ // results)
here in order to maintain the correct order.
+ $.each(
data.query.prefixsearch, function ( i, page ) {
+ var
info, title = page.title,
+
id = page.pageid,
+
mwTitle;
+
+ // Is
this a redirect? If yes, get the target.
+ if (
redirects[title] ) {
+
id = pages[redirects[title]].pageid;
+ }
+
+ if ( id
&& data.query.pages && data.query.pages[id] ) {
+
info = data.query.pages[id];
+ }
+
+ if (
$.inArray( id, pageIds ) === -1 ) {
+
if ( info ) {
+
// return all possible page data
+
pageIds.push ( id );
+
results.push( {
+
id: info.pageid,
+
heading: highlightSearchTerm( info.title, query ),
+
title: info.title,
+
url: mw.util.getUrl( info.title ),
+
thumbnail: info.thumbnail
+
} );
+
} else {
+
mwTitle = mw.Title.newFromText( page.title, self._searchNamespace );
+
+
// just add a minimum of data (title and displayname)
+
results.push( {
+
title: page.title,
+
displayname: mwTitle.getNameText()
+
} );
+
}
+ }
+ } );
+ }
+ }
+
+ // resolve the Deferred object
+ result.resolve( {
+ query: query,
+ results: results
+ } );
+ } )
+ .fail( function () {
+ // reset cached result, it
maybe contains no value
+ self.searchCache[query] =
undefined;
+ // reject
+ result.reject();
+ } );
+
+ // cache the result to prevent the execution of
one search query twice in one session
+ this.searchCache[query] = result.promise( {
+ abort: request.abort
} );
}
diff --git a/javascripts/modules/talk/TalkOverlay.js
b/javascripts/modules/talk/TalkOverlay.js
index 2372b2f..2e31302 100644
--- a/javascripts/modules/talk/TalkOverlay.js
+++ b/javascripts/modules/talk/TalkOverlay.js
@@ -69,7 +69,7 @@
*/
showSpinner: function () {
this.$board.hide();
- this.$( '.spinner' ).show();
+ Overlay.prototype.showSpinner.apply( this,
arguments );
},
/**
@@ -77,7 +77,7 @@
* @method
*/
clearSpinner: function () {
- this.$( '.spinner' ).hide();
+ Overlay.prototype.clearSpinner.apply( this,
arguments );
this.$board.show();
},
diff --git a/less/Overlay.less b/less/Overlay.less
index 4823ede..bd73694 100644
--- a/less/Overlay.less
+++ b/less/Overlay.less
@@ -336,7 +336,6 @@
}
}
-
@media all and (min-width: @wgMFDeviceWidthTablet) {
.overlay {
.panel {
diff --git a/less/modules/categories/categories.less
b/less/modules/categories/categories.less
new file mode 100644
index 0000000..6f7efc9
--- /dev/null
+++ b/less/modules/categories/categories.less
@@ -0,0 +1,5 @@
+.category-suggestions {
+ button {
+ margin-right: 0.5em;
+ }
+}
\ No newline at end of file
diff --git a/templates/modules/categories/CategoryAddOverlay.hogan
b/templates/modules/categories/CategoryAddOverlay.hogan
new file mode 100644
index 0000000..5ed4b03
--- /dev/null
+++ b/templates/modules/categories/CategoryAddOverlay.hogan
@@ -0,0 +1,9 @@
+<div class="overlay-header-container position-fixed">
+ {{>header}}
+ {{>saveHeader}}
+</div>
+
+<div class="content-header panel add-panel">
+ <div class="category-add-input"></div>
+</div>
+<p class="category-suggestions panel"></p>
diff --git a/templates/modules/categories/CategoryAddOverlayHeader.hogan
b/templates/modules/categories/CategoryAddOverlayHeader.hogan
new file mode 100644
index 0000000..3d38df5
--- /dev/null
+++ b/templates/modules/categories/CategoryAddOverlayHeader.hogan
@@ -0,0 +1,9 @@
+<div class="overlay-header initial-header hideable">
+ <ul>
+ <li>{{{backButton}}}</li>
+ </ul>
+ <div class="overlay-title">
+ {{{heading}}}
+ </div>
+ <div class="overlay-action"><button class="save submit"
disabled>{{saveMsg}}</button></div>
+</div>
\ No newline at end of file
diff --git a/templates/modules/categories/CategoryButton.hogan
b/templates/modules/categories/CategoryButton.hogan
new file mode 100644
index 0000000..ccc3623
--- /dev/null
+++ b/templates/modules/categories/CategoryButton.hogan
@@ -0,0 +1,3 @@
+<button class="mw-ui-button mw-ui-progressive mw-ui-icon mw-ui-icon-before
mw-ui-icon-ok suggestion suggested" data-title="{{title}}">
+ {{displayname}}
+</button>
\ No newline at end of file
--
To view, visit https://gerrit.wikimedia.org/r/180880
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I844787f25f4769cdb6ff899a274763dd75b8046c
Gerrit-PatchSet: 22
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: Florianschmidtwelzow <[email protected]>
Gerrit-Reviewer: Bartosz DziewoĆski <[email protected]>
Gerrit-Reviewer: Bmansurov <[email protected]>
Gerrit-Reviewer: Esanders <[email protected]>
Gerrit-Reviewer: Florianschmidtwelzow <[email protected]>
Gerrit-Reviewer: Jdlrobson <[email protected]>
Gerrit-Reviewer: Kaldari <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: Trevor Parscal <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits