source: trunk/web-app/js/ontology-chooser.js @ 591

Last change on this file since 591 was 591, checked in by duh, 9 years ago
  • spinner fix
  • Property svn:keywords set to Date Author Rev
File size: 7.3 KB
Line 
1/**
2 * Ontology chooser JavaScript class
3 *
4 * NCBO wrote it's own cross-site form completion utility
5 * utilizing it's json webservice. However, the service is
6 * no proper json service as it does not return proper json
7 * objects (just a self designed string using | for value
8 * breaks and ~!~ for line breaks. Also, their implementation
9 * conflicts with the table editor. Therefore, I wrote this
10 * cleaner implementation using jquery-ui's autocomplete
11 * functionality.
12 *
13 * Usage:
14 * ------
15 * <input type="text" name="..." rel="ontology-all-name" />
16 *
17 * Where the 'rel' value is the similar as the 'class' value in
18 * the NCBO documentation (bp_form_complete-all-name) but here
19 * we use 'ontology' instead of 'bp_form_complete' to
20 * identify ontology fields.
21 *
22 * @author      Jeroen Wesbeek
23 * @since       20100312
24 * @package     wizard
25 * @requires    jquery, jquery-ui
26 * @see         http://bioportal.bioontology.org/ontologies/
27 * @see         http://bioportal.bioontology.org/search/json_search/?q=musculus
28 *
29 * Revision information:
30 * $Rev: 591 $
31 * $Author: duh $
32 * $Date: 2010-06-18 15:27:24 +0000 (vr, 18 jun 2010) $
33 */
34function OntologyChooser() {
35}
36OntologyChooser.prototype = {
37    cache   : [],           // ontology cache
38    options : {
39        minLength   : 3,    // minimum input length before launching Ajax request
40        showHide    : null, // show / hide this DOM element on select/deselect autocomplete results
41        spinner     : '../images/spinner.gif'
42    },
43
44    /**
45     * initialize object
46     */
47    init: function(options) {
48        var that = this;
49
50        // set class parameters
51        if (options) {
52            $.each(options, function(key,value) {
53                that.options[key] = value;
54            });
55        }
56
57        // hide showHide div?
58        if (this.options.showHide) {
59            this.options.showHide.hide();
60        }
61
62        // find all ontology elements
63        $("input[rel*='ontology']").each(function() {
64            that.initAutocomplete(this);
65        });
66    },
67
68    /**
69     * initialize the ontology autocompleter
70     * @param element
71     */
72    initAutocomplete: function(element) {
73        var that = this
74        var inputElement = $(element);
75        var selected = false;
76
77        // determine what ontology to use
78        var values = inputElement.attr('rel').split("-");
79        var ontology_id = values[1];
80        var target_property = values[2];
81        if (ontology_id == "all") { ontology_id = ""; }
82
83        // http://bioportal.bioontology.org/search/json_search/?q=musculus
84        inputElement.autocomplete({
85            minLength: that.options.minLength,
86            delay: 300,
87            search: function(event, ui) {
88                if (that.options.spinner) {
89                    inputElement.css({ 'background': 'url(' + that.options.spinner + ') no-repeat right top' });
90                }
91                selected = false;
92            },
93            source: function(request, response) {
94                var q = $.trim(request.term);
95                var url = "http://bioportal.bioontology.org/search/json_search/"+ontology_id+"?q=" + request.term + "&response=json&callback=?";
96
97                // got cache?
98                if (that.cache[ q ]) {
99                    // hide spinner
100                    inputElement.css({ 'background': 'none' });
101
102                    // yeah, lucky us! ;-P
103                    response(that.cache[ q ]);
104                } else {
105                    // nope, fetch it from NCBO
106                    $.getJSON(url, function(data) {
107                        // parse result data
108                        var result = that.parseData(data.data);
109
110                        // cache results
111                        that.cache[ q ] = result;
112
113                        // hide spinner
114                        inputElement.css({ 'background': 'none' });
115
116                        // response callback
117                        response(that.parseData(data.data));
118                    });
119                }
120            },
121            select: function(event, ui) {
122                // mark that the user selected a suggestion
123                selected = true;
124
125                // option selected, set hidden fields
126                var element = inputElement;
127
128                // set hidden fields
129                that.setInputValue(element, 'concept_id', ui.item.concept_id);
130                that.setInputValue(element, 'ontology_id', ui.item.ontology_id);
131                that.setInputValue(element, 'full_id', ui.item.full_id);
132
133                // remove error class (if present)
134                element.removeClass('error');
135
136                // show showHide element if set
137                if (that.options.showHide) {
138                    that.options.showHide.show();
139                }
140            },
141            close: function(event, ui) {
142                // check if the user picked something from the ontology suggestions
143                if (!selected) {
144                    // no he didn't, clear the field(s)
145                    var element = inputElement;
146
147                    // set fields
148                    inputElement.val('');
149                    that.setInputValue(element, 'concept_id', '');
150                    that.setInputValue(element, 'ontology_id', '');
151                    that.setInputValue(element, 'full_id', '');
152
153                    // add error class
154                    element.addClass('error');
155                }
156            }
157
158        });
159    },
160
161    /**
162     * Set the value of a particular DOM element
163     * @param inputElement
164     * @param name
165     * @param value
166     */
167    setInputValue: function(inputElement, name, value) {
168        var elementName = inputElement.attr('name') + '-' + name;
169        var searchElement = inputElement.parent().find("input[name='" + elementName + "']");
170
171        // got a text/hidden field in the DOM?
172        if (searchElement.size() > 0) {
173            // yeah, set it
174            $(searchElement[0]).val(value);
175        } else {
176            // no, dynamically insert it after the input element
177            inputElement.after('<input type="hidden" name="' + elementName + '" value="' + value + '"/>');
178        }
179    },
180
181    /**
182     * Parse the result data
183     *
184     * Data is in the following format:
185     * Mus musculus musculus|birnlex_161|preferred name|29684|http://bioontology.org/projects/ontologies/birnlex#birnlex_161|Mus musculus musculus|Mus musculus musculus|BIRNLex~!~
186     *
187     * Where | codes for a column break, and ~!~ for
188     * a line break
189     *
190     * @param data
191     * @return array
192     */
193    parseData: function(data) {
194        var parsed = [];
195        var rows = data.split('~!~');
196
197        for (var i=0; i<rows.length; i++) {
198            var row = $.trim(rows[i]);
199            if (row) {
200                var cols = row.split('|');
201
202                parsed[ parsed.length ] = {
203                    value           : cols[0],
204                    label           : cols[0] + ' <span class="about">(' + cols[2] + ')</span> <span class="from">from: ' + cols[ (cols.length-1) ] + '</span>',
205                    preferred_name  : cols[0],  // e.g. Mus musculus musculus
206                    concept_id      : cols[1],  // e.g. birnlex_161
207                    ontology_id     : cols[3],  // e.g. 29684
208                    full_id         : cols[4]   // e.g. http://bioontology.org/projects/ontologies/birnlex#birnlex_161
209                }
210            }
211        }
212
213        return parsed;
214    }
215}
Note: See TracBrowser for help on using the repository browser.