Skip to content

Commit

Permalink
feat(contactChips): Add md-highlight-flags support.
Browse files Browse the repository at this point in the history
Contact Chips currently allows the use of `md-highlight-text` to
match the search text. Users have requested we add
`md-highlight-flags` as well so that the highlighted text can
match the search field parameters.

Mainly, if a match is found with case-insensitive search, it
would be nice if the highlight text was also case-insensitive.

fixes angular#3182. closes angular#4278.
  • Loading branch information
topherfangio authored and kennethcachia committed Sep 23, 2015
1 parent b1e7574 commit 1f45db7
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 106 deletions.
59 changes: 37 additions & 22 deletions src/components/chips/contact-chips.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ describe('<md-contact-chips>', function() {
md-contact-name="name"\
md-contact-image="image"\
md-contact-email="email"\
md-highlight-flags="i"\
placeholder="To">\
</md-contact-chips>';

Expand All @@ -31,6 +32,8 @@ describe('<md-contact-chips>', function() {
}
];
scope.contacts = [];

scope.highlightFlags = "i";
}));

var attachedElements = [];
Expand All @@ -42,26 +45,34 @@ describe('<md-contact-chips>', function() {
});

describe('basic functionality', function() {
it('should show the placeholder', inject(function($timeout) {
it('should show the placeholder', inject(function() {
var element = buildChips(CONTACT_CHIPS_TEMPLATE);
var ctrl = element.controller('mdContactChips');
$timeout.flush();

expect(element.find('input').length).toBe(1);
expect(element.find('input')[0].placeholder).toBe('To');
}));

it('binds the md-highlight-flags to the controller', function() {
var element = buildChips(CONTACT_CHIPS_TEMPLATE);
var ctrl = element.controller('mdContactChips');

expect(ctrl.highlightFlags).toEqual('i');
});

describe('filtering selected items', function() {
it('should filter', inject(function($timeout) {
it('should filter', inject(function() {
scope.querySearch = jasmine.createSpy('querySearch').and.callFake(function(q) {
return scope.allContacts;
});
scope.contacts.push(scope.allContacts[2]);

var element = buildChips(CONTACT_CHIPS_TEMPLATE);
var ctrl = element.controller('mdContactChips');
$timeout.flush();

var autocompleteElement = element.find('md-autocomplete');
var autocompleteCtrl = autocompleteElement.controller('mdAutocomplete');

element.scope().$apply(function() {
autocompleteCtrl.scope.searchText = 'NAME';
autocompleteCtrl.keydown({});
Expand All @@ -72,25 +83,25 @@ describe('<md-contact-chips>', function() {
}));

/* it('should not filter when disabled', inject(function($timeout) {
scope.querySearch = jasmine.createSpy('querySearch').and.callFake(function(q) {
return scope.allContacts;
});
scope.contacts.push(scope.allContacts[2]);
scope.filterSelected = false;
var element = buildChips(CONTACT_CHIPS_TEMPLATE);
var ctrl = element.controller('mdContactChips');
$timeout.flush();
scope.querySearch = jasmine.createSpy('querySearch').and.callFake(function(q) {
return scope.allContacts;
});
scope.contacts.push(scope.allContacts[2]);
scope.filterSelected = false;
var element = buildChips(CONTACT_CHIPS_TEMPLATE);
var ctrl = element.controller('mdContactChips');
$timeout.flush();
var autocompleteElement = element.find('md-autocomplete');
var autocompleteCtrl = autocompleteElement.controller('mdAutocomplete');
element.scope().$apply(function() {
autocompleteCtrl.scope.searchText = 'NAME';
autocompleteCtrl.keydown({});
});
var autocompleteElement = element.find('md-autocomplete');
var autocompleteCtrl = autocompleteElement.controller('mdAutocomplete');
element.scope().$apply(function() {
autocompleteCtrl.scope.searchText = 'NAME';
autocompleteCtrl.keydown({});
});
var matches = autocompleteCtrl.matches;
expect(matches.length).toBe(3);
}));*/
var matches = autocompleteCtrl.matches;
expect(matches.length).toBe(3);
}));*/
});

});
Expand All @@ -101,11 +112,15 @@ describe('<md-contact-chips>', function() {

function buildChips(str) {
var container;
inject(function($compile) {

inject(function($compile, $timeout) {
container = $compile(str)(scope);
container.scope().$apply();
$timeout.flush();
});

attachedElements.push(container);

return container;
}

Expand Down
1 change: 1 addition & 0 deletions src/components/chips/demoContactChips/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
md-contact-image="image"
md-contact-email="email"
md-require-match="true"
md-highlight-flags="i"
filter-selected="ctrl.filterSelected"
placeholder="To">
</md-contact-chips>
Expand Down
173 changes: 89 additions & 84 deletions src/components/chips/js/contactChipsDirective.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,57 @@
angular
.module('material.components.chips')
.directive('mdContactChips', MdContactChips);
angular
.module('material.components.chips')
.directive('mdContactChips', MdContactChips);

/**
* @ngdoc directive
* @name mdContactChips
* @module material.components.chips
*
* @description
* `<md-contact-chips>` is an input component based on `md-chips` and makes use of an
* `md-autocomplete` element. The component allows the caller to supply a query expression
* which returns a list of possible contacts. The user can select one of these and add it to
* the list of chips.
*
* @param {string=|object=} ng-model A model to bind the list of items to
* @param {string=} placeholder Placeholder text that will be forwarded to the input.
* @param {string=} secondary-placeholder Placeholder text that will be forwarded to the input,
* displayed when there is at least on item in the list
* @param {expression} md-contacts An expression expected to return contacts matching the search
* test, `$query`.
* @param {string} md-contact-name The field name of the contact object representing the
* contact's name.
* @param {string} md-contact-email The field name of the contact object representing the
* contact's email address.
* @param {string} md-contact-image The field name of the contact object representing the
* contact's image.
*
*
* // The following attribute has been removed but may come back.
* @param {expression=} filter-selected Whether to filter selected contacts from the list of
* suggestions shown in the autocomplete.
*
*
*
* @usage
* <hljs lang="html">
* <md-contact-chips
* ng-model="ctrl.contacts"
* md-contacts="ctrl.querySearch($query)"
* md-contact-name="name"
* md-contact-image="image"
* md-contact-email="email"
* placeholder="To">
* </md-contact-chips>
* </hljs>
*
*/
/**
* @ngdoc directive
* @name mdContactChips
* @module material.components.chips
*
* @description
* `<md-contact-chips>` is an input component based on `md-chips` and makes use of an
* `md-autocomplete` element. The component allows the caller to supply a query expression which
* returns a list of possible contacts. The user can select one of these and add it to the list of
* chips.
*
* You may also use the `md-highlight-text` directive along with it's parameters to control the
* appearance of the matched text inside of the contacts' autocomplete popup.
*
* @param {string=|object=} ng-model A model to bind the list of items to
* @param {string=} placeholder Placeholder text that will be forwarded to the input.
* @param {string=} secondary-placeholder Placeholder text that will be forwarded to the input,
* displayed when there is at least on item in the list
* @param {expression} md-contacts An expression expected to return contacts matching the search
* test, `$query`.
* @param {string} md-contact-name The field name of the contact object representing the
* contact's name.
* @param {string} md-contact-email The field name of the contact object representing the
* contact's email address.
* @param {string} md-contact-image The field name of the contact object representing the
* contact's image.
*
*
* // The following attribute has been removed but may come back.
* @param {expression=} filter-selected Whether to filter selected contacts from the list of
* suggestions shown in the autocomplete.
*
*
*
* @usage
* <hljs lang="html">
* <md-contact-chips
* ng-model="ctrl.contacts"
* md-contacts="ctrl.querySearch($query)"
* md-contact-name="name"
* md-contact-image="image"
* md-contact-email="email"
* placeholder="To">
* </md-contact-chips>
* </hljs>
*
*/


var MD_CONTACT_CHIPS_TEMPLATE = '\
var MD_CONTACT_CHIPS_TEMPLATE = '\
<md-chips class="md-contact-chips"\
ng-model="$mdContactChipsCtrl.contacts"\
md-require-match="$mdContactChipsCtrl.requireMatch"\
Expand All @@ -67,7 +70,8 @@
<img \
ng-src="{{item[$mdContactChipsCtrl.contactImage]}}"\
alt="{{item[$mdContactChipsCtrl.contactName]}}" />\
<span class="md-contact-name" md-highlight-text="$mdContactChipsCtrl.searchText">\
<span class="md-contact-name" md-highlight-text="$mdContactChipsCtrl.searchText"\
md-highlight-flags="{{$mdContactChipsCtrl.highlightFlags}}">\
{{item[$mdContactChipsCtrl.contactName]}}\
</span>\
<span class="md-contact-email" >{{item[$mdContactChipsCtrl.contactEmail]}}</span>\
Expand All @@ -86,42 +90,43 @@
</md-chips>';


/**
* MDContactChips Directive Definition
*
* @param $mdTheming
* @returns {*}
* @ngInject
*/
function MdContactChips ($mdTheming, $mdUtil) {
return {
template: function(element, attrs) {
return MD_CONTACT_CHIPS_TEMPLATE;
},
restrict: 'E',
controller: 'MdContactChipsCtrl',
controllerAs: '$mdContactChipsCtrl',
bindToController: true,
compile: compile,
scope: {
contactQuery: '&mdContacts',
placeholder: '@',
secondaryPlaceholder: '@',
contactName: '@mdContactName',
contactImage: '@mdContactImage',
contactEmail: '@mdContactEmail',
contacts: '=ngModel',
requireMatch: '=?mdRequireMatch'
}
};
/**
* MDContactChips Directive Definition
*
* @param $mdTheming
* @returns {*}
* @ngInject
*/
function MdContactChips($mdTheming, $mdUtil) {
return {
template: function(element, attrs) {
return MD_CONTACT_CHIPS_TEMPLATE;
},
restrict: 'E',
controller: 'MdContactChipsCtrl',
controllerAs: '$mdContactChipsCtrl',
bindToController: true,
compile: compile,
scope: {
contactQuery: '&mdContacts',
placeholder: '@',
secondaryPlaceholder: '@',
contactName: '@mdContactName',
contactImage: '@mdContactImage',
contactEmail: '@mdContactEmail',
contacts: '=ngModel',
requireMatch: '=?mdRequireMatch',
highlightFlags: '@?mdHighlightFlags'
}
};

function compile(element, attr) {
return function postLink(scope, element, attrs, controllers) {
function compile(element, attr) {
return function postLink(scope, element, attrs, controllers) {

$mdUtil.initOptionalProperties(scope, attr);
$mdTheming(element);
$mdUtil.initOptionalProperties(scope, attr);
$mdTheming(element);

element.attr('tabindex', '-1');
};
}
element.attr('tabindex', '-1');
};
}
}

0 comments on commit 1f45db7

Please sign in to comment.