31
31
C_SEARCH_SLOT = getCN(PICKER, 'search-slot'),
32
32
C_FOOTER_SLOT = getCN(PICKER, 'footer-slot'),
33
33
C_SEARCH_MODE = getCN(PICKER, 'search-mode'),
34
C_FILTER = getCN(PICKER, 'filter'),
34
35
C_RESULTS = getCN(PICKER, 'results'),
35
36
C_RESULT_TITLE = getCN(PICKER, 'result-title'),
36
37
C_RESULT_DESCRIPTION = getCN(PICKER, 'result-description'),
61
62
ASSOCIATED_FIELD_ID = 'associated_field_id',
62
63
SELECTED_VALUE = 'selected_value',
63
SELECTED_VALUE_METADATA = 'selected_value_metadata';
64
SELECTED_VALUE_METADATA = 'selected_value_metadata',
65
FILTER_OPTIONS = 'filter_options',
66
CURRENT_FILTER_VALUE = 'current_filter_value';
66
69
var Picker = function () {
200
212
if (Y.Lang.isValue(cfg[SELECTED_VALUE])) {
201
213
this.set(SELECTED_VALUE, cfg[SELECTED_VALUE]);
215
// Optional filter support
216
if (Y.Lang.isValue(cfg[FILTER_OPTIONS])) {
217
this.set(FILTER_OPTIONS, cfg[FILTER_OPTIONS]);
218
if (Y.Lang.isValue(cfg[CURRENT_FILTER_VALUE])) {
219
this.set(CURRENT_FILTER_VALUE, cfg[CURRENT_FILTER_VALUE]);
422
441
if (data.badges) {
423
442
var badges = Y.Node.create('<div>Affiliation:</div>')
424
443
.addClass('badge');
425
var already_processed = new Array();
444
var already_processed = [];
426
445
Y.each(data.badges, function(badge_info) {
427
446
var badge_url = badge_info.url;
428
447
var badge_alt = badge_info.alt;
532
551
// Remove any previous results.
533
552
Y.Event.purgeElement(this._results_box, true);
534
553
this._results_box.set('innerHTML', '');
554
this._filter_box.set('innerHTML', '');
536
556
var expander_id = this.get(BOUNDING_BOX).get('id');
537
557
Y.Array.each(results, function(data, i) {
586
606
{query: this._search_input.get('value')})));
587
607
this._results_box.appendChild(msg);
588
608
this._results_box.addClass(C_NO_RESULTS);
609
this._syncFilterUI();
590
611
this._results_box.removeClass(C_NO_RESULTS);
612
if (results.length) {
613
var filters = this.get(FILTER_OPTIONS);
614
var current_filter_value = this.get(CURRENT_FILTER_VALUE);
615
if (filters.length > 0 &&
616
!Y.Lang.isValue(current_filter_value)) {
617
this.set(CURRENT_FILTER_VALUE, filters[0].title);
619
this._syncFilterUI();
593
623
if (results.length) {
633
* Update the filter UI based on the current filter value used for the
636
_syncFilterUI: function() {
637
// Check that we need to display the filter UI.
638
var filters = this.get(FILTER_OPTIONS);
639
if( filters.length === 0 ) {
642
var current_filter_value = this.get(CURRENT_FILTER_VALUE);
643
if (!Y.Lang.isValue(current_filter_value)) {
647
var filter_msg = Y.substitute(
648
'Showing <strong>{filter}</strong> matches for "{search_terms}".',
649
{filter: current_filter_value,
650
search_terms: this._search_input.get('value')});
651
this._filter_box.appendChild(Y.Node.create(filter_msg));
653
var filter_node = Y.Node.create('<div>Filter by: </div>');
655
Y.Array.each(filters, function(filter, i) {
656
var filter_link = Y.Node.create('<a></a>')
658
.set('text', filter.title)
659
.set('title', filter.description);
660
if( filter.title === current_filter_value) {
661
filter_link.addClass('invalid-link');
663
filter_link.addClass('js-action');
664
// When a filter link is clicked, we simply fire off a search
666
filter_link.on('click', function (e) {
668
picker.set(CURRENT_FILTER_VALUE, filter.title);
669
var search_string = Y.Lang.trim(
670
picker._search_input.get('value'));
671
picker._performSearch(search_string, filter.name);
674
filter_node.append(filter_link);
675
if (i < filters.length - 2) {
676
filter_node.append(Y.Node.create(', '));
677
} else if (i === filters.length - 2) {
678
filter_node.append(Y.Node.create(', or '));
681
this._filter_box.appendChild(filter_node);
603
685
* Sync UI with search mode. Disable the search input and button.
605
687
* @method _syncSearchModeUI
671
753
this._search_slot_box.addClass(C_SEARCH_SLOT);
672
754
search_box.appendChild(this._search_slot_box);
756
this._filter_box = Y.Node.create('<div></div>');
757
this._filter_box.addClass(C_FILTER);
674
759
this._results_box = Y.Node.create('<ul></ul>');
675
760
this._results_box.addClass(C_RESULTS);
683
768
var body = Y.Node.create('<div></div>');
684
769
body.appendChild(search_box);
770
body.appendChild(this._filter_box);
685
771
body.appendChild(this._results_box);
686
772
body.appendChild(this._batches_box);
687
773
body.appendChild(this._footer_slot_box);
801
887
this.set(BATCHES, null);
802
888
this.set(BATCH_COUNT, null);
803
889
this.set(SELECTED_BATCH, 0);
890
this.set(CURRENT_FILTER_VALUE, null);
804
891
this._search_input.set('value', '');
805
892
this._results_box.set('innerHTML', '');
893
this._filter_box.set('innerHTML', '');
816
904
_defaultSearchUserAction: function(e) {
817
905
e.preventDefault();
906
this.set(CURRENT_FILTER_VALUE, null);
818
907
var search_string = Y.Lang.trim(this._search_input.get('value'));
908
this._performSearch(search_string);
912
* Fires the search event after checking the search string and reseting
913
* the relevant picker data.
915
* @param search_string The search term.
916
* @param filter_name The name of a filter to use to limit the results.
918
_performSearch: function(search_string, filter_name) {
819
919
if (search_string.length < this.get(MIN_SEARCH_CHARS)) {
820
920
var msg = Y.substitute(
821
921
"Please enter at least {min} characters.",
828
928
this.set(SELECTED_BATCH, 0);
830
930
this.set(CURRENT_SEARCH_STRING, search_string);
831
this.fire(SEARCH, search_string);
931
this.fire(SEARCH, search_string, undefined, undefined,
978
1079
current_search_string: {value: ''},
1082
* The string representation of the current filter.
1084
* @attribute current_filter_value
1087
current_filter_value: {value: null},
1090
* A list of attribute name values used to construct the filtering options
1093
* @attribute filter_options
1096
filter_options: {value: []},
981
1099
* The string representation of the value selected by using this picker.
983
1101
* @attribute selected_value