sogo/UI/WebServerResources/js/Common/sgSearch.directive.js
Francis Lachapelle eb90760b39 Use address books search fields in Contacts module
Searches can now be scoped to one or multiple fields. Those fields are
now dynamic and can be defined using SearchFieldNames in external
contacts sources (SQL and LDAP).
2017-11-21 15:56:16 -05:00

156 lines
4.8 KiB
JavaScript

/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
(function() {
/* jshint validthis: true */
'use strict';
/*
* sgSearch - Search within a list of items
* @memberof SOGo.Common
* @restrict attribute
* @param {function} sgSearch - the function to call when performing a search.
* Two variables are available: searchField and searchText.
* @example:
<div sg-search="mailbox.$filter({ sort: 'date', asc: false }, [{ searchBy: searchField, searchInput: searchText }])">
<md-button class="sg-icon-button"
sg-search-cancel="ctrl.cancelSearch()">
<md-icon>arrow_back</md-icon>
</md-button>
<md-input-container>
<input name="search" type="search"/>
</md-input-container>
<md-select multiple>
<md-option value="subject">Subject</md-option>
<md-option value="sender">sender</md-option>
</md-select>
</div>
*/
sgSearchPreTransclude.$inject = ['$parse'];
function sgSearchPreTransclude($parse) {
return {
restrict: 'A',
controller: 'sgSearchController',
controllerAs: '$sgSearchController',
priority: 1001,
compile: compile
};
function compile(tElement, tAttr) {
var mdInputEl = tElement.find('md-input-container'),
inputEl = tElement.find('input'),
selectEl = tElement.find('md-select'),
buttonEl = tElement.find('md-button');
inputEl.attr('ng-model', '$sgSearchController.searchText');
inputEl.attr('ng-model-options', '$sgSearchController.searchTextOptions');
inputEl.attr('ng-change', '$sgSearchController.onChange()');
if (selectEl) {
selectEl.attr('ng-model', '$sgSearchController.searchField');
selectEl.attr('ng-change', '$sgSearchController.onChange()');
}
if (buttonEl && buttonEl.attr('sg-search-cancel')) {
buttonEl.attr('ng-click', buttonEl.attr('sg-search-cancel'));
buttonEl.removeAttr('sg-search-cancel');
}
else {
buttonEl = null;
}
return function postLink(scope, iElement, iAttr, controller) {
var compiledButtonEl = iElement.find('button');
// Retrive the form and input names to check the form's validity in the controller
controller.formName = iElement.attr('name');
controller.inputName = inputEl.attr('name');
// Associate the sg-allow-dot parameter (boolean) to the controller
controller.allowDot = $parse(iElement.attr('sg-allow-dot'))(scope);
// Associate the sg-search-fields parameter (array) to the controller
controller.fields = $parse(iElement.attr('sg-search-fields'))(scope);
// Associate callback to controller
controller.doSearch = $parse(iElement.attr('sg-search'));
// Reset the input field when cancelling the search
if (buttonEl && compiledButtonEl) {
compiledButtonEl.on('click', controller.cancelSearch);
}
};
}
}
function sgSearch() {
return {
restrict: 'A',
priority: 1000,
transclude: true,
compile: compile
};
function compile(tElement, tAttr) {
return function postLink(scope, iElement, iAttr, controller, transclude) {
transclude(function(clone) {
iElement.append(clone);
});
};
}
}
/**
* @ngInject
*/
sgSearchController.$inject = ['$window', '$scope', '$element'];
function sgSearchController($window, $scope, $element) {
var vm = this;
// Controller variables
vm.searchText = null;
// Model options
vm.searchTextOptions = {
updateOn: 'default blur',
debounce: {
default: 300,
blur: 0
}
};
if ($element.attr('sg-search-fields')) {
var waitforFieldsOnce = $scope.$watch(vm.fields, function(value) {
// Select all fields by default
vm.searchField = _.clone(vm.fields);
waitforFieldsOnce();
});
}
// Method to call on data changes
vm.onChange = function() {
var form = $scope[vm.formName],
input = form[vm.inputName],
rawSearchText = input.$viewValue;
if (vm.allowDot && rawSearchText == '.' || form.$valid && rawSearchText) {
if (rawSearchText == '.')
// Ignore the minlength constraint when using the dot operator
input.$setValidity('minlength', true);
// doSearch is the compiled expression of the sg-search attribute
vm.doSearch($scope, { searchText: rawSearchText, searchField: vm.searchField });
}
};
// Reset input field when cancelling the search
vm.cancelSearch = function() {
vm.searchText = null;
};
}
angular
.module('SOGo.Common')
.controller('sgSearchController', sgSearchController)
.directive('sgSearch', sgSearchPreTransclude)
.directive('sgSearch', sgSearch);
})();