www/include/scripts/subtypes.js

Code
Comments
Other
Rev Date Author Line
7604 25 Feb 19 nicklas 1 /* $Id$
7604 25 Feb 19 nicklas 2   ------------------------------------------------------------------
7604 25 Feb 19 nicklas 3   Copyright (C) 2011 Nicklas Nordborg
7604 25 Feb 19 nicklas 4
7604 25 Feb 19 nicklas 5   This file is part of BASE - BioArray Software Environment.
7604 25 Feb 19 nicklas 6   Available at http://base.thep.lu.se/
7604 25 Feb 19 nicklas 7
7604 25 Feb 19 nicklas 8   BASE is free software; you can redistribute it and/or
7604 25 Feb 19 nicklas 9   modify it under the terms of the GNU General Public License
7604 25 Feb 19 nicklas 10   as published by the Free Software Foundation; either version 3
7604 25 Feb 19 nicklas 11   of the License, or (at your option) any later version.
7604 25 Feb 19 nicklas 12
7604 25 Feb 19 nicklas 13   BASE is distributed in the hope that it will be useful,
7604 25 Feb 19 nicklas 14   but WITHOUT ANY WARRANTY; without even the implied warranty of
7604 25 Feb 19 nicklas 15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7604 25 Feb 19 nicklas 16   GNU General Public License for more details.
7604 25 Feb 19 nicklas 17
7604 25 Feb 19 nicklas 18   You should have received a copy of the GNU General Public License
7604 25 Feb 19 nicklas 19   along with BASE. If not, see <http://www.gnu.org/licenses/>.
7604 25 Feb 19 nicklas 20   ------------------------------------------------------------------
7604 25 Feb 19 nicklas 21
7604 25 Feb 19 nicklas 22   JavaScript functions for working with subtypable items
7604 25 Feb 19 nicklas 23
7604 25 Feb 19 nicklas 24   @author Nicklas
7604 25 Feb 19 nicklas 25 */
7604 25 Feb 19 nicklas 26 'use strict';
7604 25 Feb 19 nicklas 27
7604 25 Feb 19 nicklas 28 var ItemSubtype = function()
7604 25 Feb 19 nicklas 29 {
7604 25 Feb 19 nicklas 30   var subtype = {};
7604 25 Feb 19 nicklas 31   var cache = [];
7604 25 Feb 19 nicklas 32   
7604 25 Feb 19 nicklas 33   /**
7604 25 Feb 19 nicklas 34     Get the subtype of the given item. Uses an AJAX request
7604 25 Feb 19 nicklas 35     and return the subtype as an object with 'id' and 'name'
7604 25 Feb 19 nicklas 36     properties.
7604 25 Feb 19 nicklas 37     
7604 25 Feb 19 nicklas 38     @param The type of the item 
7604 25 Feb 19 nicklas 39     @param The id of the item
7604 25 Feb 19 nicklas 40   */
7604 25 Feb 19 nicklas 41   subtype.getSubtype = function(itemType, itemId)
7604 25 Feb 19 nicklas 42   {
7604 25 Feb 19 nicklas 43     var cacheKey = 'subtype.'+itemType+'.'+itemId;
7604 25 Feb 19 nicklas 44     var jsonSubtype = cache[cacheKey];
7604 25 Feb 19 nicklas 45     if (!jsonSubtype)
7604 25 Feb 19 nicklas 46     {
7604 25 Feb 19 nicklas 47       var request = Ajax.getXmlHttpRequest();
7604 25 Feb 19 nicklas 48       var url = App.getRoot() + 'admin/itemsubtypes/ajax.jsp?ID=' + App.getSessionId();
7604 25 Feb 19 nicklas 49       url += '&cmd=GetSubtypeForItem&item_id=' + itemId;
7604 25 Feb 19 nicklas 50       url += '&itemType='+itemType;
7604 25 Feb 19 nicklas 51       request.open("GET", url, false); 
7604 25 Feb 19 nicklas 52       request.send(null);
7604 25 Feb 19 nicklas 53       jsonSubtype = JSON.parse(request.responseText);
7604 25 Feb 19 nicklas 54       cache[cacheKey] = jsonSubtype;
7604 25 Feb 19 nicklas 55     }
7604 25 Feb 19 nicklas 56     return jsonSubtype && jsonSubtype.id ? jsonSubtype : null;
7604 25 Feb 19 nicklas 57   }
7604 25 Feb 19 nicklas 58   
7604 25 Feb 19 nicklas 59   
7604 25 Feb 19 nicklas 60   /**
7604 25 Feb 19 nicklas 61     Get the subtype that is related to the given one.
7604 25 Feb 19 nicklas 62     @param subtypeId The main subtype
7604 25 Feb 19 nicklas 63     @param relatedItemType The item type of the related subtype we are
7604 25 Feb 19 nicklas 64       looking for
7604 25 Feb 19 nicklas 65     @param defaultSubtype The id of the default subtype to return if
7604 25 Feb 19 nicklas 66       no related subtype is found (optional)
7604 25 Feb 19 nicklas 67     @return An object with the 'id' and 'name' of the related subtype or null
7604 25 Feb 19 nicklas 68       if no related subtype is found
7604 25 Feb 19 nicklas 69   */
7604 25 Feb 19 nicklas 70   subtype.getRelatedSubtype = function(subtypeId, relatedItemType, defaultSubtypeId)
7604 25 Feb 19 nicklas 71   {
7604 25 Feb 19 nicklas 72     if (!subtypeId && !defaultSubtypeId) 
7604 25 Feb 19 nicklas 73     {
7604 25 Feb 19 nicklas 74       return null;
7604 25 Feb 19 nicklas 75     }
7604 25 Feb 19 nicklas 76     
7604 25 Feb 19 nicklas 77     var cacheKey = 'relatedsubtype.'+relatedItemType+'.'+subtypeId;
7604 25 Feb 19 nicklas 78     var jsonSubtype = cache[cacheKey];
7604 25 Feb 19 nicklas 79     if (!jsonSubtype)
7604 25 Feb 19 nicklas 80     {
7604 25 Feb 19 nicklas 81       var request = Ajax.getXmlHttpRequest();
7604 25 Feb 19 nicklas 82       var url = App.getRoot() + 'admin/itemsubtypes/ajax.jsp?ID=' + App.getSessionId();
7604 25 Feb 19 nicklas 83       url += "&cmd=GetRelatedSubtype&relatedType=" + relatedItemType;
7604 25 Feb 19 nicklas 84       if (subtypeId) 
7604 25 Feb 19 nicklas 85       {
7604 25 Feb 19 nicklas 86         url += '&item_id='+subtypeId;
7604 25 Feb 19 nicklas 87       }
7604 25 Feb 19 nicklas 88       if (defaultSubtypeId) 
7604 25 Feb 19 nicklas 89       {
7604 25 Feb 19 nicklas 90         url += '&defaultRelatedId=' + defaultSubtypeId;
7604 25 Feb 19 nicklas 91       }
7604 25 Feb 19 nicklas 92       request.open("GET", url, false); 
7604 25 Feb 19 nicklas 93       request.send(null);
7604 25 Feb 19 nicklas 94       jsonSubtype = JSON.parse(request.responseText);
7604 25 Feb 19 nicklas 95       cache[cacheKey] = jsonSubtype;
7604 25 Feb 19 nicklas 96     }
7604 25 Feb 19 nicklas 97     return jsonSubtype && jsonSubtype.id ? jsonSubtype : null;
7604 25 Feb 19 nicklas 98   }
7604 25 Feb 19 nicklas 99
7604 25 Feb 19 nicklas 100   /**
7604 25 Feb 19 nicklas 101     Get information about project default items and recently used items 
7604 25 Feb 19 nicklas 102     of the given subtype or item type. If a subtype is given, only project default 
7604 25 Feb 19 nicklas 103     and recent items of the same subtype are returned, otherwise the item type 
7604 25 Feb 19 nicklas 104     parameter is used and all project default items WITHOUT any subtype are returned.
7604 25 Feb 19 nicklas 105     
7604 25 Feb 19 nicklas 106     The function returns an object with the 'id' and 'name' of the subtype and
7604 25 Feb 19 nicklas 107     two arrays ('default' and 'recent') which both contain elements that are 
7604 25 Feb 19 nicklas 108     objects with the 'id' and 'name' of the found items.
7604 25 Feb 19 nicklas 109     
7604 25 Feb 19 nicklas 110     @param itemType The main type of items to find
7604 25 Feb 19 nicklas 111     @param subtypeId The ID of the subtype we want to find information for
7604 25 Feb 19 nicklas 112   */
7604 25 Feb 19 nicklas 113   subtype.getProjectDefaultAndRecentItems = function(itemType, subtypeId)
7604 25 Feb 19 nicklas 114   {
7604 25 Feb 19 nicklas 115     var cacheKey = 'defaultitems.'+itemType+'.'+subtypeId;
7604 25 Feb 19 nicklas 116     var jsonItems = cache[cacheKey];
7604 25 Feb 19 nicklas 117     
7604 25 Feb 19 nicklas 118     if (!jsonItems)
7604 25 Feb 19 nicklas 119     {
7604 25 Feb 19 nicklas 120       var request = Ajax.getXmlHttpRequest();
7604 25 Feb 19 nicklas 121       var url = App.getRoot() + 'admin/itemsubtypes/ajax.jsp?ID=' + App.getSessionId();
7604 25 Feb 19 nicklas 122       url += '&cmd=GetProjectDefaultAndRecentItems';
7604 25 Feb 19 nicklas 123       url += '&item_id='+subtypeId;
7604 25 Feb 19 nicklas 124       url += '&itemType='+itemType;
7604 25 Feb 19 nicklas 125       request.open("GET", url, false); 
7604 25 Feb 19 nicklas 126       request.send(null);
7604 25 Feb 19 nicklas 127       jsonItems = JSON.parse(request.responseText);
7604 25 Feb 19 nicklas 128       cache[cacheKey] = jsonItems;
7604 25 Feb 19 nicklas 129     }
7604 25 Feb 19 nicklas 130     return jsonItems;
7604 25 Feb 19 nicklas 131   }
7604 25 Feb 19 nicklas 132
7604 25 Feb 19 nicklas 133   /**
7604 25 Feb 19 nicklas 134     Utility function for finding the project default and recently used items for
7604 25 Feb 19 nicklas 135     several types of items at the same time. 
7604 25 Feb 19 nicklas 136     
7604 25 Feb 19 nicklas 137   */
7604 25 Feb 19 nicklas 138   subtype.getRelatedProjectDefaultAndRecentItems = function(itemType, subtypeId, relatedItemTypes)
7604 25 Feb 19 nicklas 139   {
7604 25 Feb 19 nicklas 140     var cacheKey = 'relateditems.'+itemType+'.'+subtypeId;
7604 25 Feb 19 nicklas 141     
7604 25 Feb 19 nicklas 142     var info = cache[cacheKey];
7604 25 Feb 19 nicklas 143     if (info)
7604 25 Feb 19 nicklas 144     {
7604 25 Feb 19 nicklas 145       // We have some info already, but...
7604 25 Feb 19 nicklas 146       // ...check if we are missing info about some related item types
7604 25 Feb 19 nicklas 147       var missingInfo = [];
7604 25 Feb 19 nicklas 148       for (var i = 0; i < relatedItemTypes.length; i++)
7604 25 Feb 19 nicklas 149       {
7604 25 Feb 19 nicklas 150         if (!info[relatedItemTypes[i]]) missingInfo[missingInfo.length] = relatedItemTypes[i];
7604 25 Feb 19 nicklas 151       }
7604 25 Feb 19 nicklas 152       relatedItemTypes = missingInfo;
7604 25 Feb 19 nicklas 153     }
7604 25 Feb 19 nicklas 154     
7604 25 Feb 19 nicklas 155     // Get more info...
7604 25 Feb 19 nicklas 156     if (relatedItemTypes.length > 0)
7604 25 Feb 19 nicklas 157     {
7604 25 Feb 19 nicklas 158       var request = Ajax.getXmlHttpRequest();
7604 25 Feb 19 nicklas 159       var url = App.getRoot() + 'admin/itemsubtypes/ajax.jsp?ID=' + App.getSessionId();
7604 25 Feb 19 nicklas 160       url += '&cmd=GetRecentAndRelated&itemType='+itemType;
7604 25 Feb 19 nicklas 161       if (subtypeId) 
7604 25 Feb 19 nicklas 162       {
7604 25 Feb 19 nicklas 163         url += '&item_id='+subtypeId;
7604 25 Feb 19 nicklas 164       }
7604 25 Feb 19 nicklas 165       for (var i = 0; i < relatedItemTypes.length; i++)
7604 25 Feb 19 nicklas 166       {
7604 25 Feb 19 nicklas 167         url += '&relatedType=' + relatedItemTypes[i];
7604 25 Feb 19 nicklas 168       }
7604 25 Feb 19 nicklas 169       request.open("GET", url, false); 
7604 25 Feb 19 nicklas 170       request.send(null);
7604 25 Feb 19 nicklas 171       var moreInfo = JSON.parse(request.responseText);
7604 25 Feb 19 nicklas 172       if (!info)
7604 25 Feb 19 nicklas 173       {
7604 25 Feb 19 nicklas 174         info = moreInfo;
7604 25 Feb 19 nicklas 175       }
7604 25 Feb 19 nicklas 176       else
7604 25 Feb 19 nicklas 177       {
7604 25 Feb 19 nicklas 178         // Merge the new info with the existing info
7604 25 Feb 19 nicklas 179         for (var i = 0; i < relatedItemTypes.length; i++)
7604 25 Feb 19 nicklas 180         {
7604 25 Feb 19 nicklas 181           info[relatedItemTypes[i]]= moreInfo[relatedItemTypes[i]];
7604 25 Feb 19 nicklas 182         }
7604 25 Feb 19 nicklas 183       }
7604 25 Feb 19 nicklas 184       cache[cacheKey] = info;
7604 25 Feb 19 nicklas 185     }
7604 25 Feb 19 nicklas 186     return info;
7604 25 Feb 19 nicklas 187   }
7604 25 Feb 19 nicklas 188   
7604 25 Feb 19 nicklas 189   /**
7604 25 Feb 19 nicklas 190     Utility function for getting the ID of the currently selected 
7604 25 Feb 19 nicklas 191     subtype in a form.
7604 25 Feb 19 nicklas 192     @param list The ID or element of a selection list with subtype items 
7604 25 Feb 19 nicklas 193   */
7604 25 Feb 19 nicklas 194   subtype.getSubtypeId = function(list)
7604 25 Feb 19 nicklas 195   {
7604 25 Feb 19 nicklas 196     list = Doc.element(list);
7604 25 Feb 19 nicklas 197     if (!list || list.disabled || list.length == 0) return 0;
7604 25 Feb 19 nicklas 198     var id = Math.abs(parseInt(list.value));
7604 25 Feb 19 nicklas 199     return id;
7604 25 Feb 19 nicklas 200   }
7604 25 Feb 19 nicklas 201
7604 25 Feb 19 nicklas 202   /**
7604 25 Feb 19 nicklas 203     Utility function for creating a (temporary) filter string that can be added
7604 25 Feb 19 nicklas 204     to a popup URL for selecting item with a specified subtype. From the
7604 25 Feb 19 nicklas 205     currently selected subtype we find the related subtype for the associated
7604 25 Feb 19 nicklas 206     item and generate a filter based on that. For example, when selecting a FILE
7604 25 Feb 19 nicklas 207     for a PROTOCOL, we use the current subtype of the protocol to find the
7604 25 Feb 19 nicklas 208     related subtype for FILE items. 
7604 25 Feb 19 nicklas 209     
7604 25 Feb 19 nicklas 210     If there is no related subtype, an empty string is returned.
7604 25 Feb 19 nicklas 211     @param list The ID or element of a selection list with subtype items
7604 25 Feb 19 nicklas 212     @param relatedItemType The item type of the related subtype we are
7604 25 Feb 19 nicklas 213       looking for
7604 25 Feb 19 nicklas 214     @param defaultSubtype The id of the default subtype to use if
7604 25 Feb 19 nicklas 215       no related subtype is found (optional)
7604 25 Feb 19 nicklas 216   */
7604 25 Feb 19 nicklas 217   subtype.createRelatedFilter = function(list, relatedItemType, defaultSubtypeId)
7604 25 Feb 19 nicklas 218   {
7604 25 Feb 19 nicklas 219     var subtypeId = subtype.getSubtypeId(list);
7604 25 Feb 19 nicklas 220     var relatedSubtype = subtype.getRelatedSubtype(subtypeId, relatedItemType, defaultSubtypeId);
7604 25 Feb 19 nicklas 221     return relatedSubtype ? '&tmpfilter:INT:itemSubtype=' + relatedSubtype.id : '';
7604 25 Feb 19 nicklas 222   }
7604 25 Feb 19 nicklas 223
7604 25 Feb 19 nicklas 224   
7604 25 Feb 19 nicklas 225   /**
7604 25 Feb 19 nicklas 226     Update the selection list with 'recently used' and 'project default' items.
7604 25 Feb 19 nicklas 227     Currently existing options under those headers will be cleared. 
7604 25 Feb 19 nicklas 228   */
7604 25 Feb 19 nicklas 229   subtype.updateSelectionList = function(list, recentItems, projectDefaults, noNoneOption)
7604 25 Feb 19 nicklas 230   {
7604 25 Feb 19 nicklas 231     list = Doc.element(list);
7604 25 Feb 19 nicklas 232     
7604 25 Feb 19 nicklas 233     var oldSelectedValue = list.selectedIndex >= 0 ? list[list.selectedIndex].value : 0;
7604 25 Feb 19 nicklas 234     var reselectValue = 0;
7604 25 Feb 19 nicklas 235     
7604 25 Feb 19 nicklas 236     // Find the first header option
7604 25 Feb 19 nicklas 237     for (var i = noNoneOption ? 0 : 1; i < list.length; i++)
7604 25 Feb 19 nicklas 238     {
7604 25 Feb 19 nicklas 239       if (list[i].value == 'NaN')
7604 25 Feb 19 nicklas 240       {
7604 25 Feb 19 nicklas 241         // Found the header entry
7604 25 Feb 19 nicklas 242         // Remember the currently selected value if it is after header
7604 25 Feb 19 nicklas 243         if (list.selectedIndex > i)
7604 25 Feb 19 nicklas 244         {
7604 25 Feb 19 nicklas 245           reselectValue = list[list.selectedIndex].value;
7604 25 Feb 19 nicklas 246         }
7604 25 Feb 19 nicklas 247         // Clear everything from the header and onwards
7604 25 Feb 19 nicklas 248         list.length = i;
7604 25 Feb 19 nicklas 249       }
7604 25 Feb 19 nicklas 250     }
7604 25 Feb 19 nicklas 251     
7604 25 Feb 19 nicklas 252     var firstNewIndex = list.length + 1;
7604 25 Feb 19 nicklas 253     if (recentItems && recentItems.length)
7604 25 Feb 19 nicklas 254     {
7604 25 Feb 19 nicklas 255       // Add recently used items
7604 25 Feb 19 nicklas 256       var recentlyUsedHeader = new Option('› recently used', 'NaN');
7604 25 Feb 19 nicklas 257       recentlyUsedHeader.className = 'recentheader';
7604 25 Feb 19 nicklas 258       recentlyUsedHeader.disabled = true;
7604 25 Feb 19 nicklas 259       list[list.length] = recentlyUsedHeader;
7604 25 Feb 19 nicklas 260       
7703 11 Apr 19 nicklas 261       var cnt = 0;
7604 25 Feb 19 nicklas 262       for (var i = 0; i < recentItems.length; i++)
7604 25 Feb 19 nicklas 263       {
7703 11 Apr 19 nicklas 264         var item = recentItems[i];
7703 11 Apr 19 nicklas 265         if (item.id)
7703 11 Apr 19 nicklas 266         {
7703 11 Apr 19 nicklas 267           cnt++;
7703 11 Apr 19 nicklas 268           var selected = reselectValue == item.id;
7703 11 Apr 19 nicklas 269           var opt = new Option(cnt + '. ' + item.name, item.id, false, selected);
7703 11 Apr 19 nicklas 270           opt.className = 'selectoptionindent';
7703 11 Apr 19 nicklas 271           list[list.length] = opt;
7703 11 Apr 19 nicklas 272         }
7703 11 Apr 19 nicklas 273         else
7703 11 Apr 19 nicklas 274         {
7703 11 Apr 19 nicklas 275           // If there is an empty element we selected the 'none' option if it is available
7703 11 Apr 19 nicklas 276           if (!noNoneOption) firstNewIndex = 0;
7703 11 Apr 19 nicklas 277         }
7604 25 Feb 19 nicklas 278       }
7604 25 Feb 19 nicklas 279     }
7604 25 Feb 19 nicklas 280     
7604 25 Feb 19 nicklas 281     if (projectDefaults && projectDefaults.length)
7604 25 Feb 19 nicklas 282     {
7604 25 Feb 19 nicklas 283       // Add project default items
7604 25 Feb 19 nicklas 284       var projectDefaultHeader = new Option('› project default', 'NaN');
7604 25 Feb 19 nicklas 285       projectDefaultHeader.className = 'defaultheader';
7604 25 Feb 19 nicklas 286       projectDefaultHeader.disabled = true;
7604 25 Feb 19 nicklas 287       list[list.length] = projectDefaultHeader;
7604 25 Feb 19 nicklas 288       
7604 25 Feb 19 nicklas 289       for (var i = 0; i < projectDefaults.length; i++)
7604 25 Feb 19 nicklas 290       {
7604 25 Feb 19 nicklas 291         var selected = reselectValue == projectDefaults[i].id;
7604 25 Feb 19 nicklas 292         var opt = new Option( projectDefaults[i].name, projectDefaults[i].id, false, selected);
7604 25 Feb 19 nicklas 293         opt.className = 'selectoptionindent';
7604 25 Feb 19 nicklas 294         list[list.length] = opt;
7604 25 Feb 19 nicklas 295       }
7604 25 Feb 19 nicklas 296     }
7604 25 Feb 19 nicklas 297     
7604 25 Feb 19 nicklas 298     // If no item is selected, select the first new item
7604 25 Feb 19 nicklas 299     if (list.selectedIndex == 0 && list.length > firstNewIndex) 
7604 25 Feb 19 nicklas 300     {
7604 25 Feb 19 nicklas 301       list.selectedIndex = firstNewIndex;
7604 25 Feb 19 nicklas 302     }
7604 25 Feb 19 nicklas 303     
7604 25 Feb 19 nicklas 304     var currentSelectedValue = list.selectedIndex >= 0 ? list[list.selectedIndex].value : 0;
7604 25 Feb 19 nicklas 305     return oldSelectedValue != currentSelectedValue;
7604 25 Feb 19 nicklas 306   }
7604 25 Feb 19 nicklas 307
7604 25 Feb 19 nicklas 308   return subtype;
7604 25 Feb 19 nicklas 309 }();
7604 25 Feb 19 nicklas 310