Skip to content

Commit

Permalink
Adding readOnly option. Closing #119.
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelclay committed Feb 10, 2014
1 parent 2476577 commit 0b5c8ea
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 39 deletions.
2 changes: 2 additions & 0 deletions demo.html
Expand Up @@ -188,6 +188,7 @@ <h2 id="demo">Demo <span class="demo-hint"><i>Try searching for: <b>account</b>,
container : $('#search_box_container'), container : $('#search_box_container'),
query : 'country: "United States" account: 5-samuel "U.S. State": California', query : 'country: "United States" account: 5-samuel "U.S. State": California',
showFacets : true, showFacets : true,
readOnly : false,
unquotable : [ unquotable : [
'text', 'text',
'account', 'account',
Expand Down Expand Up @@ -328,6 +329,7 @@ <h2 id="demo">Demo <span class="demo-hint"><i>Try searching for: <b>account</b>,
query : '', query : '',
minLength : 0, minLength : 0,
showFacets : true, showFacets : true,
readOnly : false,
unquotable : [ unquotable : [
'text', 'text',
'account', 'account',
Expand Down
2 changes: 1 addition & 1 deletion index.html
Expand Up @@ -186,7 +186,7 @@ <h2 id="demo">Demo <span class="demo-hint"><i>Try searching for: <b>account</b>,


<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
$(document).ready(function() { $(document).ready(function() {
var visualSearch = VS.init({ window.visualSearch = VS.init({
container : $('#search_box_container'), container : $('#search_box_container'),
query : 'country: "United States" "U.S. State": "New York" account: 5-samuel', query : 'country: "United States" "U.S. State": "New York" account: 5-samuel',
showFacets : true, showFacets : true,
Expand Down
15 changes: 15 additions & 0 deletions lib/css/workspace.css
Expand Up @@ -42,6 +42,9 @@
min-height: 28px; min-height: 28px;
height: auto; height: auto;
} }
.VS-search.VS-readonly .VS-search-box {
cursor: default;
}
.VS-search .VS-search-box.VS-focus { .VS-search .VS-search-box.VS-focus {
border-color: #acf; border-color: #acf;
-webkit-box-shadow: inset 0px 0px 3px #acf; -webkit-box-shadow: inset 0px 0px 3px #acf;
Expand Down Expand Up @@ -86,6 +89,9 @@
position: absolute; position: absolute;
right: 9px; top: 8px; right: 9px; top: 8px;
} }
.VS-search.VS-readonly .VS-icon-cancel {
display: none;
}


/* ================ */ /* ================ */
/* = Search Facet = */ /* = Search Facet = */
Expand All @@ -100,6 +106,9 @@
height: 20px; height: 20px;
margin: 3px -3px 3px 0; margin: 3px -3px 3px 0;
} }
.VS-search.VS-readonly .search_facet {
padding-left: 0;
}
.VS-search .search_facet.is_selected { .VS-search .search_facet.is_selected {
margin-left: -3px; margin-left: -3px;
-webkit-border-radius: 16px; -webkit-border-radius: 16px;
Expand All @@ -122,6 +131,9 @@
cursor: pointer; cursor: pointer;
padding: 4px 0 0; padding: 4px 0 0;
} }
.VS-search.VS-readonly .search_facet .category {
cursor: default;
}
.VS-search .search_facet.is_selected .category { .VS-search .search_facet.is_selected .category {
margin-left: 3px; margin-left: 3px;
} }
Expand All @@ -148,6 +160,9 @@
.VS-search .search_facet.is_selected input { .VS-search .search_facet.is_selected input {
color: #000; color: #000;
} }
.VS-search.VS-readonly .search_facet .search_facet_remove {
display: none;
}
.VS-search .search_facet .search_facet_remove { .VS-search .search_facet .search_facet_remove {
position: absolute; position: absolute;
left: 0; left: 0;
Expand Down
2 changes: 1 addition & 1 deletion lib/js/templates/search_box.jst
@@ -1,4 +1,4 @@
<div class="VS-search"> <div class="VS-search <% if (readOnly) { %>VS-readonly<% } %>">
<div class="VS-search-box-wrapper VS-search-box"> <div class="VS-search-box-wrapper VS-search-box">
<div class="VS-icon VS-icon-search"></div> <div class="VS-icon VS-icon-search"></div>
<div class="VS-placeholder"></div> <div class="VS-placeholder"></div>
Expand Down
2 changes: 1 addition & 1 deletion lib/js/templates/search_facet.jst
Expand Up @@ -3,7 +3,7 @@
<% } %> <% } %>


<div class="search_facet_input_container"> <div class="search_facet_input_container">
<input type="text" class="search_facet_input ui-menu VS-interface" value="" /> <input type="text" class="search_facet_input ui-menu VS-interface" value="" <% if (readOnly) { %>disabled="disabled"<% } %> />
</div> </div>


<div class="search_facet_remove VS-icon VS-icon-cancel"></div> <div class="search_facet_remove VS-icon VS-icon-cancel"></div>
2 changes: 1 addition & 1 deletion lib/js/templates/search_input.jst
@@ -1 +1 @@
<input type="text" class="ui-menu" /> <input type="text" class="ui-menu" <% if (readOnly) { %>disabled="disabled"<% } %> />
6 changes: 3 additions & 3 deletions lib/js/templates/templates.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions lib/js/views/search_box.js
Expand Up @@ -17,7 +17,7 @@ VS.ui.SearchBox = Backbone.View.extend({
// Creating a new SearchBox registers handlers for re-rendering facets when necessary, // Creating a new SearchBox registers handlers for re-rendering facets when necessary,
// as well as handling typing when a facet is selected. // as well as handling typing when a facet is selected.
initialize : function(options) { initialize : function(options) {
if (options) this.options = options; this.options = _.extend({}, this.options, options);


this.app = this.options.app; this.app = this.options.app;
this.flags = { this.flags = {
Expand All @@ -37,7 +37,9 @@ VS.ui.SearchBox = Backbone.View.extend({


// Renders the search box, but requires placement on the page through `this.el`. // Renders the search box, but requires placement on the page through `this.el`.
render : function() { render : function() {
$(this.el).append(JST['search_box']({})); $(this.el).append(JST['search_box']({
readOnly: this.app.options.readOnly
}));
$(document.body).setMode('no', 'search'); $(document.body).setMode('no', 'search');


return this; return this;
Expand Down Expand Up @@ -212,6 +214,7 @@ VS.ui.SearchBox = Backbone.View.extend({
// allows third-party developers to either clear data asynchronously, or // allows third-party developers to either clear data asynchronously, or
// prior to performing their custom "clear" logic. // prior to performing their custom "clear" logic.
clearSearch : function(e) { clearSearch : function(e) {
if (this.app.options.readOnly) return;
var actualClearSearch = _.bind(function() { var actualClearSearch = _.bind(function() {
this.disableFacets(); this.disableFacets();
this.value(''); this.value('');
Expand Down Expand Up @@ -367,6 +370,7 @@ VS.ui.SearchBox = Backbone.View.extend({
}, },


maybeFocusSearch : function(e) { maybeFocusSearch : function(e) {
if (this.app.options.readOnly) return;
if ($(e.target).is('.VS-search-box') || if ($(e.target).is('.VS-search-box') ||
$(e.target).is('.VS-search-inner') || $(e.target).is('.VS-search-inner') ||
e.type == 'keydown') { e.type == 'keydown') {
Expand All @@ -376,6 +380,7 @@ VS.ui.SearchBox = Backbone.View.extend({


// Bring focus to last input field. // Bring focus to last input field.
focusSearch : function(e, selectText) { focusSearch : function(e, selectText) {
if (this.app.options.readOnly) return;
var view = this.inputViews[this.inputViews.length-1]; var view = this.inputViews[this.inputViews.length-1];
view.enableEdit(selectText); view.enableEdit(selectText);
if (!selectText) view.setCursorAtEnd(-1); if (!selectText) view.setCursorAtEnd(-1);
Expand All @@ -393,6 +398,7 @@ VS.ui.SearchBox = Backbone.View.extend({
// Double-clicking on the search wrapper should select the existing text in // Double-clicking on the search wrapper should select the existing text in
// the last search input. Also start the triple-click timer. // the last search input. Also start the triple-click timer.
highlightSearch : function(e) { highlightSearch : function(e) {
if (this.app.options.readOnly) return;
if ($(e.target).is('.VS-search-box') || if ($(e.target).is('.VS-search-box') ||
$(e.target).is('.VS-search-inner') || $(e.target).is('.VS-search-inner') ||
e.type == 'keydown') { e.type == 'keydown') {
Expand All @@ -409,6 +415,7 @@ VS.ui.SearchBox = Backbone.View.extend({


// Used to show the user is focused on some input inside the search box. // Used to show the user is focused on some input inside the search box.
addFocus : function() { addFocus : function() {
if (this.app.options.readOnly) return;
this.app.options.callbacks.focus(); this.app.options.callbacks.focus();
this.$('.VS-search-box').addClass('VS-focus'); this.$('.VS-search-box').addClass('VS-focus');
}, },
Expand Down
56 changes: 30 additions & 26 deletions lib/js/views/search_facet.js
Expand Up @@ -20,19 +20,21 @@ VS.ui.SearchFacet = Backbone.View.extend({
}, },


initialize : function(options) { initialize : function(options) {
if (options) this.options = options; this.options = _.extend({}, this.options, options);


this.flags = { this.flags = {
canClose : false canClose : false
}; };
_.bindAll(this, 'set', 'keydown', 'deselectFacet', 'deferDisableEdit'); _.bindAll(this, 'set', 'keydown', 'deselectFacet', 'deferDisableEdit');
this.app = this.options.app;
}, },


// Rendering the facet sets up autocompletion, events on blur, and populates // Rendering the facet sets up autocompletion, events on blur, and populates
// the facet's input with its starting value. // the facet's input with its starting value.
render : function() { render : function() {
$(this.el).html(JST['search_facet']({ $(this.el).html(JST['search_facet']({
model : this.model model : this.model,
readOnly: this.app.options.readOnly
})); }));


this.setMode('not', 'editing'); this.setMode('not', 'editing');
Expand Down Expand Up @@ -81,11 +83,11 @@ VS.ui.SearchFacet = Backbone.View.extend({
var originalValue = this.model.get('value'); var originalValue = this.model.get('value');
this.set(ui.item.value); this.set(ui.item.value);
if (originalValue != ui.item.value || this.box.val() != ui.item.value) { if (originalValue != ui.item.value || this.box.val() != ui.item.value) {
if (this.options.app.options.autosearch) { if (this.app.options.autosearch) {
this.search(e); this.search(e);
} else { } else {
this.options.app.searchBox.renderFacets(); this.app.searchBox.renderFacets();
this.options.app.searchBox.focusNextFacet(this, 1, {viewPosition: this.options.order}); this.app.searchBox.focusNextFacet(this, 1, {viewPosition: this.options.order});
} }
} }
return false; return false;
Expand Down Expand Up @@ -156,7 +158,7 @@ VS.ui.SearchFacet = Backbone.View.extend({
var value = this.model.get('value'); var value = this.model.get('value');
var searchTerm = req.term; var searchTerm = req.term;


this.options.app.options.callbacks.valueMatches(category, searchTerm, function(matches, options) { this.app.options.callbacks.valueMatches(category, searchTerm, function(matches, options) {
options = options || {}; options = options || {};
matches = matches || []; matches = matches || [];


Expand Down Expand Up @@ -197,9 +199,9 @@ VS.ui.SearchFacet = Backbone.View.extend({
search : function(e, direction) { search : function(e, direction) {
if (!direction) direction = 1; if (!direction) direction = 1;
this.closeAutocomplete(); this.closeAutocomplete();
this.options.app.searchBox.searchEvent(e); this.app.searchBox.searchEvent(e);
_.defer(_.bind(function() { _.defer(_.bind(function() {
this.options.app.searchBox.focusNextFacet(this, direction, {viewPosition: this.options.order}); this.app.searchBox.focusNextFacet(this, direction, {viewPosition: this.options.order});
}, this)); }, this));
}, },


Expand All @@ -209,6 +211,7 @@ VS.ui.SearchFacet = Backbone.View.extend({
// This method tells all other facets and inputs to disable so it can have // This method tells all other facets and inputs to disable so it can have
// the sole focus. It also prepares the autocompletion menu. // the sole focus. It also prepares the autocompletion menu.
enableEdit : function() { enableEdit : function() {
if (this.app.options.readOnly) return;
if (this.modes.editing != 'is') { if (this.modes.editing != 'is') {
this.setMode('is', 'editing'); this.setMode('is', 'editing');
this.deselectFacet(); this.deselectFacet();
Expand All @@ -218,10 +221,10 @@ VS.ui.SearchFacet = Backbone.View.extend({
} }


this.flags.canClose = false; this.flags.canClose = false;
this.options.app.searchBox.disableFacets(this); this.app.searchBox.disableFacets(this);
this.options.app.searchBox.addFocus(); this.app.searchBox.addFocus();
_.defer(_.bind(function() { _.defer(_.bind(function() {
this.options.app.searchBox.addFocus(); this.app.searchBox.addFocus();
}, this)); }, this));
this.resize(); this.resize();
this.searchAutocomplete(); this.searchAutocomplete();
Expand Down Expand Up @@ -258,7 +261,7 @@ VS.ui.SearchFacet = Backbone.View.extend({
this.box.blur(); this.box.blur();
this.setMode('not', 'editing'); this.setMode('not', 'editing');
this.closeAutocomplete(); this.closeAutocomplete();
this.options.app.searchBox.removeFocus(); this.app.searchBox.removeFocus();
}, },


// Selects the facet, which blurs the facet's input and highlights the facet. // Selects the facet, which blurs the facet's input and highlights the facet.
Expand All @@ -267,7 +270,8 @@ VS.ui.SearchFacet = Backbone.View.extend({
// should delete this facet or just deselect it. // should delete this facet or just deselect it.
selectFacet : function(e) { selectFacet : function(e) {
if (e) e.preventDefault(); if (e) e.preventDefault();
var allSelected = this.options.app.searchBox.allSelected(); if (this.app.options.readOnly) return;
var allSelected = this.app.searchBox.allSelected();
if (this.modes.selected == 'is') return; if (this.modes.selected == 'is') return;


if (this.box.is(':focus')) { if (this.box.is(':focus')) {
Expand All @@ -286,8 +290,8 @@ VS.ui.SearchFacet = Backbone.View.extend({
$(document).unbind('keydown.facet').bind('keydown.facet', this.keydown); $(document).unbind('keydown.facet').bind('keydown.facet', this.keydown);
$(document).unbind('click.facet').one('click.facet', this.deselectFacet); $(document).unbind('click.facet').one('click.facet', this.deselectFacet);
}, this)); }, this));
this.options.app.searchBox.disableFacets(this); this.app.searchBox.disableFacets(this);
this.options.app.searchBox.addFocus(); this.app.searchBox.addFocus();
} }
return false; return false;
}, },
Expand All @@ -301,7 +305,7 @@ VS.ui.SearchFacet = Backbone.View.extend({
if (this.modes.selected == 'is') { if (this.modes.selected == 'is') {
this.setMode('not', 'selected'); this.setMode('not', 'selected');
this.closeAutocomplete(); this.closeAutocomplete();
this.options.app.searchBox.removeFocus(); this.app.searchBox.removeFocus();
} }
$(document).unbind('keydown.facet', this.keydown); $(document).unbind('keydown.facet', this.keydown);
$(document).unbind('click.facet', this.deselectFacet); $(document).unbind('click.facet', this.deselectFacet);
Expand Down Expand Up @@ -340,12 +344,12 @@ VS.ui.SearchFacet = Backbone.View.extend({
var committed = this.model.get('value'); var committed = this.model.get('value');
this.deselectFacet(); this.deselectFacet();
this.disableEdit(); this.disableEdit();
this.options.app.searchQuery.remove(this.model); this.app.searchQuery.remove(this.model);
if (committed && this.options.app.options.autosearch) { if (committed && this.app.options.autosearch) {
this.search(e, -1); this.search(e, -1);
} else { } else {
this.options.app.searchBox.renderFacets(); this.app.searchBox.renderFacets();
this.options.app.searchBox.focusNextFacet(this, -1, {viewPosition: this.options.order}); this.app.searchBox.focusNextFacet(this, -1, {viewPosition: this.options.order});
} }
}, },


Expand All @@ -367,7 +371,7 @@ VS.ui.SearchFacet = Backbone.View.extend({
} else if (key == 'left') { } else if (key == 'left') {
if (this.modes.selected == 'is') { if (this.modes.selected == 'is') {
this.deselectFacet(); this.deselectFacet();
this.options.app.searchBox.focusNextFacet(this, -1, {startAtEnd: -1}); this.app.searchBox.focusNextFacet(this, -1, {startAtEnd: -1});
} else if (this.box.getCursorPosition() == 0 && !this.box.getSelection().length) { } else if (this.box.getCursorPosition() == 0 && !this.box.getSelection().length) {
this.selectFacet(); this.selectFacet();
} }
Expand All @@ -380,27 +384,27 @@ VS.ui.SearchFacet = Backbone.View.extend({
} else if (this.box.getCursorPosition() == this.box.val().length) { } else if (this.box.getCursorPosition() == this.box.val().length) {
e.preventDefault(); e.preventDefault();
this.disableEdit(); this.disableEdit();
this.options.app.searchBox.focusNextFacet(this, 1); this.app.searchBox.focusNextFacet(this, 1);
} }
} else if (VS.app.hotkeys.shift && key == 'tab') { } else if (VS.app.hotkeys.shift && key == 'tab') {
e.preventDefault(); e.preventDefault();
this.options.app.searchBox.focusNextFacet(this, -1, { this.app.searchBox.focusNextFacet(this, -1, {
startAtEnd : -1, startAtEnd : -1,
skipToFacet : true, skipToFacet : true,
selectText : true selectText : true
}); });
} else if (key == 'tab') { } else if (key == 'tab') {
e.preventDefault(); e.preventDefault();
this.options.app.searchBox.focusNextFacet(this, 1, { this.app.searchBox.focusNextFacet(this, 1, {
skipToFacet : true, skipToFacet : true,
selectText : true selectText : true
}); });
} else if (VS.app.hotkeys.command && (e.which == 97 || e.which == 65)) { } else if (VS.app.hotkeys.command && (e.which == 97 || e.which == 65)) {
e.preventDefault(); e.preventDefault();
this.options.app.searchBox.selectAllFacets(); this.app.searchBox.selectAllFacets();
return false; return false;
} else if (VS.app.hotkeys.printable(e) && this.modes.selected == 'is') { } else if (VS.app.hotkeys.printable(e) && this.modes.selected == 'is') {
this.options.app.searchBox.focusNextFacet(this, -1, {startAtEnd: -1}); this.app.searchBox.focusNextFacet(this, -1, {startAtEnd: -1});
this.remove(e); this.remove(e);
} else if (key == 'backspace') { } else if (key == 'backspace') {
$(document).on('keydown.backspace', function(e) { $(document).on('keydown.backspace', function(e) {
Expand Down
9 changes: 6 additions & 3 deletions lib/js/views/search_input.js
Expand Up @@ -19,8 +19,8 @@ VS.ui.SearchInput = Backbone.View.extend({
}, },


initialize : function(options) { initialize : function(options) {
if (options) this.options = options; this.options = _.extend({}, this.options, options);

this.app = this.options.app; this.app = this.options.app;
this.flags = { this.flags = {
canClose : false canClose : false
Expand All @@ -31,7 +31,9 @@ VS.ui.SearchInput = Backbone.View.extend({
// Rendering the input sets up autocomplete, events on focusing and blurring // Rendering the input sets up autocomplete, events on focusing and blurring
// the input, and the auto-grow of the input. // the input, and the auto-grow of the input.
render : function() { render : function() {
$(this.el).html(JST['search_input']({})); $(this.el).html(JST['search_input']({
readOnly: this.app.options.readOnly
}));


this.setMode('not', 'editing'); this.setMode('not', 'editing');
this.setMode('not', 'selected'); this.setMode('not', 'selected');
Expand Down Expand Up @@ -259,6 +261,7 @@ VS.ui.SearchInput = Backbone.View.extend({
// `tripleClickTimer` is counting down, ready to be engaged and intercept // `tripleClickTimer` is counting down, ready to be engaged and intercept
// the click event to force a select all instead. // the click event to force a select all instead.
maybeTripleClick : function(e) { maybeTripleClick : function(e) {
if (this.app.options.readOnly) return;
if (!!this.tripleClickTimer) { if (!!this.tripleClickTimer) {
e.preventDefault(); e.preventDefault();
this.app.searchBox.selectAllFacets(); this.app.searchBox.selectAllFacets();
Expand Down
3 changes: 2 additions & 1 deletion lib/js/visualsearch.js
Expand Up @@ -34,14 +34,15 @@
unquotable : [], unquotable : [],
remainder : 'text', remainder : 'text',
showFacets : true, showFacets : true,
readOnly : false,
callbacks : { callbacks : {
search : $.noop, search : $.noop,
focus : $.noop, focus : $.noop,
blur : $.noop, blur : $.noop,
facetMatches : $.noop, facetMatches : $.noop,
valueMatches : $.noop, valueMatches : $.noop,
clearSearch : $.noop, clearSearch : $.noop,
removedFacet : $.noop, removedFacet : $.noop
} }
}; };
this.options = _.extend({}, defaults, options); this.options = _.extend({}, defaults, options);
Expand Down

0 comments on commit 0b5c8ea

Please sign in to comment.