Changeset 483

Show
Ignore:
Timestamp:
27-05-10 10:55:53 (4 years ago)
Author:
roberth
Message:

Improved flexibility of the publication chooser and added comments

Location:
trunk
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/views/publication/add.gsp

    r479 r483  
    2121  <script type="text/javascript" src="${resource(dir: 'js', file: 'publication-chooser.js')}"></script> 
    2222  <script type="text/javascript" src="${resource(dir: 'js', file: 'publication-chooser.pubmed.js')}"></script> 
     23  <script type="text/javascript" src="${resource(dir: 'js', file: 'publication-chooser.programminglanguages.js')}"></script> 
    2324 
    2425 </head> 
     
    2627 
    2728 <g:form action="createFromPubmed"> 
    28   <g:textField name="publication" rel="publication-pubmed" /> 
     29  <g:textField name="publication" rel="publication-pubmed" style="width:300px;"/> 
    2930  <g:submitButton name="add" value="Add publication" /> 
    3031 </g:form> 
    31   
     32 
     33 
     34 
    3235 ${errors} 
    3336 ${message} 
    3437 
    3538 <script type="text/javascript"> 
    36         $(document).ready(function() { 
    37           // initialize the ontology chooser 
    38           var chooser = new PublicationChooser(); 
    39  
    40           chooser.init(); 
    41         }); 
     39$(document).ready(function() { 
     40  // initialize the ontology chooser 
     41  PublicationChooser.init(); 
     42}); 
    4243 </script> 
    4344 </body> 
  • trunk/web-app/js/publication-chooser.js

    r479 r483  
    1414 * 
    1515 * Where the 'rel' value has the name 'publication' in the beginning. The text 
    16  * after the dash is used for selecting the database to use. Currently, only 
    17  * Pubmed is supported, that is also the default. 
     16 * after the dash is used for selecting the database to use. Multiple textboxes 
     17 * can be used on one page, also textboxes that search different databases. 
     18 *  
     19 * To initialize the textboxes, put the following javascript on the page.  
     20 *  
     21 *    PublicationChooser.init(); 
     22 *  
     23 * The script must be executed AFTER all textboxes have been loaded. A good way 
     24 * to achieve that is to run the init function in the document.ready event: 
     25 *  
     26 *    $(document).ready(function() { 
     27 *        // initialize the publication chooser(s) 
     28 *        PublicationChooser.init(); 
     29 *    }); 
     30 *  
     31 * Supporting different databases: 
     32 * --------------------------- 
     33 * The databases that can be used are stored in the availableDBs arraymap. This  
     34 * map consists of a key that describes the database to be used, and a value that 
     35 * points to a function to be called when searching for the publications. 
     36 *  
     37 * As such, this class is not able to search any database. In order to make an 
     38 * interface for a database, a new method has to be created that searches for  
     39 * publications, and calls another method with  an array with strings or an  
     40 * object array with label/value properties. This is described on  
     41 * http://jqueryui.com/demos/autocomplete/#option-source 
     42 *  
     43 * The function for searching has the following form: 
     44 *  
     45 *     sourceExample = function( chooserObject, searchterm, response ) { 
     46 *          response( [ 'result1', 'result2' ] ); 
     47 *     } 
     48 * 
     49 * The method takes the following parameters 
     50 * 
     51 *     chooserObject:  reference to the publicationChooser object itself 
     52 *     searchterm:     string with the text that is entered in the textfield 
     53 *     response:       reference to the function to be called when the results 
     54 *                     have been fetched. The parameters are described above 
     55 * 
     56 * After the function has been created, it must be told to the publicationChooser 
     57 * class. 
     58 * 
     59 *     PublicationChooser.prototype.availableDBs[ "example" ] = { 
     60 *         'source': sourceExample 
     61 *     }; 
     62 * 
     63 * This line will provide the PublicationChooser class with the possibility to 
     64 * search in the example database (<input rel="publication-example">), using the 
     65 * function sourceExample. N.B. You can't use a dash in the name of the database 
     66 * since that is used to separate different parts of the rel="" value. 
     67 * 
     68 * In order to do something with the selected result, two other methods can be 
     69 * written; 
     70 * 
     71 *     selectExample = function( chooserObject, inputElement, event, ui ) {} 
     72 *     closeExample = function( chooserObject, inputElement, event, ui ) {} 
     73 * 
     74 * The select method is calles when a user selects an item. The close method is 
     75 * called when a user closes the dropdown, but did not select an item. The parameters 
     76 * are: 
     77 * 
     78 *     chooserObject:  reference to the publicationChooser object itself 
     79 *     inputElement:   reference to the input element 
     80 *     event:          the event that has triggered the call. See http://docs.jquery.com/UI/Autocomplete#events 
     81 *     ui:             the ui reference from jquery. If an item is selected, 
     82 *                     ui.item contains a reference to that item. See http://docs.jquery.com/UI/Autocomplete#events 
     83 * 
     84 * In order to show the elements in the list, there is a render method. This method 
     85 * accepts the item to be rendered, and returns an HTML string to be shown in the list 
     86 * 
     87 *     renderExample = function( item ) {} 
     88 * 
     89 * Of course, these methods must also be presented to the PublicationChooser object. 
     90 * 
     91 *     PublicationChooser.prototype.availableDBs[ "example" ] = { 
     92 *         'source': sourceExample, 
     93 *         'select': selectExample, 
     94 *         'close':  closeExample, 
     95 *         'render': renderExample 
     96 *     }; 
     97 * 
     98 * Example: 
     99 * -------- 
     100 * 
     101 *    sourceProgrammingLanguages = function( chooserObject, searchterm, response ) { 
     102 *        var availableTags = ["c++", "java", "php", "coldfusion", "javascript", "asp", "ruby", "python", "c", "scala", "groovy", "haskell", "perl"]; 
     103 *        var foundTags = $.grep( availableTags, function( tag, i ){ 
     104 *            return ( tag.indexOf( searchterm ) !=-1 ); 
     105 *        } ); 
     106 * 
     107 *        response( foundTags ); 
     108 *    } 
     109 * 
     110 *    selectProgrammingLanguages = function( chooserObject, inputElement, event, ui ) { 
     111 *        alert( "Selected item: " + ui.item.value ); 
     112 *    } 
     113 * 
     114 *    closeProgrammingLanguages = function( chooserObject, inputElement, event, ui ) { 
     115 *       alert( "No selected item" ); 
     116 *    } 
     117 * 
     118 *    renderProgrammingLanguages = function( item ) { 
     119 *        return item.value; 
     120 *    }; 
     121 * 
     122 *    PublicationChooser.prototype.availableDBs[ "programminglanguages" ] = { 
     123 *        'source': sourceProgrammingLanguages, 
     124 *         'close' : closeProgrammingLanguages, 
     125 *         'select': selectProgrammingLanguages, 
     126 *        'render': renderProgrammingLanguages 
     127 *     }; 
     128 * 
     129 * Currently, only Pubmed is supported using publication-chooser.pubmed.js. 
    18130 * Other database can easily be supported. See for example 
    19131 * http://www.ncbi.nlm.nih.gov/bookshelf/br.fcgi?book=helpeutils&part=chapter2&rendertype=table&id=chapter2.chapter2_table1 
     
    33145function PublicationChooser() { 
    34146} 
     147 
     148/** 
     149 * initialize object 
     150 */ 
     151PublicationChooser.init = function() { 
     152    // find all ontology elements 
     153    $("input[rel*='publication']").each(function() { 
     154        new PublicationChooser().initAutocomplete(this); 
     155    }); 
     156}; 
     157 
    35158PublicationChooser.prototype = { 
    36159    minLength       : 3,        // minimum input length before launching Ajax request 
     
    39162    database        : '',       // Default database to be used. As for now, also the only possible database 
    40163    availableDBs    : {},       // Available databases, filled by extensions. Key is databasename and value is reference to method to be called 
    41  
    42     /** 
    43      * initialize object 
    44      */ 
    45     init: function() { 
    46         var that = this; 
    47  
    48         // find all ontology elements 
    49         $("input[rel*='publication']").each(function() { 
    50             that.initAutocomplete(this); 
    51         }); 
    52     }, 
    53  
     164     
    54165    /** 
    55166     * initialize the ontology autocompleter 
     
    72183        } 
    73184 
     185        // Initialize cache for this element 
     186        this.cache[ this.database ] = []; 
     187 
    74188        // Put the autocomplete function on the input field. See jquery-ui 
    75189        inputElement.autocomplete({ 
     
    78192 
    79193            source: function(request, response) { 
    80                         var q = $.trim(request.term); 
    81  
    82                         // Check the cache first 
    83                         if ( that.cache[ q ]) { 
    84                             // yeah, lucky us! ;-P 
    85                             response(that.cache[ q ]); 
    86                         } else { 
    87                             if( that.database != "" ) { 
    88                                 that.availableDBs[ that.database ]( that, q, response ); 
    89                             } 
    90                         } 
     194                var q = $.trim(request.term); 
     195 
     196                // Check the cache first 
     197                if ( that.cache[ that.database ][ q ]) { 
     198                    // yeah, lucky us! ;-P 
     199                    response(that.cache[ that.database ][ q ]); 
     200                } else { 
     201                    if( that.database != "" && that.availableDBs[ that.database ] && that.availableDBs[ that.database ][ 'source' ] ) { 
     202                        that.availableDBs[ that.database ][ 'source' ]( that, q, response ); 
     203                    } 
     204                } 
     205            }, 
     206            search: function(event, ui ) { 
     207                that.selected = false; 
    91208            }, 
    92209            select: function(event, ui) { 
    93210                // mark that the user selected a suggestion 
    94                 selected = true; 
    95  
    96                 // option selected, set hidden fields 
    97                 var element = inputElement; 
    98  
    99                 // set hidden fields 
    100                 that.setInputValue(element, 'title', ui.item.title); 
    101                 that.setInputValue(element, 'authorsList', ui.item.authors.join( ', ' )); 
    102                 that.setInputValue(element, 'pubMedID', ui.item.id); 
    103                 that.setInputValue(element, 'doi', ui.item.doi); 
    104  
    105                 // remove error class (if present) 
    106                 element.removeClass('error'); 
     211                that.selected = true; 
     212 
     213                if( that.database != "" && that.availableDBs[ that.database ] && that.availableDBs[ that.database ][ 'select' ] ) { 
     214                    that.availableDBs[ that.database ][ 'select' ]( that, inputElement, event, ui ); 
     215                } 
    107216            }, 
    108217            close: function(event, ui) { 
    109                 // check if the user picked something from the ontology suggestions 
    110                 if (!selected) { 
    111                     // no he didn't, clear the field(s) 
    112                     var element = inputElement; 
    113  
    114                     // set fields 
    115                     inputElement.val(''); 
    116                     that.setInputValue(element, 'title', ''); 
    117                     that.setInputValue(element, 'authorsList', ''); 
    118                     that.setInputValue(element, 'pubMedID', ''); 
    119  
    120                     // add error class 
    121                     element.addClass('error'); 
     218                if( !that.selected ) { 
     219                    if( that.database != "" && that.availableDBs[ that.database ] && that.availableDBs[ that.database ][ 'close' ] ) { 
     220                        that.availableDBs[ that.database ][ 'close' ]( that, inputElement, event, ui ); 
     221                    } 
    122222                } 
    123223            } 
    124224 
    125         }) 
    126         .data( "autocomplete" )._renderItem = this.renderPublication; 
     225        }); 
     226 
     227        // Enable custom rendering if wanted. Otherwise use renderPublication method 
     228        var renderMethod; 
     229        if( this.database != "" && this.availableDBs[ that.database ] && this.availableDBs[ that.database ][ 'render' ] ) { 
     230            renderMethod = this.availableDBs[ that.database ][ 'render' ];  
     231        } else { 
     232            renderMethod = this.renderPublication; 
     233        } 
     234 
     235        inputElement.data( "autocomplete" )._renderItem = function( ul, item ) {  
     236            return that.renderAutoCompleteText( ul, item, renderMethod( item ) ); 
     237        }; 
     238 
    127239    }, 
    128240 
    129     renderPublication: function( ul, item ) { 
     241    /** 
     242     * Renders a piece of text as a autocomplete menu item 
     243     */ 
     244    renderAutoCompleteText: function( ul, item, text ) { 
    130245        return $( "<li></li>" ) 
    131246                .data( "item.autocomplete", item ) 
    132                 .append( "<a>" + item.title + "<br><span style='font-size: 7pt;' class='authors'>" + item.authors.join( ', ' )+ "</span></a>" ) 
     247                .append( "<a>" + text + "</a>" ) 
    133248                .appendTo( ul ); 
     249    }, 
     250 
     251    /** 
     252     * Default rendering for publications in the autocomplete list 
     253     */ 
     254    renderPublication: function( item ) { 
     255        return item.title + "<br><span style='font-size: 7pt;' class='authors'>" + item.authors.join( ', ' )+ "</span>"; 
    134256    }, 
    135257 
  • trunk/web-app/js/publication-chooser.pubmed.js

    r479 r483  
    2727                         
    2828                        // Save in cache 
    29                         chooserObject.cache[ searchterm ] = parsedData; 
     29                        chooserObject.cache[ chooserObject.database ][ searchterm ] = parsedData; 
    3030 
    3131                        // Return it to jquery 
     
    3737 
    3838}; 
     39 
     40selectPubMed = function( chooserObject, inputElement, event, ui ) { 
     41 
     42    // option selected, set hidden fields 
     43    var element = inputElement; 
     44 
     45    // set hidden fields 
     46    chooserObject.setInputValue(element, 'title', ui.item.title); 
     47    chooserObject.setInputValue(element, 'authorsList', ui.item.authors.join( ', ' )); 
     48    chooserObject.setInputValue(element, 'pubMedID', ui.item.id); 
     49    chooserObject.setInputValue(element, 'doi', ui.item.doi); 
     50 
     51    // remove error class (if present) 
     52    element.removeClass('error'); 
     53}; 
     54closePubMed  = function( chooserObject, inputElement, event, ui ) { 
     55    // no he didn't, clear the field(s) 
     56    var element = inputElement; 
     57 
     58    // set fields 
     59    inputElement.val(''); 
     60    chooserObject.setInputValue(element, 'title', ''); 
     61    chooserObject.setInputValue(element, 'authorsList', ''); 
     62    chooserObject.setInputValue(element, 'pubMedID', ''); 
     63    chooserObject.setInputValue(element, 'doi', ''); 
     64 
     65    // add error class 
     66    element.addClass('error'); 
     67}; 
     68 
     69//renderPubMed = function( chooserObject, ul, item ) {}; 
    3970 
    4071/** 
     
    85116} 
    86117 
    87 PublicationChooser.prototype.availableDBs[ "pubmed" ] = sourcePubMed; 
     118PublicationChooser.prototype.availableDBs[ "pubmed" ] = {  
     119    'source': sourcePubMed, 
     120    'select': selectPubMed, 
     121    'close':  closePubMed 
     122};