Skip to content
Merged
7 changes: 7 additions & 0 deletions modules/search/instant-search/components/gridicon/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class Gridicon extends Component {
return <title>{ __( 'Has multiple images' ) }</title>;
case 'gridicons-image':
return <title>{ __( 'Has an image' ) }</title>;
case 'gridicons-jetpack-search':
case 'gridicons-search':
return <title>{ __( 'Search' ) }</title>;
case 'gridicons-tag':
Expand Down Expand Up @@ -324,6 +325,12 @@ class Gridicon extends Component {
<path d="M21 19l-5.154-5.154C16.574 12.742 17 11.42 17 10c0-3.866-3.134-7-7-7s-7 3.134-7 7 3.134 7 7 7c1.42 0 2.742-.426 3.846-1.154L19 21l2-2zM5 10c0-2.757 2.243-5 5-5s5 2.243 5 5-2.243 5-5 5-5-2.243-5-5z" />
</g>
);
case 'gridicons-jetpack-search':
return (
<g>
<path d="M12.85 10.85a7 7 0 1 0-2 2L16 18l2-2zm-2-5l-3.49 6.76V5.83zM6.64 1.39v6.78H3.15z" />
</g>
);
case 'gridicons-star-outline':
return (
<g>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import debounce from 'lodash/debounce';
import SearchResults from './search-results';
import SearchFiltersWidget from './search-filters-widget';
import SearchSortWidget from './search-sort-widget';
import SearchBox from './search-box';
import { search, buildFilterAggregations } from '../lib/api';
import {
setSearchQuery,
Expand All @@ -24,7 +25,7 @@ import {
setSortQuery,
getSortQuery,
} from '../lib/query-string';
import { removeChildren, hideSearchHeader } from '../lib/dom';
import { removeChildren, hideElements } from '../lib/dom';

class SearchApp extends Component {
constructor() {
Expand All @@ -38,8 +39,9 @@ class SearchApp extends Component {
query: this.props.initialValue,
sort: this.props.initialSort,
results: {},
loading: false,
};
this.getResults = debounce( this.getResults, 500 );
this.getResults = debounce( this.getResults, 200 );
this.getResults( this.state.query, getFilterQuery(), this.state.sort );
}

Expand All @@ -48,11 +50,15 @@ class SearchApp extends Component {
this.input.current.focus();
}

hideSearchHeader();
removeChildren( document.querySelector( 'main' ) );
hideElements( this.props.themeOptions.elem_selectors );
removeChildren( document.querySelector( this.props.themeOptions.results_selector ) );
this.props.widgets.forEach( function( widget ) {
removeChildren( document.getElementById( widget.widget_id ) );
} );
const searchForms = document.querySelectorAll( this.props.themeOptions.search_form_selector );
searchForms.forEach( function( elem ) {
removeChildren( elem );
} );
}

onChangeQuery = event => {
Expand All @@ -77,6 +83,9 @@ class SearchApp extends Component {
this.requestId++;
const requestId = this.requestId;

this.setState( {
loading: true,
} );
search( {
aggregations: this.props.aggregations,
filter,
Expand All @@ -86,36 +95,36 @@ class SearchApp extends Component {
sort,
} ).then( results => {
if ( this.requestId === requestId ) {
this.setState( { results } );
this.setState( {
results,
loading: false,
} );
}
} );
} else {
this.setState( { results: [] } );
this.setState( {
results: [],
loading: false,
} );
}
};

render() {
const { query, results } = this.state;
const searchForms = Array.from(
document.querySelectorAll( this.props.themeOptions.search_form_selector )
);
return (
<Preact.Fragment>
{ this.props.widgets.map( ( widget, index ) => (
{ this.props.widgets.map( widget => (
<Portal into={ `#${ widget.widget_id }` }>
<div id={ `${ widget.widget_id }-wrapper` }>
<div className="search-form">
{ /* TODO: Add support for preserving label text */ }
<input
className="search-field"
onInput={ this.onChangeQuery }
ref={ index === 0 ? this.input : null }
type="search"
value={ query }
<SearchBox
onChangeQuery={ this.onChangeQuery }
appRef={ this.input }
query={ query }
/>
<button type="submit" className="search-submit">
<svg className="icon icon-search" aria-hidden="true" role="img">
<use href="#icon-search" />
</svg>
<span className="screen-reader-text">Search</span>
</button>
</div>
<div className="jetpack-search-sort-wrapper">
<SearchSortWidget
Expand All @@ -126,6 +135,7 @@ class SearchApp extends Component {
<SearchFiltersWidget
initialValues={ this.props.initialFilters }
onChange={ this.onChangeFilter }
loading={ this.state.loading }
postTypes={ this.props.options.postTypes }
results={ this.state.results }
widget={ widget }
Expand All @@ -134,9 +144,21 @@ class SearchApp extends Component {
</Portal>
) ) }

<Portal into="main">
{ searchForms &&
searchForms.map( elem => (
<Portal into={ elem }>
<SearchBox
onChangeQuery={ this.onChangeQuery }
appRef={ this.input }
query={ query }
/>
</Portal>
) ) }

<Portal into={ this.props.themeOptions.results_selector }>
<SearchResults
query={ query }
loading={ this.state.loading }
{ ...results }
result_format={ this.props.options.resultFormat }
/>
Expand Down
30 changes: 30 additions & 0 deletions modules/search/instant-search/components/search-box.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/** @jsx h */

/**
* External dependencies
*/
import { h, Component } from 'preact';
import { __ } from '@wordpress/i18n';

class SearchBox extends Component {
render() {
const { query, onChangeQuery, appRef } = this.props;

return (
<div className={ 'jp-instant-search__box' }>
{ /* TODO: Add support for preserving label text */ }
<span className="screen-reader-text">{ __( 'Search', 'jetpack' ) }</span>
<input
className="search-field jp-instant-search__box-input"
onInput={ onChangeQuery }
ref={ appRef }
placeholder={ __( 'Search…', 'jetpack' ) }
type="search"
value={ query }
/>
</div>
);
}
}

export default SearchBox;
8 changes: 8 additions & 0 deletions modules/search/instant-search/components/search-box.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* apply to all the inputs to try and pick up any theme styling */
.jp-instant-search__box input {
border-radius: 2px;
font-size: 14px;
height: 26px;
width: 100%;
line-height: 1.2em;
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,13 @@ export default class SearchFiltersWidget extends Component {

render() {
const aggregations = get( this.props.results, 'aggregations' );
const cls =
this.props.loading === true
? 'jetpack-instant-search__filters-widget jetpack-instant-search__is-loading'
: 'jetpack-instant-search__filters-widget';

return (
<div className="jetpack-instant-search__filters-widget">
<div className={ cls }>
{ get( this.props.widget, 'filters' )
.map( configuration =>
aggregations
Expand Down
26 changes: 16 additions & 10 deletions modules/search/instant-search/components/search-results.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/**
* External dependencies
*/
import { __, sprintf } from '@wordpress/i18n';
import { __, _n, sprintf } from '@wordpress/i18n';
import { h, Component } from 'preact';

/**
Expand All @@ -23,33 +23,39 @@ class SearchResults extends Component {
}

render() {
const { results = [], query, total = 0, corrected_query = false } = this.props;
const { results = [], query, total = 0, corrected_query = false, loading = false } = this.props;
if ( query === '' ) {
return <div className="jetpack-instant-search__search-results" />;
}
if ( total === 0 ) {
return (
<div className="jetpack-instant-search__search-results">
<div>
<h3>{ sprintf( __( 'No Results.' ), query ) }</h3>
<h3>{ sprintf( __( 'No Results.', 'jetpack' ), query ) }</h3>
</div>
</div>
);
}
const num = new Intl.NumberFormat().format( total );
const cls =
loading === true
? 'jetpack-instant-search__search-results jetpack-instant-search__is-loading'
: 'jetpack-instant-search__search-results';

return (
<div className="jetpack-instant-search__search-results">
<span className="jetpack-instant-search__search-results-count">
{ sprintf( __( '%d Results' ), total ) }
</span>
<div className={ cls }>
<p className="jetpack-instant-search__search-results-real-query">
{ corrected_query !== false
? sprintf( __( 'Showing results for "%s"' ), corrected_query )
: sprintf( __( 'Results for "%s"' ), query ) }
? sprintf(
_n( 'Showing %s result for "%s"', 'Showing %s results for "%s"', total ),
num,
corrected_query
)
: sprintf( _n( '%s results for "%s"', '%s results for "%s"', total ), num, query ) }
</p>
{ corrected_query !== false && (
<p className="jetpack-instant-search__search-results-unused-query">
{ sprintf( __( 'No results for "%s"' ), query ) }
{ sprintf( __( 'No results for "%s"', 'jetpack' ), query ) }
</p>
) }
{ results.map( result => this.render_result( result ) ) }
Expand Down
11 changes: 3 additions & 8 deletions modules/search/instant-search/components/search-results.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
.jetpack-instant-search__search-results {
padding: 0.125em 0;
margin: 1em 0;
padding: 0.125em 2em;
margin: 1em auto;
position: relative;
}

.jetpack-instant-search__search-results-count {
float: right;
margin-left: 0.5em;
display: block;
max-width: 1080px;
}

.jetpack-instant-search__search-results-real-query {
Expand Down
10 changes: 6 additions & 4 deletions modules/search/instant-search/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ import { h, render } from 'preact';
/**
* Internal dependencies
*/
import SearchWidget from './components/search-widget';
import SearchApp from './components/search-app';
import { getSearchQuery, getFilterQuery, getSortQuery } from './lib/query-string';
import { getThemeOptions } from './lib/dom';
import { SERVER_OBJECT_NAME } from './lib/constants';

const injectSearchWidget = grabFocus => {
const injectSearchApp = grabFocus => {
render(
<SearchWidget
<SearchApp
grabFocus={ grabFocus }
initialFilters={ getFilterQuery() }
initialSort={ getSortQuery() }
initialValue={ getSearchQuery() }
options={ window[ SERVER_OBJECT_NAME ] }
themeOptions={ getThemeOptions( window[ SERVER_OBJECT_NAME ] ) }
/>,
document.body
);
Expand All @@ -31,6 +33,6 @@ document.addEventListener( 'DOMContentLoaded', function() {
'siteId' in window[ SERVER_OBJECT_NAME ] &&
document.body.classList.contains( 'search' )
) {
injectSearchWidget();
injectSearchApp();
}
} );
5 changes: 5 additions & 0 deletions modules/search/instant-search/instant-search.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,10 @@
@import './components/search-filters-widget.scss';
@import './components/search-sort-widget.scss';
@import './components/search-result-minimal.scss';
@import './components/search-box.scss';
//@import './components/search-result-engagement.scss';
//@import './components/search-result-product.scss';

.jetpack-instant-search__is-loading {
opacity: 0.2;
}
Loading