update to 0.2.5 of the magic search widget

Update the XStatic Magic Search package, to take
advantage of Eucalyptus' new fixes and features.  Including
allowing multiple Magic Search widgets on same page.

Change-Id: I1328ed868d1278d5cd631bcddcc0c2ba924e65b1
Partial-Bug: #1434710
This commit is contained in:
Rajat Vig 2015-07-15 10:41:38 -07:00
parent 1741baf4a0
commit fc2a3c6985
4 changed files with 93 additions and 48 deletions

View File

@ -11,7 +11,7 @@ NAME = __name__.split('.')[-1] # package name (e.g. 'foo' or 'foo_bar')
# please use a all-lowercase valid python # please use a all-lowercase valid python
# package name # package name
VERSION = '0.2.0' # version of the packaged files, please use the upstream VERSION = '0.2.5' # version of the packaged files, please use the upstream
# version number # version number
BUILD = '1' # our package build number, so we can release new builds BUILD = '1' # our package build number, so we can release new builds
# with fixes for xstatic stuff. # with fixes for xstatic stuff.

View File

@ -1,5 +1,5 @@
<!--! Magic Searchbar --> <!--! Magic Searchbar -->
<div class="magic-search" magic-overrides> <div class="magic-search" magic-overrides="">
<div class="search-bar"> <div class="search-bar">
<i class="fi-filter go"></i> <i class="fi-filter go"></i>
<div class="search-main-area"> <div class="search-main-area">
@ -18,7 +18,7 @@
{{ facetSelected.label[0] }}: {{ facetSelected.label[0] }}:
</span> </span>
<div class="search-entry" is-open="isMenuOpen"> <div class="search-entry" is-open="isMenuOpen">
<input class="search-input" type="text" data-dropdown="facet-drop" dropdown-toggle <input class="search-input" type="text" data-dropdown="facet-drop" dropdown-toggle=""
placeholder="{{ strings.prompt }}" autocomplete="off" /> placeholder="{{ strings.prompt }}" autocomplete="off" />
<ul id="facet-drop" class="f-dropdown dropdown-menu" data-dropdown-content=""> <ul id="facet-drop" class="f-dropdown dropdown-menu" data-dropdown-content="">
<li ng-repeat="facet in filteredObj" ng-show="!facetSelected"> <li ng-repeat="facet in filteredObj" ng-show="!facetSelected">
@ -38,6 +38,7 @@
ng-show="isMatchLabel(option.label)"> ng-show="isMatchLabel(option.label)">
{{ option.label[0] }}<span class="match">{{ option.label[1] }}</span>{{ option.label[2] }} {{ option.label[0] }}<span class="match">{{ option.label[1] }}</span>{{ option.label[2] }}
</a> </a>
</li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@ -23,8 +23,9 @@ angular.module('MagicSearch')
templateUrl: function (scope, elem) { templateUrl: function (scope, elem) {
return elem.template; return elem.template;
}, },
controller: function ($scope, $timeout) { controller: function ($scope, $element, $timeout) {
$scope.promptString = $scope.strings['prompt']; var searchInput = $element.find('.search-input');
$scope.promptString = $scope.strings.prompt;
$scope.currentSearch = []; $scope.currentSearch = [];
$scope.initSearch = function() { $scope.initSearch = function() {
if (typeof $scope.facets_param === 'string') { if (typeof $scope.facets_param === 'string') {
@ -48,7 +49,7 @@ angular.module('MagicSearch')
initialFacets = initialFacets.split('&'); initialFacets = initialFacets.split('&');
if (initialFacets.length > 1 || initialFacets[0].length > 0) { if (initialFacets.length > 1 || initialFacets[0].length > 0) {
$timeout(function() { $timeout(function() {
$scope.strings['prompt'] = ''; $scope.strings.prompt = '';
}); });
} }
angular.forEach(initialFacets, function(facet, idx) { angular.forEach(initialFacets, function(facet, idx) {
@ -76,12 +77,18 @@ angular.module('MagicSearch')
}); });
}); });
if ($scope.textSearch !== undefined) { if ($scope.textSearch !== undefined) {
$scope.currentSearch.push({'name':'text='+$scope.textSearch, 'label':[$scope.strings['text'], $scope.textSearch]}); $scope.currentSearch.push({'name':'text='+$scope.textSearch, 'label':[$scope.strings.text, $scope.textSearch]});
} }
$scope.filteredObj = $scope.facetsObj; $scope.filteredObj = $scope.facetsObj;
}; };
$scope.addFacets = function(facets) {
// add a facets javascript object to the existing list
for (var facet in facets) {
$scope.facetsObj.append(facet);
}
};
$scope.copyFacets = function(facets) { $scope.copyFacets = function(facets) {
var ret = [] var ret = [];
for (var i=0; i<facets.length; i++) { for (var i=0; i<facets.length; i++) {
var facet = Object.create(facets[i]); var facet = Object.create(facets[i]);
if (facets[i].options !== undefined) { if (facets[i].options !== undefined) {
@ -93,7 +100,7 @@ angular.module('MagicSearch')
ret.push(facet); ret.push(facet);
} }
return ret; return ret;
} };
// removes a facet from the menu // removes a facet from the menu
$scope.deleteFacetSelection = function(facetParts) { $scope.deleteFacetSelection = function(facetParts) {
angular.forEach($scope.facetsObj.slice(), function(facet, idx) { angular.forEach($scope.facetsObj.slice(), function(facet, idx) {
@ -121,17 +128,17 @@ angular.module('MagicSearch')
} }
}); });
}; };
$('.search-input').on('keydown', function($event) { // handle ctrl-char input searchInput.on('keydown', function($event) {
var key = $event.keyCode || $event.charCode; var key = $event.keyCode || $event.charCode;
if (key == 9) { // prevent default when we can. if (key == 9) { // prevent default when we can.
$event.preventDefault(); $event.preventDefault();
} }
}); });
$('.search-input').on('keyup', function($event) { // handle ctrl-char input searchInput.on('keyup', function($event) { // handle ctrl-char input
if ($event.metaKey == true) { if ($event.metaKey === true) {
return; return;
} }
var searchVal = $('.search-input').val(); var searchVal = searchInput.val();
var key = $event.keyCode || $event.charCode; var key = $event.keyCode || $event.charCode;
if (key == 9) { // tab, so select facet if narrowed down to 1 if (key == 9) { // tab, so select facet if narrowed down to 1
if ($scope.facetSelected === undefined) { if ($scope.facetSelected === undefined) {
@ -144,14 +151,14 @@ angular.module('MagicSearch')
$scope.resetState(); $scope.resetState();
} }
$timeout(function() { $timeout(function() {
$('.search-input').val(''); searchInput.val('');
}); });
return; return;
} }
if (key == 27) { // esc, so cancel and reset everthing if (key == 27) { // esc, so cancel and reset everthing
$timeout(function() { $timeout(function() {
$scope.hideMenu(); $scope.hideMenu();
$('.search-input').val(''); searchInput.val('');
}); });
$scope.resetState(); $scope.resetState();
var textFilter = $scope.textSearch; var textFilter = $scope.textSearch;
@ -179,10 +186,10 @@ angular.module('MagicSearch')
$scope.currentSearch.splice(i, 1); $scope.currentSearch.splice(i, 1);
} }
} }
$scope.currentSearch.push({'name':'text='+searchVal, 'label':[$scope.strings['text'], searchVal]}); $scope.currentSearch.push({'name':'text='+searchVal, 'label':[$scope.strings.text, searchVal]});
$scope.$apply(); $scope.$apply();
$scope.hideMenu(); $scope.hideMenu();
$('.search-input').val(''); searchInput.val('');
$scope.$emit('textSearch', searchVal, $scope.filter_keys); $scope.$emit('textSearch', searchVal, $scope.filter_keys);
$scope.textSearch = searchVal; $scope.textSearch = searchVal;
} }
@ -191,15 +198,19 @@ angular.module('MagicSearch')
else { else {
if (searchVal === '') { if (searchVal === '') {
$scope.filteredObj = $scope.facetsObj; $scope.filteredObj = $scope.facetsObj;
$scope.$apply();
$scope.$emit('textSearch', '', $scope.filter_keys); $scope.$emit('textSearch', '', $scope.filter_keys);
if ($scope.facetSelected && $scope.facetSelected.options === undefined) {
$scope.resetState();
}
} }
else { else {
$scope.filterFacets(searchVal); $scope.filterFacets(searchVal);
} }
} }
}); });
$('.search-input').on('keypress', function($event) { // handle character input searchInput.on('keypress', function($event) { // handle character input
var searchVal = $('.search-input').val(); var searchVal = searchInput.val();
var key = $event.which || $event.keyCode || $event.charCode; var key = $event.which || $event.keyCode || $event.charCode;
if (key != 8 && key != 46 && key != 13 && key != 9 && key != 27) { if (key != 8 && key != 46 && key != 13 && key != 9 && key != 27) {
searchVal = searchVal + String.fromCharCode(key).toLowerCase(); searchVal = searchVal + String.fromCharCode(key).toLowerCase();
@ -207,13 +218,17 @@ angular.module('MagicSearch')
if (searchVal == ' ') { // space and field is empty, show menu if (searchVal == ' ') { // space and field is empty, show menu
$scope.showMenu(); $scope.showMenu();
$timeout(function() { $timeout(function() {
$('.search-input').val(''); searchInput.val('');
}); });
return; return;
} }
if (searchVal === '') { if (searchVal === '') {
$scope.filteredObj = $scope.facetsObj; $scope.filteredObj = $scope.facetsObj;
$scope.$apply();
$scope.$emit('textSearch', '', $scope.filter_keys); $scope.$emit('textSearch', '', $scope.filter_keys);
if ($scope.facetSelected && $scope.facetSelected.options === undefined) {
$scope.resetState();
}
return; return;
} }
if (key != 8 && key != 46) { if (key != 8 && key != 46) {
@ -267,9 +282,10 @@ angular.module('MagicSearch')
} }
}; };
// enable text entry when mouse clicked anywhere in search box // enable text entry when mouse clicked anywhere in search box
$('.search-main-area').on("click", function($event) { $element.find('.search-main-area').on('click', function($event) {
$('.search-input').trigger("focus"); var target = $($event.target);
if ($scope.facetSelected === undefined) { if (target.is('.search-main-area')) {
searchInput.trigger('focus');
$scope.showMenu(); $scope.showMenu();
} }
}); });
@ -287,11 +303,11 @@ angular.module('MagicSearch')
$scope.showMenu(); $scope.showMenu();
} }
$timeout(function() { $timeout(function() {
$('.search-input').val(''); searchInput.val('');
}); });
$scope.strings['prompt'] = ''; $scope.strings.prompt = '';
$timeout(function() { $timeout(function() {
$('.search-input').focus(); searchInput.focus();
}); });
}; };
// when option clicked, complete facet and send event // when option clicked, complete facet and send event
@ -319,11 +335,12 @@ angular.module('MagicSearch')
} }
if (removed !== undefined && removed.indexOf('text') === 0) { if (removed !== undefined && removed.indexOf('text') === 0) {
$scope.$emit('textSearch', '', $scope.filter_keys); $scope.$emit('textSearch', '', $scope.filter_keys);
$scope.textSearch = undefined $scope.textSearch = undefined;
} }
else { else {
$scope.$emit('searchUpdated', query); $scope.$emit('searchUpdated', query);
if ($scope.currentSearch.length > 0) { if ($scope.currentSearch.length > 0) {
// prune facets as needed from menus
var newFacet = $scope.currentSearch[$scope.currentSearch.length-1].name; var newFacet = $scope.currentSearch[$scope.currentSearch.length-1].name;
var facetParts = newFacet.split('='); var facetParts = newFacet.split('=');
angular.forEach($scope.facetsSave, function(facet, idx) { angular.forEach($scope.facetsSave, function(facet, idx) {
@ -348,10 +365,10 @@ angular.module('MagicSearch')
} }
else { else {
$scope.resetState(); $scope.resetState();
$('.search-input').val(''); searchInput.val('');
} }
if ($scope.currentSearch.length == 0) { if ($scope.currentSearch.length === 0) {
$scope.strings['prompt'] = $scope.promptString; $scope.strings.prompt = $scope.promptString;
} }
// re-init to restore facets cleanly // re-init to restore facets cleanly
$scope.facetsObj = $scope.copyFacets($scope.facetsSave); $scope.facetsObj = $scope.copyFacets($scope.facetsSave);
@ -366,24 +383,26 @@ angular.module('MagicSearch')
$scope.resetState(); $scope.resetState();
$scope.$emit('searchUpdated', ''); $scope.$emit('searchUpdated', '');
$scope.$emit('textSearch', '', $scope.filter_keys); $scope.$emit('textSearch', '', $scope.filter_keys);
$scope.strings['prompt'] = $scope.promptString;
} }
}; };
$scope.isMatchLabel = function(label) { $scope.isMatchLabel = function(label) {
return Array.isArray(label); return Array.isArray(label);
}; };
$scope.resetState = function() { $scope.resetState = function() {
$('.search-input').val(''); searchInput.val('');
$scope.filteredObj = $scope.facetsObj; $scope.filteredObj = $scope.facetsObj;
$scope.facetSelected = undefined; $scope.facetSelected = undefined;
$scope.facetOptions = undefined; $scope.facetOptions = undefined;
$scope.filteredOptions = undefined $scope.filteredOptions = undefined;
if ($scope.currentSearch.length === 0) {
$scope.strings.prompt = $scope.promptString;
}
}; };
// showMenu and hideMenu depend on foundation's dropdown. They need // showMenu and hideMenu depend on foundation's dropdown. They need
// to be modified to work with another dropdown implemenation (i.e. bootstrap) // to be modified to work with another dropdown implemenation (i.e. bootstrap)
$scope.showMenu = function() { $scope.showMenu = function() {
$timeout(function() { $timeout(function() {
if ($('#facet-drop').hasClass('open') === false) { if ($('#facet-drop').hasClass('open') === false && $scope.filteredObj.length > 0) {
$('.search-input').trigger('click'); $('.search-input').trigger('click');
} }
}); });

View File

@ -3,6 +3,8 @@
/*----------------------------------------- /*-----------------------------------------
Colors Colors
----------------------------------------- */ ----------------------------------------- */
$bordercolor: #ccc;
$iconcolor: #6a737b;
$textcolor: #444; $textcolor: #444;
$background: white; $background: white;
$itembackground: #e6e7e8; $itembackground: #e6e7e8;
@ -12,11 +14,13 @@ $itembackground: #e6e7e8;
----------------------------------------- */ ----------------------------------------- */
@mixin item-list { @mixin item-list {
.item-list { .item-list {
margin-bottom: 6px; position: relative;
//top: -0.30rem;
.item { .item {
color: #333; color: #333;
background-color: $itembackground; background-color: $itembackground;
margin-right: 8px; height: 1.3rem;
margin-right: 0.5rem;
a { a {
color: white; color: white;
} }
@ -24,20 +28,31 @@ $itembackground: #e6e7e8;
} }
} }
@-moz-document url-prefix() {
.item-list {
.item {
top: -0.40rem;
}
}
.search-selected {
top: -0.40rem;
}
}
/*----------------------------------------- /*-----------------------------------------
Magic Search bar Magic Search bar
----------------------------------------- */ ----------------------------------------- */
.search-bar { .search-bar {
position: relative; position: relative;
border: 1px solid black; border: 1px solid $bordercolor;
background-color: $background; background-color: $background;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
padding: 4px; padding: 0.25rem;
height: auto; height: auto;
i.fi-filter { i.fi-filter {
color: $textcolor; color: $iconcolor;
position: absolute; position: absolute;
top: 0.5rem; top: 0.35rem;
left: 0.65rem; left: 0.65rem;
} }
.search-main-area { .search-main-area {
@ -47,38 +62,48 @@ $itembackground: #e6e7e8;
cursor: text; cursor: text;
} }
@include item-list; @include item-list;
.item-list { //.item-list {
margin-bottom: 2px; // margin-bottom: 0.125rem;
} //}
.search-selected { .search-selected {
position: relative;
padding-left: 0;
padding-right: 0;
background-color: $background; background-color: $background;
color: $textcolor; color: $textcolor;
} }
.search-entry { .search-entry {
position: relative;
display: inline-block; display: inline-block;
height: 1.5rem; height: 1.5rem;
height: 1.5rem;
} }
.search-input { .search-input {
width: 220px; width: 17.5rem;
border: 0; border: 0;
box-shadow: none; box-shadow: none;
height: 1.5rem; height: 1.5rem;
padding: 3px; padding: 0.25rem;
margin-bottom: 0;
background-color: $background; background-color: $background;
&:focus { &:focus {
box-shadow: none; box-shadow: none;
background-color: $background;
} }
} }
.match { .match {
font-weight: bold; font-weight: bold;
} }
i.cancel { i.cancel {
color: $textcolor; color: $iconcolor;
&:hover { &:hover {
color: darkred; color: darkred;
} }
position: absolute; position: absolute;
top: 0.5rem; top: 0.35rem;
right: 0.65rem; right: 0.65rem;
} }
.f-dropdown.open {
left: 0 !important;
}
} }