AutoSuggest: Make directly clicking a suggestion initiate search
[transitory.git] / Open-ILS / web / js / dojo / openils / widget / AutoSuggest.js
1 if (!dojo._hasResource["openils.widget.AutoSuggest"]) {
2     dojo.provide("openils.widget.AutoSuggest");
3     dojo._hasResource["openils.widget.AutoSuggest"] = true;
4
5     dojo.require("dijit.form.ComboBox");
6     dojo.require("openils.AutoSuggestStore");
7
8     /* Here's a monkey patch to assist in making clicking on a suggestion lead
9      * directly to search. Relies on overridden _startSearch() in the widget
10      * below. */
11     var _orig_onMouseUp = dijit.form._ComboBoxMenu.prototype._onMouseUp;
12     dijit.form._ComboBoxMenu.prototype._onMouseUp = function(evt) {
13         if (this.parent_widget)
14             this.parent_widget.mouse_used_most_recently = true;
15         dojo.hitch(this, _orig_onMouseUp)(evt);
16     };
17
18     dojo.declare(
19         "openils.widget.AutoSuggest", [dijit.form.ComboBox], {
20
21             "labelAttr": "match",
22             "labelType": "html",
23             "searchAttr": "term",
24             "hasDownArrow": false,
25             "autoComplete": false,
26             "searchDelay": 200,
27
28             /* Don't forget to these two parameters when instantiating. */
29             "submitter": function() { console.log("No submitter connected"); },
30             "type_selector": null,  /* see openils.AutoSuggestStore for docs */
31
32             "store_args": {},
33
34             "mouse_used_most_recently": false,
35
36             "_update_search_type_selector": function(id) {  /* cmf id */
37                 if (!this.store.cm_cache.is_done) {
38                     console.warn(
39                         "can't update search type selector; " +
40                         "store doesn't have config.metabib_* caches available"
41                     );
42                     return;
43                 }
44
45                 var f = this.store.cm_cache.cmf[id];
46                 var selector = this.type_selector;
47                 var search_class = f.field_class + "|" + f.name;
48                 var exact = dojo.indexOf(
49                     dojo.map(selector.options, function(o) { return o.value; }),
50                     search_class
51                 );
52
53                 if (exact > 0) {
54                     selector.selectedIndex = exact;
55                 } else {    /* settle for class match if we can get it */
56                     for (var i = 0; i < selector.options.length; i++) {
57                         if (selector.options[i].value.split("|")[0] ==
58                                 f.field_class) {
59                             selector.selectedIndex = i;
60                             break;
61                         }
62                     }
63                 }
64             },
65
66             "_startSearch": function() {
67                 this.inherited(arguments);
68                 this._popupWidget.parent_widget = this;
69             },
70
71             "onChange": function(value) {
72                 if (typeof value.field == "number") {
73                     this._update_search_type_selector(value.field);
74
75                     /* If onChange fires and the following condition is true,
76                      * it must mean that the user clicked on an actual
77                      * suggestion with the mouse.  To match the behavior
78                      * of well known autosuggesting things out there (like
79                      * with Google search), we should actually perform our
80                      * search now.  We also perform our search when the user
81                      * presses enter (handled elsewhere), but not when the user
82                      * selects something and tabs out.  */
83                     if (this.mouse_used_most_recently)
84                         this.submitter();
85                 }
86             },
87
88             "postMixInProperties": function() {
89                 this.inherited(arguments);
90
91                 if (typeof this.submitter == "string")
92                     this.submitter = dojo.hitch(this, this.submitter);
93
94                 if (typeof this.type_selector == "string")
95                     this.type_selector = dojo.byId(this.type_selector);
96
97                 /* Save the instantiator from needing to specify same thing
98                  * twice, even though we need it and the store needs it too.
99                  */
100                 if (this.type_selector && !this.store_args.type_selector)
101                     this.store_args.type_selector = this.type_selector;
102
103                 this.store = new openils.AutoSuggestStore(this.store_args);
104             },
105
106             "postCreate": function() {
107                 this.inherited(arguments);
108
109                 dojo.connect(
110                     this, "onKeyPress", this, function(evt) {
111                         this.mouse_used_most_recently = false;
112                         if (evt.keyCode == dojo.keys.ENTER)
113                             this.submitter();
114                     }
115                 );
116             }
117         }
118     );
119 }