216 lines
7.0 KiB
JavaScript
216 lines
7.0 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
angular
|
|
.module('MagicSearch')
|
|
.directive('magicOverrides', magicOverrides);
|
|
|
|
/**
|
|
* @ngdoc directive
|
|
* @name MagicSearch:magicOverrides
|
|
* @description
|
|
* A directive to modify and extend Magic Search functionality for use in
|
|
* Horizon.
|
|
*
|
|
* 1. The base Magic Search widget makes Foundation (a responsive front-end
|
|
* framework) specific calls in showMenu and hideMenu. In Horizon we use
|
|
* Bootstrap, therefore we need to override those methods.
|
|
*
|
|
* 2. Added 'facetsChanged' listener so we can notify the base Magic Search
|
|
* widget that new facets are available. Use this if your table has dynamic
|
|
* facets.
|
|
*
|
|
* 3. Due to the current inconsistencies in the APIs, where some support
|
|
* filtering and others do not, we wanted a way to distinguish client-side
|
|
* filtering (searching the visible subset) vs server-side filtering
|
|
* (another server filter query).
|
|
*
|
|
* To support this distinction we overrode the methods 'removeFacet' and
|
|
* 'initfacets' to emit a 'checkFacets' event. Implementers can add property
|
|
* 'isServer' to facets (what triggers the facet icon and color difference).
|
|
*
|
|
* Each table that incorporates Magic Search is responsible for adding
|
|
* property 'isServer' to their facets as they have the intimate knowledge
|
|
* of the API supplying the table data. The setting of this property needs
|
|
* to be done in the Magic Search supporting JavaScript for each table.
|
|
*
|
|
* Example:
|
|
* Set property 'isServer' on facets that you want to render as server
|
|
* facet (server icon, lighter grey color). Note: If the property
|
|
* 'isServer' is not set, then facet renders with client icon and darker
|
|
* grey color.
|
|
*
|
|
* scope.$on('checkFacets', function (event, currentSearch) {
|
|
* angular.forEach(currentSearch, function (facet) {
|
|
* if (apiVersion < 3) {
|
|
* facet.isServer = true;
|
|
* }
|
|
* });
|
|
* });
|
|
*
|
|
* 4. Overrode 'initfacets' to fix refresh/bookmark issue where facets
|
|
* menu wasn't removing facets that were already on URL.
|
|
*
|
|
* @restrict A
|
|
* @scope
|
|
*
|
|
* @example
|
|
* ```
|
|
* <div class="magic-search" magic-overrides>
|
|
* ```
|
|
*/
|
|
function magicOverrides() {
|
|
var directive = {
|
|
restrict: 'A',
|
|
controller: MagicOverridesController
|
|
};
|
|
|
|
MagicOverridesController.$inject = [
|
|
'$element',
|
|
'$scope',
|
|
'$timeout',
|
|
'$window'
|
|
];
|
|
|
|
return directive;
|
|
|
|
function MagicOverridesController($element, $scope, $timeout, $window) {
|
|
|
|
/**
|
|
* showMenu and hideMenu depend on Foundation's dropdown. They need
|
|
* to be modified to work with another dropdown implementation.
|
|
* For Bootstrap, they are not needed at all.
|
|
*/
|
|
$scope.showMenu = function () {
|
|
$timeout(function () {
|
|
$scope.isMenuOpen = true;
|
|
});
|
|
};
|
|
$scope.hideMenu = function () {
|
|
$timeout(function () {
|
|
$scope.isMenuOpen = false;
|
|
});
|
|
};
|
|
$scope.isMenuOpen = false;
|
|
|
|
/**
|
|
* Add ability to update facet
|
|
* Broadcast event when facet options are returned via AJAX.
|
|
* Should magic_search.js absorb this?
|
|
*/
|
|
var facetsChangedWatcher = $scope.$on('facetsChanged', function () {
|
|
$timeout(function () {
|
|
$scope.currentSearch = [];
|
|
$scope.initSearch();
|
|
});
|
|
});
|
|
|
|
$scope.$on('$destroy', function () {
|
|
facetsChangedWatcher();
|
|
});
|
|
|
|
function getFacets(currentFacets) {
|
|
if (angular.isUndefined(currentFacets)) {
|
|
var initialFacets = $window.location.search;
|
|
if (initialFacets.indexOf('?') === 0) {
|
|
initialFacets = initialFacets.slice(1);
|
|
}
|
|
return initialFacets.split('&');
|
|
} else {
|
|
return currentFacets.map(function(facet) {
|
|
return facet.name;
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Override magic_search.js 'initFacets' to fix browser refresh issue
|
|
* and to emit('checkFacets') to flag facets as 'isServer'
|
|
*/
|
|
$scope.initFacets = function(currentFacets) {
|
|
var facets = getFacets(currentFacets);
|
|
|
|
if (facets.length > 1 || (facets[0] && facets[0].length > 0)) {
|
|
$timeout(function () {
|
|
$scope.strings.prompt = '';
|
|
});
|
|
}
|
|
|
|
angular.forEach(facets, function(facet) {
|
|
var facetParts = facet.split('=');
|
|
angular.forEach($scope.facetsObj, function (value) {
|
|
if (value.name == facetParts[0]) {
|
|
if (angular.isUndefined(value.options)) {
|
|
$scope.currentSearch.push({
|
|
'name': facet,
|
|
'label': [value.label, facetParts[1]]
|
|
});
|
|
|
|
/**
|
|
* for refresh case, need to remove facets that were
|
|
* bookmarked/current when browser refresh was clicked
|
|
*/
|
|
$scope.deleteFacetEntirely(facetParts);
|
|
|
|
} else {
|
|
angular.forEach(value.options, function (option) {
|
|
if (option.key == facetParts[1]) {
|
|
$scope.currentSearch.push({
|
|
'name': facet,
|
|
'label': [value.label, option.label]
|
|
});
|
|
if (value.singleton === true) {
|
|
$scope.deleteFacetEntirely(facetParts);
|
|
} else {
|
|
$scope.deleteFacetSelection(facetParts);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
});
|
|
if (angular.isDefined($scope.textSearch)) {
|
|
$scope.currentSearch.push({
|
|
'name': 'text=' + $scope.textSearch,
|
|
'label': [$scope.strings.text, $scope.textSearch]
|
|
});
|
|
}
|
|
$scope.filteredObj = $scope.facetsObj;
|
|
|
|
// broadcast to check facets for server-side
|
|
$scope.$emit('checkFacets', $scope.currentSearch);
|
|
};
|
|
|
|
/**
|
|
* Override magic_search.js 'removeFacet' to emit('checkFacets')
|
|
* to flag facets as 'isServer' after removing facet and
|
|
* either update filter or search
|
|
*/
|
|
$scope.removeFacet = function ($index) {
|
|
var removed = $scope.currentSearch[$index].name;
|
|
$scope.currentSearch.splice($index, 1);
|
|
if (angular.isUndefined($scope.facetSelected)) {
|
|
$scope.emitQuery(removed);
|
|
} else {
|
|
$scope.resetState();
|
|
$element.find('.search-input').val('');
|
|
}
|
|
if ($scope.currentSearch.length === 0) {
|
|
$scope.strings.prompt = $scope.promptString;
|
|
}
|
|
// re-init to restore facets cleanly
|
|
$scope.facetsObj = $scope.copyFacets($scope.facetsSave);
|
|
var currentSearch = angular.copy($scope.currentSearch);
|
|
$scope.currentSearch = [];
|
|
$scope.initFacets(currentSearch);
|
|
|
|
// broadcast to check facets for server-side
|
|
$scope.$emit('checkFacets', $scope.currentSearch);
|
|
};
|
|
|
|
$scope.emitQuery();
|
|
}
|
|
}
|
|
})();
|