From: Jan Drewniak Date: Wed, 18 Jan 2017 10:27:43 +0000 (+0100) Subject: Displaying interwiki results in sidebar X-Git-Tag: 1.31.0-rc.0~4155^2 X-Git-Url: http://git.cyclocoop.org/%24href?a=commitdiff_plain;h=d78a470fcd2a825f11d4c4352e718b46942bb9af;p=lhc%2Fweb%2Fwiklou.git Displaying interwiki results in sidebar Displays newly designed interwiki search results in the sidebar of the specialSearch page. A prototype of this change can be viewed on this labs url: http://sistersearch.wmflabs.org/w/index.php?title=Special:Search&search=mars Bug: T149806 Change-Id: I66e4b6a502dae488d105f11cad73e145990c2327 --- diff --git a/autoload.php b/autoload.php index a6840b4fb7..dbb7dbd349 100644 --- a/autoload.php +++ b/autoload.php @@ -936,8 +936,11 @@ $wgAutoloadLocalClasses = [ 'MediaWiki\\Widget\\Search\\DidYouMeanWidget' => __DIR__ . '/includes/widget/search/DidYouMeanWidget.php', 'MediaWiki\\Widget\\Search\\FullSearchResultWidget' => __DIR__ . '/includes/widget/search/FullSearchResultWidget.php', 'MediaWiki\\Widget\\Search\\InterwikiSearchResultSetWidget' => __DIR__ . '/includes/widget/search/InterwikiSearchResultSetWidget.php', + 'MediaWiki\\Widget\\Search\\InterwikiSearchResultWidget' => __DIR__ . '/includes/widget/search/InterwikiSearchResultWidget.php', 'MediaWiki\\Widget\\Search\\SearchFormWidget' => __DIR__ . '/includes/widget/search/SearchFormWidget.php', + 'MediaWiki\\Widget\\Search\\SearchResultSetWidget' => __DIR__ . '/includes/widget/search/SearchResultSetWidget.php', 'MediaWiki\\Widget\\Search\\SearchResultWidget' => __DIR__ . '/includes/widget/search/SearchResultWidget.php', + 'MediaWiki\\Widget\\Search\\SimpleSearchResultSetWidget' => __DIR__ . '/includes/widget/search/SimpleSearchResultSetWidget.php', 'MediaWiki\\Widget\\Search\\SimpleSearchResultWidget' => __DIR__ . '/includes/widget/search/SimpleSearchResultWidget.php', 'MediaWiki\\Widget\\TitleInputWidget' => __DIR__ . '/includes/widget/TitleInputWidget.php', 'MediaWiki\\Widget\\UserInputWidget' => __DIR__ . '/includes/widget/UserInputWidget.php', diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index a7cbd96dd8..e98227dcac 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -8562,6 +8562,25 @@ $wgLearnerMemberSince = 4; # days $wgExperiencedUserEdits = 500; $wgExperiencedUserMemberSince = 30; # days +/** + * Mapping of interwiki index prefixes to descriptors that + * can be used to change the display of interwiki search results. + * + * Descriptors are appended to CSS classes of interwiki results + * which using InterwikiSearchResultWidget. + * + * Predefined descriptors include the following words: + * definition, textbook, news, quotation, book, travel, course + * + * @par Example: + * @code + * $wgInterwikiPrefixDisplayTypes = [ + * 'iwprefix' => 'definition' + *]; + * @endcode + */ +$wgInterwikiPrefixDisplayTypes = []; + /** * For really cool vim folding this needs to be at the end: * vim: foldmarker=@{,@} foldmethod=marker diff --git a/includes/specials/SpecialSearch.php b/includes/specials/SpecialSearch.php index 34620ff9e2..b7356e7509 100644 --- a/includes/specials/SpecialSearch.php +++ b/includes/specials/SpecialSearch.php @@ -25,9 +25,11 @@ use MediaWiki\MediaWikiServices; use MediaWiki\Widget\Search\BasicSearchResultSetWidget; -use MediaWiki\Widget\Search\InterwikiSearchResultSetWidget; use MediaWiki\Widget\Search\FullSearchResultWidget; +use MediaWiki\Widget\Search\InterwikiSearchResultWidget; +use MediaWiki\Widget\Search\InterwikiSearchResultSetWidget; use MediaWiki\Widget\Search\SimpleSearchResultWidget; +use MediaWiki\Widget\Search\SimpleSearchResultSetWidget; /** * implements Special:Search - Run text & title search and display the output @@ -385,13 +387,26 @@ class SpecialSearch extends SpecialPage { // results to display. $linkRenderer = $this->getLinkRenderer(); $mainResultWidget = new FullSearchResultWidget( $this, $linkRenderer ); - $sidebarResultWidget = new SimpleSearchResultWidget( $this, $linkRenderer ); - $sidebarResultsWidget = new InterwikiSearchResultSetWidget( - $this, - $sidebarResultWidget, - $linkRenderer, - MediaWikiServices::getInstance()->getInterwikiLookup() - ); + + if ( $search->getFeatureData( 'enable-new-crossproject-page' ) ) { + + $sidebarResultWidget = new InterwikiSearchResultWidget( $this, $linkRenderer ); + $sidebarResultsWidget = new InterwikiSearchResultSetWidget( + $this, + $sidebarResultWidget, + $linkRenderer, + MediaWikiServices::getInstance()->getInterwikiLookup() + ); + } else { + $sidebarResultWidget = new SimpleSearchResultWidget( $this, $linkRenderer ); + $sidebarResultsWidget = new SimpleSearchResultSetWidget( + $this, + $sidebarResultWidget, + $linkRenderer, + MediaWikiServices::getInstance()->getInterwikiLookup() + ); + } + $widget = new BasicSearchResultSetWidget( $this, $mainResultWidget, $sidebarResultsWidget ); $out->addHTML( $widget->render( diff --git a/includes/widget/search/BasicSearchResultSetWidget.php b/includes/widget/search/BasicSearchResultSetWidget.php index 2c31bd2a43..07094afca6 100644 --- a/includes/widget/search/BasicSearchResultSetWidget.php +++ b/includes/widget/search/BasicSearchResultSetWidget.php @@ -22,7 +22,7 @@ class BasicSearchResultSetWidget { public function __construct( SpecialSearch $specialPage, SearchResultWidget $resultWidget, - InterwikiSearchResultSetWidget $sidebarWidget + SearchResultSetWidget $sidebarWidget ) { $this->specialPage = $specialPage; $this->resultWidget = $resultWidget; diff --git a/includes/widget/search/InterwikiSearchResultSetWidget.php b/includes/widget/search/InterwikiSearchResultSetWidget.php index c738483562..af1ed0525b 100644 --- a/includes/widget/search/InterwikiSearchResultSetWidget.php +++ b/includes/widget/search/InterwikiSearchResultSetWidget.php @@ -7,13 +7,14 @@ use MediaWiki\Linker\LinkRenderer; use SearchResultSet; use SpecialSearch; use Title; +use Html; /** * Renders one or more SearchResultSets into a sidebar grouped by * interwiki prefix. Includes a per-wiki header indicating where * the results are from. */ -class InterwikiSearchResultSetWidget { +class InterwikiSearchResultSetWidget implements SearchResultSetWidget { /** @var SpecialSearch */ protected $specialSearch; /** @var SearchResultWidget */ @@ -24,6 +25,10 @@ class InterwikiSearchResultSetWidget { protected $linkRenderer; /** @var InterwikiLookup */ protected $iwLookup; + /** @var $output */ + protected $output; + /** @var $iwPrefixDisplayTypes */ + protected $iwPrefixDisplayTypes; public function __construct( SpecialSearch $specialSearch, @@ -35,8 +40,11 @@ class InterwikiSearchResultSetWidget { $this->resultWidget = $resultWidget; $this->linkRenderer = $linkRenderer; $this->iwLookup = $iwLookup; + $this->output = $specialSearch->getOutput(); + $this->iwPrefixDisplayTypes = $specialSearch->getConfig()->get( + 'InterwikiPrefixDisplayTypes' + ); } - /** * @param string $term User provided search term * @param SearchResultSet|SearchResultSet[] $resultSets List of interwiki @@ -50,6 +58,9 @@ class InterwikiSearchResultSetWidget { $this->loadCustomCaptions(); + $this->output->addModules( 'mediawiki.special.search.commonsInterwikiWidget' ); + $this->output->addModuleStyles( 'mediawiki.special.search.interwikiwidget.styles' ); + $iwResults = []; foreach ( $resultSets as $resultSet ) { $result = $resultSet->next(); @@ -61,56 +72,99 @@ class InterwikiSearchResultSetWidget { } } - $out = ''; + $iwResultSetPos = 1; + $iwResultListOutput = ''; + foreach ( $iwResults as $iwPrefix => $results ) { - $out .= $this->headerHtml( $iwPrefix, $term ); - $out .= ""; + + $headerHtml = $this->headerHtml( $term, $iwPrefix ); + $footerHtml = $this->footerHtml( $term, $iwPrefix ); + $iwResultListOutput .= Html::rawElement( 'li', + [ + 'class' => 'iw-resultset iw-resultset--' . $iwDisplayType, + 'data-iw-resultset-pos' => $iwResultSetPos + ], + $headerHtml . + $iwResultItemOutput . + $footerHtml + ); + + $iwResultSetPos++; } - return - "
" . - "
" . - $this->specialSearch->msg( 'search-interwiki-caption' )->text() . - '
' . - $out . - "
"; + return Html::rawElement( + 'div', + [ 'id' => 'mw-interwiki-results' ], + Html::rawElement( + 'p', + [ 'class' => 'iw-headline' ], + $this->specialSearch->msg( 'search-interwiki-caption' )->escaped() + ) . + Html::rawElement( + 'ul', [ 'class' => 'iw-results', ], $iwResultListOutput + ) + ); } /** * Generates an appropriate HTML header for the given interwiki prefix * - * @param string $iwPrefix Interwiki prefix of wiki to show header for * @param string $term User provided search term + * @param string $iwPrefix Interwiki prefix of wiki to show header for * @return string HTML */ - protected function headerHtml( $iwPrefix, $term ) { + protected function headerHtml( $term, $iwPrefix ) { + + $iwDisplayType = isset( $this->iwPrefixDisplayTypes[$iwPrefix] ) + ? $this->iwPrefixDisplayTypes[$iwPrefix] + : ""; + if ( isset( $this->customCaptions[$iwPrefix] ) ) { + /* customCaptions composed by loadCustomCaptions() with pre-escaped content.*/ $caption = $this->customCaptions[$iwPrefix]; } else { $interwiki = $this->iwLookup->fetch( $iwPrefix ); $parsed = wfParseUrl( wfExpandUrl( $interwiki ? $interwiki->getURL() : '/' ) ); - $caption = $this->specialSearch->msg( 'search-interwiki-default', $parsed['host'] )->text(); + $caption = $this->specialSearch->msg( 'search-interwiki-default', $parsed['host'] )->escaped(); } - $searchLink = $this->linkRenderer->makeLink( - Title::newFromText( "$iwPrefix:Special:Search" ), - $this->specialSearch->msg( 'search-interwiki-more' )->text(), - [], - [ - 'search' => $term, - 'fulltext' => 1, - ] + + return Html::rawElement( 'div', [ 'class' => 'iw-result__header' ], + Html::rawElement( 'span', [ 'class' => 'iw-result__icon iw-result__icon--' . $iwDisplayType ] ) + . $caption ); - return - "
" . - "{$searchLink}" . - $caption . - "
"; + } + + /** + * Generates an HTML footer for the given interwiki prefix + * + * @param string $term User provided search term + * @param string $iwPrefix Interwiki prefix of wiki to show footer for + * @return string HTML + */ + protected function footerHtml( $term, $iwPrefix ) { + + $href = Title::makeTitle( NS_SPECIAL, 'Search', null, $iwPrefix )->getLocalURL( + [ 'search' => $term, 'fulltext' => 1 ] + ); + + $searchLink = Html::rawElement( + 'a', + [ 'href' => $href ], + $this->specialSearch->msg( 'search-interwiki-more' )->escaped() + ); + + return Html::rawElement( 'div', [ 'class' => 'iw-result__footer' ], $searchLink ); } protected function loadCustomCaptions() { @@ -119,7 +173,7 @@ class InterwikiSearchResultSetWidget { } $this->customCaptions = []; - $customLines = explode( "\n", $this->specialSearch->msg( 'search-interwiki-custom' )->text() ); + $customLines = explode( "\n", $this->specialSearch->msg( 'search-interwiki-custom' )->escaped() ); foreach ( $customLines as $line ) { $parts = explode( ':', $line, 2 ); if ( count( $parts ) === 2 ) { diff --git a/includes/widget/search/InterwikiSearchResultWidget.php b/includes/widget/search/InterwikiSearchResultWidget.php new file mode 100644 index 0000000000..44229b83a5 --- /dev/null +++ b/includes/widget/search/InterwikiSearchResultWidget.php @@ -0,0 +1,86 @@ +specialSearch = $specialSearch; + $this->linkRenderer = $linkRenderer; + $this->iwPrefixDisplayTypes = $specialSearch->getConfig()->get( 'InterwikiPrefixDisplayTypes' ); + } + + /** + * @param SearchResult $result The result to render + * @param string $terms Terms to be highlighted (@see SearchResult::getTextSnippet) + * @param int $position The result position, including offset + * @return string HTML + */ + public function render( SearchResult $result, $terms, $position ) { + + $title = $result->getTitle(); + $iwPrefix = $result->getTitle()->getInterwiki(); + $titleSnippet = $result->getTitleSnippet(); + $snippet = $result->getTextSnippet( $terms ); + $displayType = isset( $this->iwPrefixDisplayTypes[$iwPrefix] ) + ? $this->iwPrefixDisplayTypes[$iwPrefix] + : ""; + + if ( $titleSnippet ) { + $titleSnippet = new HtmlArmor( $titleSnippet ); + } else { + $titleSnippet = null; + } + + $link = $this->linkRenderer->makeLink( $title, $titleSnippet ); + + $redirectTitle = $result->getRedirectTitle(); + $redirect = ''; + if ( $redirectTitle !== null ) { + + $redirectText = $result->getRedirectSnippet(); + + if ( $redirectText ) { + $redirectText = new HtmlArmor( $redirectText ); + } else { + $redirectText = null; + } + + $redirect = Html::rawElement( 'span', [ 'class' => 'iw-result__redirect' ], + $this->specialSearch->msg( 'search-redirect' )->rawParams( + $this->linkRenderer->makeLink( $redirectTitle, $redirectText ) + )->escaped() + ); + } + + switch ( $displayType ) { + case 'definition': + return "
" . + "{$link} {$redirect}: " . + $snippet . + "
"; + case 'quotation': + return "
{$snippet}
" . + "
{$link} {$redirect}
"; + default: + return "
{$link} {$redirect}
" . + "
{$snippet}
"; + }; + } +} diff --git a/includes/widget/search/SearchResultSetWidget.php b/includes/widget/search/SearchResultSetWidget.php new file mode 100644 index 0000000000..6df6e65c2a --- /dev/null +++ b/includes/widget/search/SearchResultSetWidget.php @@ -0,0 +1,18 @@ +specialSearch = $specialSearch; + $this->resultWidget = $resultWidget; + $this->linkRenderer = $linkRenderer; + $this->iwLookup = $iwLookup; + } + + /** + * @param string $term User provided search term + * @param SearchResultSet|SearchResultSet[] $resultSets List of interwiki + * results to render. + * @return string HTML + */ + public function render( $term, $resultSets ) { + if ( !is_array( $resultSets ) ) { + $resultSets = [ $resultSets ]; + } + + $this->loadCustomCaptions(); + + $iwResults = []; + foreach ( $resultSets as $resultSet ) { + $result = $resultSet->next(); + while ( $result ) { + if ( !$result->isBrokenTitle() ) { + $iwResults[$result->getTitle()->getInterwiki()][] = $result; + } + $result = $resultSet->next(); + } + } + + $out = ''; + foreach ( $iwResults as $iwPrefix => $results ) { + $out .= $this->headerHtml( $iwPrefix, $term ); + $out .= ""; + } + + return + "
" . + "
" . + $this->specialSearch->msg( 'search-interwiki-caption' )->escaped() . + '
' . + $out . + "
"; + } + + /** + * Generates an appropriate HTML header for the given interwiki prefix + * + * @param string $iwPrefix Interwiki prefix of wiki to show header for + * @param string $term User provided search term + * @return string HTML + */ + protected function headerHtml( $iwPrefix, $term ) { + if ( isset( $this->customCaptions[$iwPrefix] ) ) { + $caption = $this->customCaptions[$iwPrefix]; + } else { + $interwiki = $this->iwLookup->fetch( $iwPrefix ); + $parsed = wfParseUrl( wfExpandUrl( $interwiki ? $interwiki->getURL() : '/' ) ); + $caption = $this->specialSearch->msg( 'search-interwiki-default', $parsed['host'] )->escaped(); + } + + $href = Title::makeTitle( NS_SPECIAL, 'Search', null, $iwPrefix )->getLocalURL( + [ 'search' => $term, 'fulltext' => 1 ] + ); + $searchLink = Html::rawElement( + 'a', + [ 'href' => $href ], + $this->specialSearch->msg( 'search-interwiki-more' )->escaped() + ); + + return + "
" . + "{$searchLink}" . + $caption . + "
"; + } + + protected function loadCustomCaptions() { + if ( $this->customCaptions !== null ) { + return; + } + + $this->customCaptions = []; + $customLines = explode( "\n", $this->specialSearch->msg( 'search-interwiki-custom' )->escaped() ); + foreach ( $customLines as $line ) { + $parts = explode( ':', $line, 2 ); + if ( count( $parts ) === 2 ) { + $this->customCaptions[$parts[0]] = $parts[1]; + } + } + } +} diff --git a/languages/i18n/en.json b/languages/i18n/en.json index 81d9af1f29..b1e97be366 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -1002,6 +1002,7 @@ "search-interwiki-default": "Results from $1:", "search-interwiki-custom": "", "search-interwiki-more": "(more)", + "search-interwiki-more-results": "more results", "search-relatedarticle": "Related", "searchrelated": "related", "searchall": "all", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index b141ffc00d..6ad64aa74c 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -1188,6 +1188,7 @@ "search-interwiki-default": "Parameters:\n* $1 - the hostname of the remote wiki from where the additional results listed below are returned", "search-interwiki-custom": "#REDIRECT [[MediaWiki:Wmf-search-interwiki-custom/qqq]]", "search-interwiki-more": "{{Identical|More}}", + "search-interwiki-more-results": "Label for a link that leads to more search results from a given wiki.", "search-relatedarticle": "This is a search result (and I guess search engine) dependent messages. I do not know how to trigger the feature. The message is displayed if the search result contains information that related pages can also be provided from the search engine. I assume this is \"More Like This\" functionality. Microsoft glossary defines MLT as \"A way to refine search by identifying the right set of documents and then locating similar documents. This allows the searcher to control the direction of the search and focus on the most fruitful lines of inquiry.\"[http://www.microsoft.com/enterprisesearch/en/us/search-glossary.aspx]\n{{Identical|Related}}", "searchrelated": "This is a search result (and I guess search engine) dependent messages. I do not know how to trigger the feature. The message is displayed if the search result contains information that related pages can also be provided from the search engine. I assume this is \"More Like This\" functionality. Microsoft glossary defines MLT as \"A way to refine search by identifying the right set of documents and then locating similar documents. This allows the searcher to control the direction of the search and focus on the most fruitful lines of inquiry.\"[http://www.microsoft.com/enterprisesearch/en/us/search-glossary.aspx]\n{{Identical|Related}}", "searchall": "{{Identical|All}}", diff --git a/resources/Resources.php b/resources/Resources.php index f14787f815..7e64b77702 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -1983,6 +1983,23 @@ return [ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.search.styles.css', 'targets' => [ 'desktop', 'mobile' ], ], + 'mediawiki.special.search.interwikiwidget.styles' => [ + 'styles' => 'resources/src/mediawiki.special/' + . 'mediawiki.special.search.interwikiwidget.styles.less', + 'targets' => [ 'desktop', 'mobile' ] + ], + 'mediawiki.special.search.commonsInterwikiWidget' => [ + 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.search.commonsInterwikiWidget.js', + 'dependencies' => [ + 'mediawiki.Uri', + 'mediawiki.jqueryMsg' + ], + 'targets' => [ 'desktop', 'mobile' ], + 'messages' => [ + 'search-interwiki-more', + 'searchprofile-images' + ], + ], 'mediawiki.special.undelete' => [ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.undelete.js', ], diff --git a/resources/src/mediawiki.special/images/special.search/book-icon.png b/resources/src/mediawiki.special/images/special.search/book-icon.png new file mode 100644 index 0000000000..07e3ec746e Binary files /dev/null and b/resources/src/mediawiki.special/images/special.search/book-icon.png differ diff --git a/resources/src/mediawiki.special/images/special.search/book-icon.svg b/resources/src/mediawiki.special/images/special.search/book-icon.svg new file mode 100644 index 0000000000..6c3fa5f2aa --- /dev/null +++ b/resources/src/mediawiki.special/images/special.search/book-icon.svg @@ -0,0 +1,36 @@ + + + + wikisource-icon + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/src/mediawiki.special/images/special.search/course-icon.png b/resources/src/mediawiki.special/images/special.search/course-icon.png new file mode 100644 index 0000000000..9aad230aac Binary files /dev/null and b/resources/src/mediawiki.special/images/special.search/course-icon.png differ diff --git a/resources/src/mediawiki.special/images/special.search/course-icon.svg b/resources/src/mediawiki.special/images/special.search/course-icon.svg new file mode 100644 index 0000000000..4fab1f3d4a --- /dev/null +++ b/resources/src/mediawiki.special/images/special.search/course-icon.svg @@ -0,0 +1,35 @@ + + + + wikiversity-icon + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/src/mediawiki.special/images/special.search/definition-icon.png b/resources/src/mediawiki.special/images/special.search/definition-icon.png new file mode 100644 index 0000000000..b279f4ed04 Binary files /dev/null and b/resources/src/mediawiki.special/images/special.search/definition-icon.png differ diff --git a/resources/src/mediawiki.special/images/special.search/definition-icon.svg b/resources/src/mediawiki.special/images/special.search/definition-icon.svg new file mode 100644 index 0000000000..1d58906244 --- /dev/null +++ b/resources/src/mediawiki.special/images/special.search/definition-icon.svg @@ -0,0 +1,22 @@ + + + + wiktionary-icon + Created with Sketch. + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/src/mediawiki.special/images/special.search/dna-icon.png b/resources/src/mediawiki.special/images/special.search/dna-icon.png new file mode 100644 index 0000000000..76ae7b97c3 Binary files /dev/null and b/resources/src/mediawiki.special/images/special.search/dna-icon.png differ diff --git a/resources/src/mediawiki.special/images/special.search/dna-icon.svg b/resources/src/mediawiki.special/images/special.search/dna-icon.svg new file mode 100644 index 0000000000..b6472d2975 --- /dev/null +++ b/resources/src/mediawiki.special/images/special.search/dna-icon.svg @@ -0,0 +1,34 @@ + + + + wikispecies-icon + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/src/mediawiki.special/images/special.search/image-icon.png b/resources/src/mediawiki.special/images/special.search/image-icon.png new file mode 100644 index 0000000000..1ebbc7414e Binary files /dev/null and b/resources/src/mediawiki.special/images/special.search/image-icon.png differ diff --git a/resources/src/mediawiki.special/images/special.search/image-icon.svg b/resources/src/mediawiki.special/images/special.search/image-icon.svg new file mode 100644 index 0000000000..b68762e09c --- /dev/null +++ b/resources/src/mediawiki.special/images/special.search/image-icon.svg @@ -0,0 +1,16 @@ + + + + commons-icon + Created with Sketch. + + + + + + + + + + + \ No newline at end of file diff --git a/resources/src/mediawiki.special/images/special.search/news-icon.png b/resources/src/mediawiki.special/images/special.search/news-icon.png new file mode 100644 index 0000000000..6b79590dd3 Binary files /dev/null and b/resources/src/mediawiki.special/images/special.search/news-icon.png differ diff --git a/resources/src/mediawiki.special/images/special.search/news-icon.svg b/resources/src/mediawiki.special/images/special.search/news-icon.svg new file mode 100644 index 0000000000..996bc84b10 --- /dev/null +++ b/resources/src/mediawiki.special/images/special.search/news-icon.svg @@ -0,0 +1,31 @@ + + + + wikinews-icon + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/src/mediawiki.special/images/special.search/quotation-icon.png b/resources/src/mediawiki.special/images/special.search/quotation-icon.png new file mode 100644 index 0000000000..9d3ade30b8 Binary files /dev/null and b/resources/src/mediawiki.special/images/special.search/quotation-icon.png differ diff --git a/resources/src/mediawiki.special/images/special.search/quotation-icon.svg b/resources/src/mediawiki.special/images/special.search/quotation-icon.svg new file mode 100644 index 0000000000..0a24b3ef82 --- /dev/null +++ b/resources/src/mediawiki.special/images/special.search/quotation-icon.svg @@ -0,0 +1,12 @@ + + + + wikiquote-icon + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/resources/src/mediawiki.special/images/special.search/textbook-icon.png b/resources/src/mediawiki.special/images/special.search/textbook-icon.png new file mode 100644 index 0000000000..0de2821fad Binary files /dev/null and b/resources/src/mediawiki.special/images/special.search/textbook-icon.png differ diff --git a/resources/src/mediawiki.special/images/special.search/textbook-icon.svg b/resources/src/mediawiki.special/images/special.search/textbook-icon.svg new file mode 100644 index 0000000000..52446b88b1 --- /dev/null +++ b/resources/src/mediawiki.special/images/special.search/textbook-icon.svg @@ -0,0 +1,28 @@ + + + + wikibooks-icon + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/src/mediawiki.special/images/special.search/travel-icon.png b/resources/src/mediawiki.special/images/special.search/travel-icon.png new file mode 100644 index 0000000000..9540e5b568 Binary files /dev/null and b/resources/src/mediawiki.special/images/special.search/travel-icon.png differ diff --git a/resources/src/mediawiki.special/images/special.search/travel-icon.svg b/resources/src/mediawiki.special/images/special.search/travel-icon.svg new file mode 100644 index 0000000000..c61da34f03 --- /dev/null +++ b/resources/src/mediawiki.special/images/special.search/travel-icon.svg @@ -0,0 +1,15 @@ + + + + wikivoyage-icon + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/resources/src/mediawiki.special/mediawiki.special.search.commonsInterwikiWidget.js b/resources/src/mediawiki.special/mediawiki.special.search.commonsInterwikiWidget.js new file mode 100644 index 0000000000..3810ac1b0a --- /dev/null +++ b/resources/src/mediawiki.special/mediawiki.special.search.commonsInterwikiWidget.js @@ -0,0 +1,80 @@ +( function ( mw, $ ) { + + var api = new mw.Api(), + pageUrl = new mw.Uri(), + imagesText = new mw.Message( mw.messages, 'searchprofile-images' ), + moreResultsText = new mw.Message( mw.messages, 'search-interwiki-more' ); + + function itemTemplate( results ) { + + var resultOutput = '', i, result, imageCaption, imageThumbnailSrc; + + for ( i = 0; i < results.length; i++ ) { + result = results[ i ], + imageCaption = mw.html.element( 'span', { 'class': 'iw-result__mini-gallery__caption' }, result.title ); + imageThumbnailSrc = ( result.thumbnail ) ? result.thumbnail.source : ''; + resultOutput += ''; + } + + return resultOutput; + } + + function itemWrapperTemplate( pageQuery, itemTemplateOutput ) { + + return '
  • ' + + '
    ' + + '' + + '' + imagesText.escaped() + '' + + '
    ' + + '
    ' + + /* template output has been sanitized by mw.html.element */ + itemTemplateOutput + + '
    ' + + '' + + '
  • '; + + } + + api.get( { + action: 'query', + generator: 'search', + gsrsearch: pageUrl.query.search, + gsrnamespace: mw.config.get( 'wgNamespaceIds' ).file, + gsrlimit: 3, + prop: 'pageimages', + pilimit: 3, + piprop: 'thumbnail', + pithumbsize: 300, + formatversion: 2 + } ) + .done( function ( resp ) { + var results = ( resp.query && resp.query.pages ) ? resp.query.pages : false, + multimediaWidgetTemplate; + + if ( !results ) { + return; + } + + results.sort( function( a, b ) { + return b.index - a.index; + } ); + + multimediaWidgetTemplate = itemWrapperTemplate( pageUrl.query.search, itemTemplate( results ) ); + /* we really only need to wait for document ready for DOM manipulation */ + $( function () { + $( '.iw-results' ).prepend( multimediaWidgetTemplate ); + } ); + } ); + +}( mediaWiki, jQuery ) ); diff --git a/resources/src/mediawiki.special/mediawiki.special.search.interwikiwidget.styles.less b/resources/src/mediawiki.special/mediawiki.special.search.interwikiwidget.styles.less new file mode 100644 index 0000000000..923b81a019 --- /dev/null +++ b/resources/src/mediawiki.special/mediawiki.special.search.interwikiwidget.styles.less @@ -0,0 +1,222 @@ +/* interwiki search results */ +/*==========================*/ + +#mw-interwiki-results { + float: right; + width: 30%; +} + +.iw-headline { + font-weight: bold; + font-size: 1rem; + font-size: 16px; + opacity: 0.7; +} + +.iw-results { + list-style: none; + margin: 0; +} + +.iw-resultset { + margin-bottom: 1.2em; + background-color: #f2f4f7; + vertical-align: top; + width: 100%; + float: left; + list-style-type: none; +} + +/* clearfix */ +.iw-result:after { + visibility: hidden; + display: block; + font-size: 0; + content: " "; + clear: both; + height: 0; +} + +* html .interwiki-result { zoom: 1; } /* IE6 */ +*:first-child+html .iw-resultset { zoom: 1; } /* IE7 */ + +/* padding each .iw-resultset section seperately. +This allows us greater flexibility in the design. +For example changing the background color on the +header and footer. */ +.iw-result__header, +.iw-result__title, +.iw-result__content, +.iw-result__footer { + padding-left: 0.85em; + padding-right: 0.85em; + padding-top: 0.25em; + padding-bottom: 0.25em; +} + +/* definition titles appear inline, +to resemble a traditional dictionary definition */ +.iw-resultset--definition .iw-result__title { + display: inline; + padding: 0; +} + +.iw-resultset > div:first-child { + padding-top: 0.85em; +} + +.iw-resultset > div:last-child { + padding-bottom: 0.85em; +} + +.iw-result__title { + font-size: 16px; /* rem fallback */ + font-size: 1rem; +} + +.iw-result__title a.extiw { + color: #252525; + font-weight: bold; +} + +.iw-result__content:after { /* clearfix */ + visibility: hidden; + display: block; + font-size: 0; + content: " "; + clear: both; + height: 0; +} + +.iw-result__footer { + float: right; +} + +.iw-result__icon { + display: inline-block; + width: 24px; + height: 24px; + vertical-align: middle; + margin-right: 0.25em; + background: url( images/special.search/definition-icon.svg ) no-repeat 0 0; + background-size: 100% 100%; +} + +@interwikiContentTypes: definition, travel, quotation, book, course, news, textbook, image; + +.generate-iwIcons(); + +.generate-iwIcons( @i:1 ) when ( @i =< length( @interwikiContentTypes ) ) { + @iwIcon: extract( @interwikiContentTypes, @i ); + + .iw-result__icon--@{iwIcon} { + /* stylelint-disable-next-line function-url-quotes */ + background-image: url( 'images/special.search/@{iwIcon}-icon.png' ); + /* stylelint-disable-next-line function-url-quotes */ + background-image: url( 'images/special.search/@{iwIcon}-icon.svg' ); + } + + .generate-iwIcons( @i + 1 ); +} + +/* image search result */ +.iw-result__mini-gallery { + position: relative; + float: left; + width: 60%; + height: 200px; + box-sizing: border-box; + padding: 0.25rem; +} + +.iw-result__mini-gallery__image { + display: block; + position: relative; + width: 100%; + height: 100%; + background-size: cover; + background-repeat: no-repeat; + background-position: center center; +} + +.iw-result__mini-gallery__image:hover > .iw-result__mini-gallery__caption { + visibility: visible; +} + +.iw-result__mini-gallery__image > .iw-result__mini-gallery__caption { /* image gallery text */ + visibility: hidden; + position: absolute; + bottom: 0; + left: 0; + text-align: center; + color: #fff; + text-shadow: 0 0 10px rgba( 0, 0, 0, 0.4 ); /* improves legibility on white background*/ + font-size: 0.8em; + padding: 5px; + background-color: rgba( 0, 0, 0, 0.5 ); +} + +.iw-result__mini-gallery:nth-child(2), +.iw-result__mini-gallery:nth-child(3) { /* second and third images are small */ + width: 40%; + height: 100px; +} + +/* different types of interwiki result boxes */ +/* quotation box */ +.iw-resultset--quotation .iw-result__content { + border-left: 4px solid #afb1b5; + margin-left: 1em; + padding-top: 0; + margin-top: 0.25em; +} +.iw-resultset--quotation .iw-result__title{ + margin-left: 1em; +} +.iw-result--quotation .iw-result__title:before{ + content: ' — '; + display: inline-block; +} +.iw-result--quotation .iw-result__footer { + text-align: right; +} + +/* no results +span the interwiki results across the bottom of the page. +*/ + +.mw-search-nonefound ~ #mw-search-interwiki { + width: 100%; +} + +.mw-search-nonefound ~ #mw-search-interwiki .iw-resultset { + width: 30%; + max-width: 300px; + margin-left: 0.5em; + margin-right: 0.5em; +} + +/* mobile */ +@media only screen and ( max-width:768px ) { + #mw-interwiki-results { + width: 100%; + } + .mw-search-results { + max-width: none !important; + } + .iw-resultset { + width: 45% !important; + margin-left: 0.5em !important; + margin-right: 0.5em !important; + } + +} + +@media only screen and ( max-width:600px ) { + .iw-resultset { + width: 100% !important; + margin-left: 0 !important; + margin-right: 0 !important; + max-width: none !important; + } +} diff --git a/resources/src/mediawiki.special/mediawiki.special.search.styles.css b/resources/src/mediawiki.special/mediawiki.special.search.styles.css index ebe9ed94ce..9559f20cd3 100644 --- a/resources/src/mediawiki.special/mediawiki.special.search.styles.css +++ b/resources/src/mediawiki.special/mediawiki.special.search.styles.css @@ -29,13 +29,11 @@ .mw-search-nonefound + .mw-search-interwiki-header { margin-top: 0; } -.searchresult { - font-size: 95%; - max-width: 38em; -} + .mw-search-results { - margin-left: 0; + margin: 0; float: left; + max-width: 60%; } .mw-search-visualclear { clear: both; @@ -93,6 +91,10 @@ float: left; width: 100%; } + +/* Advanced options menu */ +/*==========================*/ + #mw-searchoptions { margin: 0; padding: 0.5em 0.75em 0.75em 0.75em; @@ -127,12 +129,14 @@ padding-left: 6em; font-size: 85%; } + #mw-search-interwiki { float: right; width: 18em; border: 1px solid #a2a9b1; margin-top: 2ex; } + .searchalttitle, #mw-search-interwiki li { font-size: 95%; @@ -153,6 +157,7 @@ background-color: #eaecf0; border-top: 1px solid #c8ccd1; } + .searchdidyoumean { font-size: 127%; margin-top: 0.8em;