visualsearch.0.4.0.lib.js.utils.search_parser.js Maven / Gradle / Ivy
(function() {
var $ = jQuery; // Handle namespaced jQuery
// Used to extract keywords and facets from the free text search.
var QUOTES_RE = "('[^']+'|\"[^\"]+\")";
var FREETEXT_RE = "('[^']+'|\"[^\"]+\"|[^'\"\\s]\\S*)";
var CATEGORY_RE = FREETEXT_RE + ':\\s*';
VS.app.SearchParser = {
// Matches `category: "free text"`, with and without quotes.
ALL_FIELDS : new RegExp(CATEGORY_RE + FREETEXT_RE, 'g'),
// Matches a single category without the text. Used to correctly extract facets.
CATEGORY : new RegExp(CATEGORY_RE),
// Called to parse a query into a collection of `SearchFacet` models.
parse : function(instance, query) {
var searchFacets = this._extractAllFacets(instance, query);
instance.searchQuery.reset(searchFacets);
return searchFacets;
},
// Walks the query and extracts facets, categories, and free text.
_extractAllFacets : function(instance, query) {
var facets = [];
var originalQuery = query;
while (query) {
var category, value;
originalQuery = query;
var field = this._extractNextField(query);
if (!field) {
category = instance.options.remainder;
value = this._extractSearchText(query);
query = VS.utils.inflector.trim(query.replace(value, ''));
} else if (field.indexOf(':') != -1) {
category = field.match(this.CATEGORY)[1].replace(/(^['"]|['"]$)/g, '');
value = field.replace(this.CATEGORY, '').replace(/(^['"]|['"]$)/g, '');
query = VS.utils.inflector.trim(query.replace(field, ''));
} else if (field.indexOf(':') == -1) {
category = instance.options.remainder;
value = field;
query = VS.utils.inflector.trim(query.replace(value, ''));
}
if (category && value) {
var searchFacet = new VS.model.SearchFacet({
category : category,
value : VS.utils.inflector.trim(value),
app : instance
});
facets.push(searchFacet);
}
if (originalQuery == query) break;
}
return facets;
},
// Extracts the first field found, capturing any free text that comes
// before the category.
_extractNextField : function(query) {
var textRe = new RegExp('^\\s*(\\S+)\\s+(?=' + QUOTES_RE + FREETEXT_RE + ')');
var textMatch = query.match(textRe);
if (textMatch && textMatch.length >= 1) {
return textMatch[1];
} else {
return this._extractFirstField(query);
}
},
// If there is no free text before the facet, extract the category and value.
_extractFirstField : function(query) {
var fields = query.match(this.ALL_FIELDS);
return fields && fields.length && fields[0];
},
// If the found match is not a category and facet, extract the trimmed free text.
_extractSearchText : function(query) {
query = query || '';
var text = VS.utils.inflector.trim(query.replace(this.ALL_FIELDS, ''));
return text;
}
};
})();