2
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2025-09-06 10:50:21 +08:00
discourse/app/assets/javascripts/discourse/components/search-menu.js.es6
2015-09-13 08:56:20 +08:00

162 lines
4.4 KiB
JavaScript

import {searchForTerm, searchContextDescription, isValidSearchTerm } from 'discourse/lib/search';
import DiscourseURL from 'discourse/lib/url';
import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
import showModal from 'discourse/lib/show-modal';
let _dontSearch = false;
export default Ember.Component.extend({
searchService: Ember.inject.service('search'),
classNames: ['search-menu'],
typeFilter: null,
@observes('searchService.searchContext')
contextChanged: function() {
if (this.get('searchService.searchContextEnabled')) {
_dontSearch = true;
this.set('searchService.searchContextEnabled', false);
_dontSearch = false;
}
},
@computed('searchService.searchContext', 'searchService.term', 'searchService.searchContextEnabled')
fullSearchUrlRelative(searchContext, term, searchContextEnabled) {
if (searchContextEnabled && Ember.get(searchContext, 'type') === 'topic') {
return null;
}
let url = '/search?q=' + encodeURIComponent(this.get('searchService.term'));
if (searchContextEnabled) {
if (searchContext.id.toString().toLowerCase() === this.get('currentUser.username_lower') &&
searchContext.type === "private_messages"
) {
url += ' in:private';
} else {
url += encodeURIComponent(" " + searchContext.type + ":" + searchContext.id);
}
}
return url;
},
@computed('fullSearchUrlRelative')
fullSearchUrl(fullSearchUrlRelative) {
if (fullSearchUrlRelative) {
return Discourse.getURL(fullSearchUrlRelative);
}
},
@computed('searchService.searchContext')
searchContextDescription(ctx) {
return searchContextDescription(Em.get(ctx, 'type'), Em.get(ctx, 'user.username') || Em.get(ctx, 'category.name'));
},
@observes('searchService.searchContextEnabled')
searchContextEnabledChanged() {
if (_dontSearch) { return; }
this.newSearchNeeded();
},
// If we need to perform another search
@observes('searchService.term', 'typeFilter')
newSearchNeeded() {
this.set('noResults', false);
const term = this.get('searchService.term')
if (isValidSearchTerm(term)) {
this.set('loading', true);
Ember.run.debounce(this, 'searchTerm', term, this.get('typeFilter'), 400);
} else {
this.setProperties({ content: null });
}
this.set('selectedIndex', 0);
},
searchTerm(term, typeFilter) {
// for cancelling debounced search
if (this._cancelSearch){
this._cancelSearch = null;
return;
}
if (this._search) {
this._search.abort();
}
const searchContext = this.get('searchService.searchContextEnabled') ? this.get('searchService.searchContext') : null;
this._search = searchForTerm(term, { typeFilter, searchContext, fullSearchUrl: this.get('fullSearchUrl') });
this._search.then((content) => {
this.setProperties({ noResults: !content, content });
}).finally(() => {
this.set('loading', false);
this._search = null;
});
},
@computed('typeFilter', 'loading')
showCancelFilter(typeFilter, loading) {
if (loading) { return false; }
return !Ember.isEmpty(typeFilter);
},
@observes('searchService.term')
termChanged() {
this.cancelTypeFilter();
},
actions: {
fullSearch() {
const self = this;
if (this._search) {
this._search.abort();
}
// maybe we are debounced and delayed
// stop that as well
this._cancelSearch = true;
Em.run.later(function() {
self._cancelSearch = false;
}, 400);
const url = this.get('fullSearchUrlRelative');
if (url) {
DiscourseURL.routeTo(url);
}
},
moreOfType(type) {
this.set('typeFilter', type);
},
cancelType() {
this.cancelTypeFilter();
},
showedSearch() {
$('#search-term').focus();
},
showSearchHelp() {
// TODO: @EvitTrout how do we get a loading indicator here?
Discourse.ajax("/static/search_help.html", { dataType: 'html' }).then((model) => {
showModal('searchHelp', { model });
});
},
cancelHighlight() {
this.set('searchService.highlightTerm', null);
}
},
cancelTypeFilter() {
this.set('typeFilter', null);
},
keyDown(e) {
if (e.which === 13 && isValidSearchTerm(this.get('searchService.term'))) {
this.set('visible', false);
this.send('fullSearch');
}
}
});