Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F4101708
App.vue
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
App.vue
View Options
<template>
<cdx-typeahead-search
:id="id"
ref="searchForm"
class="vector-typeahead-search"
:class="rootClasses"
:search-results-label="$i18n( 'searchresults' ).text()"
:accesskey="searchAccessKey"
:autocapitalize="autocapitalizeValue"
:title="searchTitle"
:placeholder="searchPlaceholder"
:aria-label="searchPlaceholder"
:initial-input-value="searchQuery"
:button-label="$i18n( 'searchbutton' ).text()"
:form-action="action"
:show-thumbnail="showThumbnail"
:highlight-query="highlightQuery"
:auto-expand-width="autoExpandWidth"
:search-results="suggestions"
:search-footer-url="searchFooterUrl"
:visible-item-limit="visibleItemLimit"
@load-more="onLoadMore"
@input="onInput"
@search-result-click="instrumentation.onSuggestionClick"
@submit="onSubmit"
@focus="onFocus"
@blur="onBlur"
>
<template #default>
<input
type="hidden"
name="title"
:value="searchPageTitle"
>
<input
type="hidden"
name="wprov"
:value="wprov"
>
</template>
<template #search-results-pending>
{{ $i18n( 'vector-search-loader' ).text() }}
</template>
<!-- eslint-disable-next-line vue/no-template-shadow -->
<template #search-footer-text="{ searchQuery }">
<span v-i18n-html:vector-searchsuggest-containing="[ searchQuery ]"></span>
</template>
</cdx-typeahead-search>
</template>
<script>
const { CdxTypeaheadSearch } = mw.loader.require( 'skins.vector.search.codex.scripts' ),
{ defineComponent, nextTick } = require( 'vue' ),
client = require( './restSearchClient.js' ),
restClient = client( mw.config ),
urlGenerator = require( './urlGenerator.js' )( mw.config ),
instrumentation = require( './instrumentation.js' );
// @vue/component
module.exports = exports = defineComponent( {
name: 'App',
compatConfig: {
MODE: 3
},
compilerOptions: {
whitespace: 'condense'
},
components: { CdxTypeaheadSearch },
props: {
id: {
type: String,
required: true
},
autocapitalizeValue: {
type: String,
default: undefined
},
searchPageTitle: {
type: String,
default: 'Special:Search'
},
autofocusInput: {
type: Boolean,
default: false
},
action: {
type: String,
default: ''
},
/** The keyboard shortcut to focus search. */
searchAccessKey: {
type: String,
default: undefined
},
/** The access key informational tip for search. */
searchTitle: {
type: String,
default: undefined
},
/** The ghost text shown when no search query is entered. */
searchPlaceholder: {
type: String,
default: undefined
},
/**
* The search query string taken from the server-side rendered input immediately before
* client render.
*/
searchQuery: {
type: String,
default: undefined
},
showThumbnail: {
type: Boolean,
required: true,
default: false
},
showDescription: {
type: Boolean,
default: false
},
highlightQuery: {
type: Boolean,
default: false
},
autoExpandWidth: {
type: Boolean,
default: false
}
},
data() {
return {
// -1 here is the default "active suggestion index".
wprov: instrumentation.getWprovFromResultIndex( -1 ),
// Suggestions to be shown in the TypeaheadSearch menu.
suggestions: [],
// Link to the search page for the current search query.
searchFooterUrl: '',
// The current search query. Used to detect whether a fetch response is stale.
currentSearchQuery: '',
// Whether to apply a CSS class that disables the CSS transitions on the text input
disableTransitions: this.autofocusInput,
instrumentation: instrumentation.listeners,
isFocused: false
};
},
computed: {
rootClasses() {
return {
'vector-search-box-disable-transitions': this.disableTransitions,
'vector-typeahead-search--active': this.isFocused
};
},
visibleItemLimit() {
// if the search client supports loading more results,
// show 7 out of 10 results at first (arbitrary number),
// so that scroll events are fired and trigger onLoadMore()
return restClient.loadMore ? 7 : null;
}
},
methods: {
/**
* Fetch suggestions when new input is received.
*
* @param {string} value
*/
onInput: function ( value ) {
const query = value.trim();
this.currentSearchQuery = query;
if ( query === '' ) {
this.suggestions = [];
this.searchFooterUrl = '';
return;
}
this.updateUIWithSearchClientResult(
restClient.fetchByTitle( query, 10, this.showDescription ),
true
);
},
/**
* Fetch additional suggestions.
*
* This should only be called if visibleItemLimit is non-null,
* i.e. if the search client supports loading more results.
*/
onLoadMore() {
if ( !restClient.loadMore ) {
mw.log.warn( 'onLoadMore() should not have been called for this search client' );
return;
}
this.updateUIWithSearchClientResult(
restClient.loadMore(
this.currentSearchQuery,
this.suggestions.length,
10,
this.showDescription
),
false
);
},
/**
* @param {AbortableSearchFetch} search
* @param {boolean} replaceResults
*/
updateUIWithSearchClientResult( search, replaceResults ) {
const query = this.currentSearchQuery;
instrumentation.listeners.onFetchStart();
search.fetch
.then( ( data ) => {
// Only use these results if they're still relevant
// If currentSearchQuery !== query, these results are for a previous search
// and we shouldn't show them.
if ( this.currentSearchQuery === query ) {
if ( replaceResults ) {
this.suggestions = [];
}
this.suggestions.push(
...instrumentation.addWprovToSearchResultUrls(
data.results, this.suggestions.length
)
);
this.searchFooterUrl = urlGenerator.generateUrl( query );
}
const event = {
numberOfResults: data.results.length,
query: query
};
instrumentation.listeners.onFetchEnd( event );
} )
.catch( () => {
// TODO: error handling
} );
},
/**
* @param {SearchSubmitEvent} event
*/
onSubmit( event ) {
this.wprov = instrumentation.getWprovFromResultIndex( event.index );
instrumentation.listeners.onSubmit( event );
},
onFocus() {
this.isFocused = true;
},
onBlur() {
this.isFocused = false;
}
},
mounted() {
if ( this.autofocusInput ) {
this.$refs.searchForm.focus();
nextTick( () => {
this.disableTransitions = false;
} );
}
}
} );
</script>
File Metadata
Details
Attached
Mime Type
text/html
Expires
Tue, Aug 18, 17:05 (3 w, 4 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
15/24/0d57971d91d306cb1d3d43e1c4a9
Default Alt Text
App.vue (6 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment