www/common/annotations/annotate.js

Code
Comments
Other
Rev Date Author Line
6938 19 Aug 15 nicklas 1 /* $Id $
6938 19 Aug 15 nicklas 2   ------------------------------------------------------------------
6938 19 Aug 15 nicklas 3   Copyright (C) 2012 Nicklas Nordborg
6938 19 Aug 15 nicklas 4
6938 19 Aug 15 nicklas 5   This file is part of BASE - BioArray Software Environment.
6938 19 Aug 15 nicklas 6   Available at http://base.thep.lu.se/
6938 19 Aug 15 nicklas 7
6938 19 Aug 15 nicklas 8   BASE is free software; you can redistribute it and/or
6938 19 Aug 15 nicklas 9   modify it under the terms of the GNU General Public License
6938 19 Aug 15 nicklas 10   as published by the Free Software Foundation; either version 3
6938 19 Aug 15 nicklas 11   of the License, or (at your option) any later version.
6938 19 Aug 15 nicklas 12
6938 19 Aug 15 nicklas 13   BASE is distributed in the hope that it will be useful,
6938 19 Aug 15 nicklas 14   but WITHOUT ANY WARRANTY; without even the implied warranty of
6938 19 Aug 15 nicklas 15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6938 19 Aug 15 nicklas 16   GNU General Public License for more details.
6938 19 Aug 15 nicklas 17
6938 19 Aug 15 nicklas 18   You should have received a copy of the GNU General Public License
6938 19 Aug 15 nicklas 19   along with BASE. If not, see <http://www.gnu.org/licenses/>.
6938 19 Aug 15 nicklas 20   ------------------------------------------------------------------
6938 19 Aug 15 nicklas 21
6938 19 Aug 15 nicklas 22   @author Nicklas
6938 19 Aug 15 nicklas 23 */
7429 07 Dec 17 nicklas 24 'use strict';
6938 19 Aug 15 nicklas 25
6938 19 Aug 15 nicklas 26 var Annotate = function()
6938 19 Aug 15 nicklas 27 {
6938 19 Aug 15 nicklas 28   var annotate = {};
6938 19 Aug 15 nicklas 29
6943 01 Sep 15 nicklas 30   var MODIFIED = 'MODIFIED';
6943 01 Sep 15 nicklas 31   var SYNCED = 'SYNCED';
6943 01 Sep 15 nicklas 32   var CONVERTED = 'CONVERTED';
6945 04 Sep 15 nicklas 33   var DELETE = 'DELETE';
6947 08 Sep 15 nicklas 34   var INHERITED = 'INHERITED';
6943 01 Sep 15 nicklas 35   
6938 19 Aug 15 nicklas 36   var annotations;
6947 08 Sep 15 nicklas 37   var parents;
6938 19 Aug 15 nicklas 38   var selectedAnnotation;
6955 28 Sep 15 nicklas 39   var selectedMultiIndex;
6938 19 Aug 15 nicklas 40   
6938 19 Aug 15 nicklas 41
6938 19 Aug 15 nicklas 42   annotate.initPage = function()
6938 19 Aug 15 nicklas 43   {
6938 19 Aug 15 nicklas 44     // Buttons (on standalone dialog)
6938 19 Aug 15 nicklas 45     Buttons.addClickHandler('close', App.closeWindow);
6938 19 Aug 15 nicklas 46     Buttons.addClickHandler('btnSave', annotate.save);
6938 19 Aug 15 nicklas 47     
6938 19 Aug 15 nicklas 48     // Parse the current annotation information which contain value type, current values, etc.
6938 19 Aug 15 nicklas 49     annotations = Data.json('page-data', 'annotations');
6947 08 Sep 15 nicklas 50     parents = Data.json('page-data', 'parents');
6947 08 Sep 15 nicklas 51     
6938 19 Aug 15 nicklas 52     // Loop through all annotations and build the selection list
6946 07 Sep 15 nicklas 53     var numPrimary = 0;
6938 19 Aug 15 nicklas 54     for (var i = 0; i < annotations.length; i++)
6938 19 Aug 15 nicklas 55     {
6947 08 Sep 15 nicklas 56       annotate.createAnnotationEntryInList(annotations[i], false);
6946 07 Sep 15 nicklas 57       if (annotations[i].source == 'PRIMARY') numPrimary++;
6938 19 Aug 15 nicklas 58     }
6946 07 Sep 15 nicklas 59     if (numPrimary == 0) Doc.hide('primary-list');
6946 07 Sep 15 nicklas 60     if (numPrimary == annotations.length) Doc.hide('inherited-list');
6938 19 Aug 15 nicklas 61
6938 19 Aug 15 nicklas 62     // Event handlers for input fields
6938 19 Aug 15 nicklas 63     Events.addEventHandler('STRING-input', 'change', annotate.valueOnChange);
6955 28 Sep 15 nicklas 64     Events.addEventHandler('STRING-input', 'blur', annotate.valueOnBlur);
6938 19 Aug 15 nicklas 65     Events.addEventHandler('TEXT-input', 'change', annotate.valueOnChange);
6955 28 Sep 15 nicklas 66     Events.addEventHandler('TEXT-input', 'blur', annotate.valueOnBlur);
6938 19 Aug 15 nicklas 67     Buttons.addClickHandler('TEXT-zoom', annotate.openTextZoom);
6938 19 Aug 15 nicklas 68     Events.addEventHandler('INT-input', 'keypress', Events.integerOnly);
6938 19 Aug 15 nicklas 69     Events.addEventHandler('INT-input', 'change', annotate.valueOnChange);
6955 28 Sep 15 nicklas 70     Events.addEventHandler('INT-input', 'blur', annotate.valueOnBlur);
6938 19 Aug 15 nicklas 71     Events.addEventHandler('LONG-input', 'keypress', Events.integerOnly);
6938 19 Aug 15 nicklas 72     Events.addEventHandler('LONG-input', 'change', annotate.valueOnChange);
6955 28 Sep 15 nicklas 73     Events.addEventHandler('LONG-input', 'blur', annotate.valueOnBlur);
6938 19 Aug 15 nicklas 74     Events.addEventHandler('FLOAT-input', 'keypress', Events.numberOnly);
6938 19 Aug 15 nicklas 75     Events.addEventHandler('FLOAT-input', 'change', annotate.valueOnChange);
6955 28 Sep 15 nicklas 76     Events.addEventHandler('FLOAT-input', 'blur', annotate.valueOnBlur);
6938 19 Aug 15 nicklas 77     Events.addEventHandler('DOUBLE-input', 'keypress', Events.numberOnly);
6938 19 Aug 15 nicklas 78     Events.addEventHandler('DOUBLE-input', 'change', annotate.valueOnChange);
6955 28 Sep 15 nicklas 79     Events.addEventHandler('DOUBLE-input', 'blur', annotate.valueOnBlur);
6938 19 Aug 15 nicklas 80     Events.addEventHandler('DATE-input', 'change', annotate.valueOnChange);
6955 28 Sep 15 nicklas 81     Events.addEventHandler('DATE-input', 'blur', annotate.valueOnBlur);
6938 19 Aug 15 nicklas 82     Buttons.addClickHandler('DATE-calendar', annotate.openCalendar);
6938 19 Aug 15 nicklas 83     Events.addEventHandler('TIMESTAMP-input', 'change', annotate.valueOnChange);
6955 28 Sep 15 nicklas 84     Events.addEventHandler('TIMESTAMP-input', 'blur', annotate.valueOnBlur);
6938 19 Aug 15 nicklas 85     Buttons.addClickHandler('TIMESTAMP-calendar', annotate.openCalendar);
6938 19 Aug 15 nicklas 86     Events.addEventHandler('BOOLEAN-input-NULL', 'click', annotate.valueOnChange);
6938 19 Aug 15 nicklas 87     Events.addEventHandler('BOOLEAN-input-TRUE', 'click', annotate.valueOnChange);
6938 19 Aug 15 nicklas 88     Events.addEventHandler('BOOLEAN-input-FALSE', 'click', annotate.valueOnChange);
6938 19 Aug 15 nicklas 89     Events.addEventHandler('ENUM-SINGLE-input', 'change', annotate.valueOnChange);
6938 19 Aug 15 nicklas 90     Events.addEventHandler('ENUM-MULTIPLE-input', 'change', annotate.valueOnChange);
6938 19 Aug 15 nicklas 91
6938 19 Aug 15 nicklas 92     // Buttons for multi-valued annotations
6938 19 Aug 15 nicklas 93     Buttons.addClickHandler('btnMultiAdd', annotate.addMultiValue);
6938 19 Aug 15 nicklas 94     Buttons.addClickHandler('btnMultiRemove', annotate.removeMultiValue);
6938 19 Aug 15 nicklas 95     Events.addEventHandler('multi-values', 'click', annotate.multiValueOnClick);
6938 19 Aug 15 nicklas 96     
6938 19 Aug 15 nicklas 97     
6938 19 Aug 15 nicklas 98     // The category list box is used to filter visible annotations
6938 19 Aug 15 nicklas 99     Events.addEventHandler('categories', 'change', annotate.categoryOnChange);
6938 19 Aug 15 nicklas 100     annotate.categoryOnChange();
6938 19 Aug 15 nicklas 101     
6938 19 Aug 15 nicklas 102     // Unit selection
6938 19 Aug 15 nicklas 103     Events.addEventHandler('unit', 'change', annotate.unitOnChange);
6938 19 Aug 15 nicklas 104     
6946 07 Sep 15 nicklas 105     // Check/uncheck all
6946 07 Sep 15 nicklas 106     Events.addEventHandler('check-all-primary', 'click', annotate.checkAllPrimary);
6946 07 Sep 15 nicklas 107     Events.addEventHandler('check-all-inherited', 'click', annotate.checkAllInherited);
6946 07 Sep 15 nicklas 108     
6943 01 Sep 15 nicklas 109     // Sync modified clone
6945 04 Sep 15 nicklas 110     Events.addEventHandler('sync-modified', 'click', annotate.syncSelectedClone);
6945 04 Sep 15 nicklas 111     Buttons.addClickHandler('btnSync', annotate.syncAllCheckedClones);
6945 04 Sep 15 nicklas 112     
6946 07 Sep 15 nicklas 113     // Convert between inherited/cloned
6945 04 Sep 15 nicklas 114     Events.addEventHandler('convert-to-cloned', 'click', annotate.convertSelectedToCloned);
6945 04 Sep 15 nicklas 115     Buttons.addClickHandler('btnClone', annotate.convertAllCheckedToCloned);
6946 07 Sep 15 nicklas 116     Buttons.addClickHandler('btnUnclone', annotate.convertAllCheckedToInherited);
6943 01 Sep 15 nicklas 117     
6946 07 Sep 15 nicklas 118     // Delete annotations
6945 04 Sep 15 nicklas 119     Buttons.addClickHandler('btnDelete', annotate.deleteAllChecked);
6947 08 Sep 15 nicklas 120     // Add inherited annotations
6947 08 Sep 15 nicklas 121     Buttons.addClickHandler('btnAdd', annotate.addInheritedAnnotations);
6947 08 Sep 15 nicklas 122     Events.addEventHandler('btnAdd', 'remove-annotation', annotate.onRemoveInheritedAnnotation);
6947 08 Sep 15 nicklas 123     Events.addEventHandler('btnAdd', 'inherit-annotation', annotate.onAddInheritedAnnotation);
6945 04 Sep 15 nicklas 124     
6938 19 Aug 15 nicklas 125     // Select the initial annotation
6938 19 Aug 15 nicklas 126     var annotationTypeId = Data.int('page-data', 'annotation-type-id');
6938 19 Aug 15 nicklas 127     var annotationId = Data.int('page-data', 'annotation-id');
6938 19 Aug 15 nicklas 128     if (annotationId)
6938 19 Aug 15 nicklas 129     {
7832 24 Jun 20 nicklas 130       annotate.selectAnnotation(annotationTypeId+'-'+annotationId, true);
6938 19 Aug 15 nicklas 131     }
6938 19 Aug 15 nicklas 132     else if (annotationTypeId) 
6938 19 Aug 15 nicklas 133     {
7832 24 Jun 20 nicklas 134       annotate.selectAnnotation(annotationTypeId, true);
6938 19 Aug 15 nicklas 135     }
6938 19 Aug 15 nicklas 136     else
6938 19 Aug 15 nicklas 137     {
6938 19 Aug 15 nicklas 138       annotate.selectAnnotation(null);
6938 19 Aug 15 nicklas 139     }
6938 19 Aug 15 nicklas 140   }
6938 19 Aug 15 nicklas 141   
6938 19 Aug 15 nicklas 142   /**
6938 19 Aug 15 nicklas 143     Create an entry for the given annotation/annotation type
6938 19 Aug 15 nicklas 144     in the list.
6938 19 Aug 15 nicklas 145   */
6947 08 Sep 15 nicklas 146   annotate.createAnnotationEntryInList = function(entry, autoSort)
6938 19 Aug 15 nicklas 147   {
6938 19 Aug 15 nicklas 148     var ann = entry.annotation;
6938 19 Aug 15 nicklas 149     var at = entry.annotationType;
6938 19 Aug 15 nicklas 150     
6938 19 Aug 15 nicklas 151     var div = document.createElement('div');
6938 19 Aug 15 nicklas 152     div.className = 'param interactable';
7206 19 Oct 16 nicklas 153     if (!entry.annotatePermission) div.className += ' disabled';
6938 19 Aug 15 nicklas 154     div.id = entry.id;
6938 19 Aug 15 nicklas 155     div.title = Strings.encodeTags(at.name);
6938 19 Aug 15 nicklas 156     
6938 19 Aug 15 nicklas 157     var html = '';
6945 04 Sep 15 nicklas 158     var icon = annotate.getIcon(entry);
6943 01 Sep 15 nicklas 159     
7206 19 Oct 16 nicklas 160     if (entry.annotatePermission)
7206 19 Oct 16 nicklas 161     {
7206 19 Oct 16 nicklas 162       html += '<input type="checkbox" style="float: right;" id="check.'+entry.id+'">';
7206 19 Oct 16 nicklas 163     }
6938 19 Aug 15 nicklas 164     html += '<span class="icon">';
6938 19 Aug 15 nicklas 165     html += '<img id="icon.'+entry.id+'" src="../../images/'+icon+'">';
6938 19 Aug 15 nicklas 166     html += '</span>';
6938 19 Aug 15 nicklas 167     // DEBUG!!
6938 19 Aug 15 nicklas 168     //html += entry.source;
6938 19 Aug 15 nicklas 169     
6938 19 Aug 15 nicklas 170     html += '<span class="label">';
6938 19 Aug 15 nicklas 171     if (at.removed) html += '<img src="../../images/deleted.png">';
6938 19 Aug 15 nicklas 172     if (at.protocolParameter) html += '<img src="../../images/parameter.png">';
6938 19 Aug 15 nicklas 173     html += Strings.encodeTags(at.name)+'</span>';
6938 19 Aug 15 nicklas 174     html += '</div>';
6938 19 Aug 15 nicklas 175     div.innerHTML = html;
6938 19 Aug 15 nicklas 176     
6938 19 Aug 15 nicklas 177     Events.addEventHandler(div, 'click', annotate.annotationOnClick);
6947 08 Sep 15 nicklas 178     var list = Doc.element(entry.source == 'PRIMARY' ? 'primary-list' : 'inherited-list');
6947 08 Sep 15 nicklas 179     var beforeChild = null;
6947 08 Sep 15 nicklas 180     if (autoSort)
6947 08 Sep 15 nicklas 181     {
6947 08 Sep 15 nicklas 182       var childNo = 0;
6947 08 Sep 15 nicklas 183       while (childNo < list.childNodes.length)
6947 08 Sep 15 nicklas 184       {
6947 08 Sep 15 nicklas 185         var child = list.childNodes[childNo];
6947 08 Sep 15 nicklas 186         if (child.title && child.title > div.title)
6947 08 Sep 15 nicklas 187         {
6947 08 Sep 15 nicklas 188           beforeChild = child;
6947 08 Sep 15 nicklas 189           break;
6947 08 Sep 15 nicklas 190         }
6947 08 Sep 15 nicklas 191         childNo++;
6947 08 Sep 15 nicklas 192       }
6947 08 Sep 15 nicklas 193     }
6947 08 Sep 15 nicklas 194     list.insertBefore(div, beforeChild);
6938 19 Aug 15 nicklas 195   }
6938 19 Aug 15 nicklas 196   
6938 19 Aug 15 nicklas 197   /**
6938 19 Aug 15 nicklas 198     Event handler for the 'Categories' list. This will
6938 19 Aug 15 nicklas 199     filter the main list to only include annotations in the select
6938 19 Aug 15 nicklas 200     category. Special cases are 'all', 'protocol parameter' and 'uncategorized'
6938 19 Aug 15 nicklas 201    */
6938 19 Aug 15 nicklas 202   annotate.categoryOnChange = function()
6938 19 Aug 15 nicklas 203   {
6938 19 Aug 15 nicklas 204     var frm = document.forms['annotations'];
6938 19 Aug 15 nicklas 205     var categoryId = parseInt(frm.categories.value);
6938 19 Aug 15 nicklas 206     
6938 19 Aug 15 nicklas 207     for (var entryNo = 0; entryNo < annotations.length; entryNo++)
6938 19 Aug 15 nicklas 208     {
6938 19 Aug 15 nicklas 209       var entry = annotations[entryNo];
6938 19 Aug 15 nicklas 210       var at = entry.annotationType;
6938 19 Aug 15 nicklas 211
6938 19 Aug 15 nicklas 212       var show = false;
6947 08 Sep 15 nicklas 213       if (entry.source != 'PRIMARY')
6947 08 Sep 15 nicklas 214       {
6947 08 Sep 15 nicklas 215         // INHERITED or CLONED annotations are visible unless DELETEd
6947 08 Sep 15 nicklas 216         show = entry.modified != 'DELETE';
6947 08 Sep 15 nicklas 217       }
6946 07 Sep 15 nicklas 218       else if (categoryId == -1)
6938 19 Aug 15 nicklas 219       {
6938 19 Aug 15 nicklas 220         // show all
6938 19 Aug 15 nicklas 221         show = true;
6938 19 Aug 15 nicklas 222       }
6938 19 Aug 15 nicklas 223       else if (categoryId == -2 && at.protocolParameter)
6938 19 Aug 15 nicklas 224       {
6938 19 Aug 15 nicklas 225         // show protocol parameters
6938 19 Aug 15 nicklas 226         show = true;
6938 19 Aug 15 nicklas 227       }
6938 19 Aug 15 nicklas 228       else if (categoryId == 0 && at.categories.length == 0 && !at.protocolParameter)
6938 19 Aug 15 nicklas 229       {
6938 19 Aug 15 nicklas 230         // show uncategorized
6938 19 Aug 15 nicklas 231         show = true;
6938 19 Aug 15 nicklas 232       }
6938 19 Aug 15 nicklas 233       else
6938 19 Aug 15 nicklas 234       {
6938 19 Aug 15 nicklas 235         // show the selected category
6938 19 Aug 15 nicklas 236         for (var categoryNo = 0; categoryNo < at.categories.length; categoryNo++)
6938 19 Aug 15 nicklas 237         {
6938 19 Aug 15 nicklas 238           if (at.categories[categoryNo] == categoryId) 
6938 19 Aug 15 nicklas 239           {
6938 19 Aug 15 nicklas 240             show = true;
6938 19 Aug 15 nicklas 241             break;
6938 19 Aug 15 nicklas 242           }
6938 19 Aug 15 nicklas 243         }
6938 19 Aug 15 nicklas 244       }
6938 19 Aug 15 nicklas 245       
7926 24 Feb 21 nicklas 246       entry.visible = show;
6938 19 Aug 15 nicklas 247       Doc.showHide(entry.id, show);
6938 19 Aug 15 nicklas 248     }
6938 19 Aug 15 nicklas 249   }
6938 19 Aug 15 nicklas 250   
6938 19 Aug 15 nicklas 251   /**
6938 19 Aug 15 nicklas 252     Get the annotation entry for the given id.
6938 19 Aug 15 nicklas 253     Returns null if not found.
6938 19 Aug 15 nicklas 254   */
6938 19 Aug 15 nicklas 255   annotate.getEntryById = function(entryId)
6938 19 Aug 15 nicklas 256   {
6938 19 Aug 15 nicklas 257     for (var i = 0; i < annotations.length; i++)
6938 19 Aug 15 nicklas 258     {
6938 19 Aug 15 nicklas 259       if (annotations[i].id == entryId)
6938 19 Aug 15 nicklas 260       {
6938 19 Aug 15 nicklas 261         return annotations[i];
6938 19 Aug 15 nicklas 262       }
6938 19 Aug 15 nicklas 263     }
6938 19 Aug 15 nicklas 264     return null;
6938 19 Aug 15 nicklas 265   }
6938 19 Aug 15 nicklas 266   
6938 19 Aug 15 nicklas 267   
6938 19 Aug 15 nicklas 268   /**
6938 19 Aug 15 nicklas 269     Select the given annotation entry. This will mark the annotation 
6938 19 Aug 15 nicklas 270     in the main list, display the input fields associated with it
6938 19 Aug 15 nicklas 271     and populate the input fields with the current value(s).
6938 19 Aug 15 nicklas 272   */
7832 24 Jun 20 nicklas 273   annotate.selectAnnotation = function(entryId, scrollIntoView)
6938 19 Aug 15 nicklas 274   {
6938 19 Aug 15 nicklas 275     if (selectedAnnotation)
6938 19 Aug 15 nicklas 276     {
6938 19 Aug 15 nicklas 277       Doc.removeClass(selectedAnnotation.id, 'selected');
6938 19 Aug 15 nicklas 278     }
6938 19 Aug 15 nicklas 279
6938 19 Aug 15 nicklas 280     var frm = document.forms['annotations'];
6938 19 Aug 15 nicklas 281     // Mark the selected annotation and make sure the
6938 19 Aug 15 nicklas 282     // category list doesn't hide it
6938 19 Aug 15 nicklas 283     selectedAnnotation = annotate.getEntryById(entryId);
6955 28 Sep 15 nicklas 284     selectedMultiIndex = -1;
6955 28 Sep 15 nicklas 285     
6938 19 Aug 15 nicklas 286     var classes = [];
6938 19 Aug 15 nicklas 287     var valueElement;
6938 19 Aug 15 nicklas 288     
6938 19 Aug 15 nicklas 289     if (selectedAnnotation == null)
6938 19 Aug 15 nicklas 290     {
6938 19 Aug 15 nicklas 291       classes.push('none-selected');
6938 19 Aug 15 nicklas 292       if (annotations.length == 0) 
6938 19 Aug 15 nicklas 293       {
6938 19 Aug 15 nicklas 294         classes.push('no-annotations');
6938 19 Aug 15 nicklas 295       }
6938 19 Aug 15 nicklas 296     }
6938 19 Aug 15 nicklas 297     else
6938 19 Aug 15 nicklas 298     {
6938 19 Aug 15 nicklas 299       
6938 19 Aug 15 nicklas 300       Doc.addClass(entryId, 'selected');
6938 19 Aug 15 nicklas 301       if (Doc.element(entryId).style.display=='none')
6938 19 Aug 15 nicklas 302       {
6938 19 Aug 15 nicklas 303         // Make sure the entry is not hidden because a different
6938 19 Aug 15 nicklas 304         // category is selected
6938 19 Aug 15 nicklas 305         frm.categories.selectedIndex = 0;
6938 19 Aug 15 nicklas 306         annotate.categoryOnChange();
6938 19 Aug 15 nicklas 307       }
7832 24 Jun 20 nicklas 308       if (scrollIntoView) Doc.element(entryId).scrollIntoView({block: 'center'});
6938 19 Aug 15 nicklas 309       
6938 19 Aug 15 nicklas 310       var at = selectedAnnotation.annotationType;
6938 19 Aug 15 nicklas 311       var ann = selectedAnnotation.annotation;
6938 19 Aug 15 nicklas 312       
6938 19 Aug 15 nicklas 313       annotate.showNameAndOtherInfo(at);
6943 01 Sep 15 nicklas 314       classes.push('has-selected');
6938 19 Aug 15 nicklas 315       classes.push(selectedAnnotation.source);
6938 19 Aug 15 nicklas 316       if (at.description) classes.push('has-description');
7206 19 Oct 16 nicklas 317       if (!selectedAnnotation.annotatePermission) classes.push('no-annotate-permission');
6938 19 Aug 15 nicklas 318       
7334 11 Apr 17 nicklas 319       if (at.projectAnnotations && ann)
7334 11 Apr 17 nicklas 320       {
7334 11 Apr 17 nicklas 321         var msg = '';
7334 11 Apr 17 nicklas 322         var defaultValues = '';
8083 20 Oct 22 nicklas 323         var projectId = Data.int('page-data', 'project-id');
8083 20 Oct 22 nicklas 324         var activeProjectId = Data.int('page-data', 'active-project-id');
7334 11 Apr 17 nicklas 325         if (ann.projectId != 0)
7334 11 Apr 17 nicklas 326         {
7334 11 Apr 17 nicklas 327           if (ann.override)
7334 11 Apr 17 nicklas 328           {
7334 11 Apr 17 nicklas 329             msg = 'This is a project-specific annotation that overrides  the default value:<br>';
7334 11 Apr 17 nicklas 330             var defA = selectedAnnotation.defaultValues;
7334 11 Apr 17 nicklas 331             var symbol = defA.unitSymbol ? ' ' + defA.unitSymbol : '';
7334 11 Apr 17 nicklas 332             defaultValues = Strings.encodeTags(defA.values.join(symbol+', ')+symbol);
7334 11 Apr 17 nicklas 333           }
7334 11 Apr 17 nicklas 334           else
7334 11 Apr 17 nicklas 335           {
7334 11 Apr 17 nicklas 336             msg = 'This is a project-specific annotation without a default value.';
7334 11 Apr 17 nicklas 337           }
7334 11 Apr 17 nicklas 338         }
7334 11 Apr 17 nicklas 339         else
7334 11 Apr 17 nicklas 340         {
8083 20 Oct 22 nicklas 341           msg = 'This is the default value for a project annotation.';
8083 20 Oct 22 nicklas 342           if (projectId < 0 && activeProjectId > 0) msg += '<br>Changing it will create a project-specific value.';
7334 11 Apr 17 nicklas 343         }
7334 11 Apr 17 nicklas 344         Doc.element('project-annotations-message').innerHTML = msg;
7334 11 Apr 17 nicklas 345         Doc.element('default-values').innerHTML = defaultValues;
7334 11 Apr 17 nicklas 346         classes.push('project-annotations');
7334 11 Apr 17 nicklas 347       }
7334 11 Apr 17 nicklas 348       
6938 19 Aug 15 nicklas 349       if (selectedAnnotation.source != 'PRIMARY')
6938 19 Aug 15 nicklas 350       {
6938 19 Aug 15 nicklas 351         var inherited = selectedAnnotation.inherited;
6938 19 Aug 15 nicklas 352         if (inherited)
6938 19 Aug 15 nicklas 353         {
6938 19 Aug 15 nicklas 354           var symbol = inherited.unitSymbol ? ' ' + inherited.unitSymbol : '';
6943 01 Sep 15 nicklas 355           
6938 19 Aug 15 nicklas 356           Doc.element('inherited-values').innerHTML = Strings.encodeTags(inherited.values.join(symbol+', ')+symbol);
6943 01 Sep 15 nicklas 357           Doc.element('inherited-item').innerHTML = (selectedAnnotation.source == 'CLONED' ? 'Cloned from ' : 'Inherited from ') + Strings.encodeTags(inherited.from.name) + ' <span class="itemsubtype">('+inherited.from.type+')</span>';
6943 01 Sep 15 nicklas 358           
6943 01 Sep 15 nicklas 359           if (selectedAnnotation.source == 'CLONED' && inherited.lastUpdate > ann.lastUpdate)
6943 01 Sep 15 nicklas 360           {
6943 01 Sep 15 nicklas 361             classes.push('modified');
6943 01 Sep 15 nicklas 362           }
6943 01 Sep 15 nicklas 363           
6938 19 Aug 15 nicklas 364         }
6938 19 Aug 15 nicklas 365         else
6938 19 Aug 15 nicklas 366         {
6938 19 Aug 15 nicklas 367           classes.push('inherited-missing');
6938 19 Aug 15 nicklas 368         }
6938 19 Aug 15 nicklas 369       }
6938 19 Aug 15 nicklas 370       
6938 19 Aug 15 nicklas 371       if (!at.enumeration)
6938 19 Aug 15 nicklas 372       {
6938 19 Aug 15 nicklas 373         // Just display the correct input section
6938 19 Aug 15 nicklas 374         classes.push(at.valueType);
6938 19 Aug 15 nicklas 375         valueElement = frm[at.valueType+'-input'];
6938 19 Aug 15 nicklas 376       }
6938 19 Aug 15 nicklas 377       else
6938 19 Aug 15 nicklas 378       {
6938 19 Aug 15 nicklas 379         // We need to populate the selection list or
6938 19 Aug 15 nicklas 380         // generate radiobuttons/checkboxes
6938 19 Aug 15 nicklas 381         var symbol = at.defaultUnit ? ' ' + at.defaultSymbol : '';
6938 19 Aug 15 nicklas 382         if (at.displayAsList)
6938 19 Aug 15 nicklas 383         {
6938 19 Aug 15 nicklas 384           classes.push(at.multiplicity == 1 ? 'ENUM-SINGLE' : 'ENUM-MULTIPLE');
6938 19 Aug 15 nicklas 385           var list = Doc.element(at.multiplicity == 1 ? 'ENUM-SINGLE-input' : 'ENUM-MULTIPLE-input');
6943 01 Sep 15 nicklas 386           annotate.initEnumList(list, at.enumeration, at.multiplicity == 1 && selectedAnnotation.source == 'PRIMARY', symbol);
6938 19 Aug 15 nicklas 387           valueElement = list;          
6938 19 Aug 15 nicklas 388         }
6938 19 Aug 15 nicklas 389         else
6938 19 Aug 15 nicklas 390         {
6938 19 Aug 15 nicklas 391           classes.push('ENUM-RADIO-CHECKBOX');
6943 01 Sep 15 nicklas 392           var tmp = annotate.initEnumCheckboxes(at.enumeration, at.multiplicity == 1, symbol, selectedAnnotation.source == 'PRIMARY');
6938 19 Aug 15 nicklas 393           Doc.element('ENUM-RADIO-CHECKBOX').innerHTML = '';
6938 19 Aug 15 nicklas 394           Doc.element('ENUM-RADIO-CHECKBOX').appendChild(tmp);
6938 19 Aug 15 nicklas 395           valueElement = frm['check'];
6938 19 Aug 15 nicklas 396         }
6938 19 Aug 15 nicklas 397       }
6938 19 Aug 15 nicklas 398     
6938 19 Aug 15 nicklas 399       if (at.units)
6938 19 Aug 15 nicklas 400       {
6938 19 Aug 15 nicklas 401         classes.push('has-unit')
6938 19 Aug 15 nicklas 402         annotate.initUnitList(at.units, ann && ann.unit || at.defaultUnit);
6938 19 Aug 15 nicklas 403       }
6938 19 Aug 15 nicklas 404       
6955 28 Sep 15 nicklas 405       
6938 19 Aug 15 nicklas 406       // Fill form with current values
6955 28 Sep 15 nicklas 407       var values = ann.values.length > 0 || at.multiplicity != 1 ? ann.values : [''];
6938 19 Aug 15 nicklas 408       if (valueElement.type && valueElement.type.indexOf('select') == 0)
6938 19 Aug 15 nicklas 409       {
6938 19 Aug 15 nicklas 410         // selection list
6938 19 Aug 15 nicklas 411         Forms.selectListOptions(valueElement, values);
6938 19 Aug 15 nicklas 412       }
6938 19 Aug 15 nicklas 413       else if (valueElement.length)
6938 19 Aug 15 nicklas 414       {
6938 19 Aug 15 nicklas 415         // radio buttons or checkboxes
6938 19 Aug 15 nicklas 416         if (at.multiplicity == 1)
6938 19 Aug 15 nicklas 417         {
6938 19 Aug 15 nicklas 418           Forms.checkRadio(valueElement, values[0]);
6938 19 Aug 15 nicklas 419         }
6938 19 Aug 15 nicklas 420         else
6938 19 Aug 15 nicklas 421         {
6938 19 Aug 15 nicklas 422           Forms.checkCheckBoxes(valueElement, values);
6938 19 Aug 15 nicklas 423         }
6938 19 Aug 15 nicklas 424       }
6938 19 Aug 15 nicklas 425       else
6938 19 Aug 15 nicklas 426       {
6938 19 Aug 15 nicklas 427         // regular input field
6938 19 Aug 15 nicklas 428         if (at.multiplicity == 1)
6938 19 Aug 15 nicklas 429         {
6938 19 Aug 15 nicklas 430           valueElement.value = values[0];
6938 19 Aug 15 nicklas 431         }
6938 19 Aug 15 nicklas 432         else
6938 19 Aug 15 nicklas 433         {
6955 28 Sep 15 nicklas 434           classes.push('multiple');
6955 28 Sep 15 nicklas 435           // Fill the 'multi-values' list with the current values
6955 28 Sep 15 nicklas 436           var multiValues = frm['multi-values'];
6955 28 Sep 15 nicklas 437           multiValues.length = 0;
6955 28 Sep 15 nicklas 438           for (var i = 0; i < values.length; i++) 
6955 28 Sep 15 nicklas 439           {
6955 28 Sep 15 nicklas 440             multiValues[multiValues.length] = new Option(values[i]);
6955 28 Sep 15 nicklas 441           }
6955 28 Sep 15 nicklas 442           valueElement.value = '';
6938 19 Aug 15 nicklas 443         }
6938 19 Aug 15 nicklas 444       }
6938 19 Aug 15 nicklas 445     }
6938 19 Aug 15 nicklas 446     Doc.element('selected-container').className = classes.join(' ');
6938 19 Aug 15 nicklas 447     if (valueElement && valueElement.focus) valueElement.focus();
6938 19 Aug 15 nicklas 448   }
6938 19 Aug 15 nicklas 449   
6938 19 Aug 15 nicklas 450   /**
6938 19 Aug 15 nicklas 451     Display information about the annotation.
6938 19 Aug 15 nicklas 452   */
6938 19 Aug 15 nicklas 453   annotate.showNameAndOtherInfo = function(at)
6938 19 Aug 15 nicklas 454   {
6938 19 Aug 15 nicklas 455     Doc.element('selected-name').innerHTML = Strings.encodeTags(at.name);
6938 19 Aug 15 nicklas 456     Doc.element('selected-description').innerHTML = at.description || '';
6938 19 Aug 15 nicklas 457     
6938 19 Aug 15 nicklas 458     var typeSummary = at.valueType;
6938 19 Aug 15 nicklas 459     if (at.enumeration)
6938 19 Aug 15 nicklas 460     {
6938 19 Aug 15 nicklas 461       if (at.multiplicity == 0)
6938 19 Aug 15 nicklas 462       {
6938 19 Aug 15 nicklas 463         typeSummary = "Select one or more";
6938 19 Aug 15 nicklas 464       }
6938 19 Aug 15 nicklas 465       else if (at.multiplicity == 1)
6938 19 Aug 15 nicklas 466       {
6938 19 Aug 15 nicklas 467         typeSummary = "Select one";
6938 19 Aug 15 nicklas 468       }
6938 19 Aug 15 nicklas 469       else
6938 19 Aug 15 nicklas 470       {
6938 19 Aug 15 nicklas 471         typeSummary = "Select 1‒"+at.multiplicity;
6938 19 Aug 15 nicklas 472       }
6938 19 Aug 15 nicklas 473     }
6938 19 Aug 15 nicklas 474     else
6938 19 Aug 15 nicklas 475     {
6938 19 Aug 15 nicklas 476       if (at.minValue != null && at.maxValue != null)
6938 19 Aug 15 nicklas 477       {
6938 19 Aug 15 nicklas 478         typeSummary += ': '+at.minValue+'-'+at.maxValue;
6938 19 Aug 15 nicklas 479       }
6938 19 Aug 15 nicklas 480       else if (at.minValue != null)
6938 19 Aug 15 nicklas 481       {
6938 19 Aug 15 nicklas 482         typeSummary += ' &gt;= '+at.minValue;
6938 19 Aug 15 nicklas 483       }
6938 19 Aug 15 nicklas 484       else if (at.maxValue != null)
6938 19 Aug 15 nicklas 485       {
6938 19 Aug 15 nicklas 486         typeSummary += ' &lt;= '+at.maxValue;
6938 19 Aug 15 nicklas 487       }
6955 28 Sep 15 nicklas 488       if (at.multiplicity > 1)
6955 28 Sep 15 nicklas 489       {
6955 28 Sep 15 nicklas 490         typeSummary += '; max '+at.multiplicity+' values';
6955 28 Sep 15 nicklas 491       }
6938 19 Aug 15 nicklas 492     }
6938 19 Aug 15 nicklas 493     Doc.element('selected-type').innerHTML = typeSummary;
6938 19 Aug 15 nicklas 494   }
6938 19 Aug 15 nicklas 495   
6938 19 Aug 15 nicklas 496   /**
6938 19 Aug 15 nicklas 497     Initialize the units list with the given units.
6938 19 Aug 15 nicklas 498     'selected' is the id of the unit that should be
6938 19 Aug 15 nicklas 499     selected.
6938 19 Aug 15 nicklas 500    */
6938 19 Aug 15 nicklas 501   annotate.initUnitList = function(units, selected)
6938 19 Aug 15 nicklas 502   {
6938 19 Aug 15 nicklas 503     var unitList = Doc.element('unit');
6938 19 Aug 15 nicklas 504     unitList.length = 0;
6938 19 Aug 15 nicklas 505     for (var unitNo = 0; unitNo < units.length; unitNo++)
6938 19 Aug 15 nicklas 506     {
6938 19 Aug 15 nicklas 507       var unit = units[unitNo];
6981 08 Oct 15 nicklas 508       var option = new Option(unit.symbol, unit.id, false, selected == unit.id);
6938 19 Aug 15 nicklas 509       option.title = unit.description;
6938 19 Aug 15 nicklas 510       unitList[unitList.length] = option;
6938 19 Aug 15 nicklas 511     }
6938 19 Aug 15 nicklas 512   }
6938 19 Aug 15 nicklas 513   
6938 19 Aug 15 nicklas 514   /**
6938 19 Aug 15 nicklas 515     Fill the given <select> list with the given
6938 19 Aug 15 nicklas 516     options. If 'notSpecified' is set, the first
6938 19 Aug 15 nicklas 517     option will be 'not specified'.
6938 19 Aug 15 nicklas 518   */
6938 19 Aug 15 nicklas 519   annotate.initEnumList = function(list, values, notSpecified, unit)
6938 19 Aug 15 nicklas 520   {
6938 19 Aug 15 nicklas 521     list.length = 0;
6938 19 Aug 15 nicklas 522     if (notSpecified)
6938 19 Aug 15 nicklas 523     {
6938 19 Aug 15 nicklas 524       list[0] = new Option('- not specified -', '');
6938 19 Aug 15 nicklas 525       list[0].className = 'not-specified';
6938 19 Aug 15 nicklas 526     }
6938 19 Aug 15 nicklas 527     for (var valueNo = 0; valueNo < values.length; valueNo++)
6938 19 Aug 15 nicklas 528     {
6938 19 Aug 15 nicklas 529       var value = values[valueNo];
6938 19 Aug 15 nicklas 530       list[list.length] = new Option(value+unit, value);
6938 19 Aug 15 nicklas 531     }
6938 19 Aug 15 nicklas 532   }
6938 19 Aug 15 nicklas 533   
6938 19 Aug 15 nicklas 534   /**
6938 19 Aug 15 nicklas 535     Generate checkboxes or radiobuttons for an enumeration
6938 19 Aug 15 nicklas 536     annotation.
6938 19 Aug 15 nicklas 537   */
6943 01 Sep 15 nicklas 538   annotate.initEnumCheckboxes = function(values, radio, unit, includeNotSpecified)
6938 19 Aug 15 nicklas 539   {
6938 19 Aug 15 nicklas 540     var tmp = document.createDocumentFragment();
6938 19 Aug 15 nicklas 541     var ctlType = radio ? 'radio' : 'checkbox';
6955 28 Sep 15 nicklas 542     if (includeNotSpecified && radio)
6938 19 Aug 15 nicklas 543     {
6938 19 Aug 15 nicklas 544       var noop = annotate.createRadioOrCheckBox(ctlType, '', '- not specified -');
6938 19 Aug 15 nicklas 545       noop.className = 'not-specified';
6938 19 Aug 15 nicklas 546       tmp.appendChild(noop);
6938 19 Aug 15 nicklas 547     }
6938 19 Aug 15 nicklas 548     for (var valueNo = 0; valueNo < values.length; valueNo++)
6938 19 Aug 15 nicklas 549     {
6938 19 Aug 15 nicklas 550       var value = values[valueNo];
6938 19 Aug 15 nicklas 551       tmp.appendChild(annotate.createRadioOrCheckBox(ctlType, value, value+unit));
6938 19 Aug 15 nicklas 552     }
6938 19 Aug 15 nicklas 553     return tmp;
6938 19 Aug 15 nicklas 554   }
6938 19 Aug 15 nicklas 555
6938 19 Aug 15 nicklas 556   /**
6938 19 Aug 15 nicklas 557     Create a <input> element that is either a radio och checkbox.
6938 19 Aug 15 nicklas 558   */
6938 19 Aug 15 nicklas 559   annotate.createRadioOrCheckBox = function(type, value, text)
6938 19 Aug 15 nicklas 560   {
6938 19 Aug 15 nicklas 561     var ctl = document.createElement('input');
6938 19 Aug 15 nicklas 562     ctl.type = type;
6938 19 Aug 15 nicklas 563     ctl.name = 'check';
6938 19 Aug 15 nicklas 564     ctl.value = value;
6938 19 Aug 15 nicklas 565     Events.addEventHandler(ctl, 'click', annotate.valueOnChange);
6938 19 Aug 15 nicklas 566     var lbl = document.createElement('label');
6938 19 Aug 15 nicklas 567     lbl.appendChild(ctl);
6938 19 Aug 15 nicklas 568     lbl.appendChild(document.createTextNode(text));
6938 19 Aug 15 nicklas 569     lbl.appendChild(document.createElement('br'));
6938 19 Aug 15 nicklas 570     return lbl;
6938 19 Aug 15 nicklas 571   }
6938 19 Aug 15 nicklas 572   
6938 19 Aug 15 nicklas 573   /**
6938 19 Aug 15 nicklas 574     Event handler for selecting annotations from the main list.
6938 19 Aug 15 nicklas 575   */
6938 19 Aug 15 nicklas 576   annotate.annotationOnClick = function(event)
6938 19 Aug 15 nicklas 577   {
6938 19 Aug 15 nicklas 578     annotate.selectAnnotation(event.currentTarget.id);
6938 19 Aug 15 nicklas 579   }
6938 19 Aug 15 nicklas 580   
6938 19 Aug 15 nicklas 581   /**
6938 19 Aug 15 nicklas 582     Update the given annotation with a single value. All existing
6938 19 Aug 15 nicklas 583     values are overwritten. If the value is not accepted an
6938 19 Aug 15 nicklas 584     exception is thrown.
6938 19 Aug 15 nicklas 585   */
6955 28 Sep 15 nicklas 586   annotate.setSingleValue = function(entry, value)
6938 19 Aug 15 nicklas 587   {
6938 19 Aug 15 nicklas 588     var values = [];
6938 19 Aug 15 nicklas 589     if (value != null && value != '')
6938 19 Aug 15 nicklas 590     {
6938 19 Aug 15 nicklas 591       values[0] = value;
6938 19 Aug 15 nicklas 592     }
6955 28 Sep 15 nicklas 593     annotate.setMultipleValues(entry, values);
6938 19 Aug 15 nicklas 594   }
6938 19 Aug 15 nicklas 595   
6938 19 Aug 15 nicklas 596   /**
6938 19 Aug 15 nicklas 597     Update the given annotation with multiple values. All existing
6938 19 Aug 15 nicklas 598     values are overwritten. If the values are not accepted an
6938 19 Aug 15 nicklas 599     exception is thrown.
6938 19 Aug 15 nicklas 600   */
6955 28 Sep 15 nicklas 601   annotate.setMultipleValues = function(entry, values)
6938 19 Aug 15 nicklas 602   {
6955 28 Sep 15 nicklas 603     var at = entry.annotationType;
6955 28 Sep 15 nicklas 604     var ann = entry.annotation;
6938 19 Aug 15 nicklas 605     
6938 19 Aug 15 nicklas 606     if (at.multiplicity > 0 && values.length > at.multiplicity)
6938 19 Aug 15 nicklas 607     {
6938 19 Aug 15 nicklas 608       throw 'Max '+at.multiplicity+' values allowed';
6938 19 Aug 15 nicklas 609     }
6938 19 Aug 15 nicklas 610     ann.values = values;
6955 28 Sep 15 nicklas 611     entry.modified = MODIFIED;
6955 28 Sep 15 nicklas 612     annotate.updateIcon(entry);
6938 19 Aug 15 nicklas 613   }
6938 19 Aug 15 nicklas 614   
6938 19 Aug 15 nicklas 615   /**
6938 19 Aug 15 nicklas 616     Update/add/remove a single value in a multi-valued annotation. If the value
6938 19 Aug 15 nicklas 617     is not accepted an exception is thrown.
6938 19 Aug 15 nicklas 618   */
6955 28 Sep 15 nicklas 619   annotate.setIndexedValue = function(entry, index, value)
6938 19 Aug 15 nicklas 620   {
6955 28 Sep 15 nicklas 621     var ann = entry.annotation;
6955 28 Sep 15 nicklas 622     var at = entry.annotationType;
6955 28 Sep 15 nicklas 623     
6938 19 Aug 15 nicklas 624     if (!value)
6938 19 Aug 15 nicklas 625     {
6955 28 Sep 15 nicklas 626       if (index < ann.values.length)
6938 19 Aug 15 nicklas 627       {
6955 28 Sep 15 nicklas 628         ann.values.splice(index, 1);
6938 19 Aug 15 nicklas 629       }
6938 19 Aug 15 nicklas 630     }
6938 19 Aug 15 nicklas 631     else
6938 19 Aug 15 nicklas 632     {
6955 28 Sep 15 nicklas 633       if (index >= ann.values.length)
6938 19 Aug 15 nicklas 634       {
6938 19 Aug 15 nicklas 635         // Add a new value
6955 28 Sep 15 nicklas 636         if (at.multiplicity > 0 && ann.values.length >= at.multiplicity)
6938 19 Aug 15 nicklas 637         {
6955 28 Sep 15 nicklas 638           throw 'Max '+at.multiplicity+' values allowed';
6938 19 Aug 15 nicklas 639         }
6955 28 Sep 15 nicklas 640         index = ann.values.length;
6938 19 Aug 15 nicklas 641       }
6955 28 Sep 15 nicklas 642       ann.values[index] = value;
6938 19 Aug 15 nicklas 643     }
6955 28 Sep 15 nicklas 644     entry.modified = MODIFIED;
6955 28 Sep 15 nicklas 645     annotate.updateIcon(entry);
6938 19 Aug 15 nicklas 646   }
6938 19 Aug 15 nicklas 647   
6938 19 Aug 15 nicklas 648   /**
6938 19 Aug 15 nicklas 649     Change the unit of the given annotation.
6938 19 Aug 15 nicklas 650   */
6938 19 Aug 15 nicklas 651   annotate.setUnit = function(annotation, unit)
6938 19 Aug 15 nicklas 652   {
6938 19 Aug 15 nicklas 653     annotation.annotation.unit = unit;
6943 01 Sep 15 nicklas 654     annotation.modified = MODIFIED;
6938 19 Aug 15 nicklas 655   }
6938 19 Aug 15 nicklas 656   
6938 19 Aug 15 nicklas 657   /**
6938 19 Aug 15 nicklas 658     Event handler that is executed when an annotation values has changed.
6938 19 Aug 15 nicklas 659     This new value should be stored back into the 'annotations' array.
6938 19 Aug 15 nicklas 660     The exact procedure depends on the type of value.
6938 19 Aug 15 nicklas 661   */
6938 19 Aug 15 nicklas 662   annotate.valueOnChange = function(event)
6938 19 Aug 15 nicklas 663   {
6938 19 Aug 15 nicklas 664     if (!selectedAnnotation) return;
6938 19 Aug 15 nicklas 665     
6938 19 Aug 15 nicklas 666     var at = selectedAnnotation.annotationType;
6938 19 Aug 15 nicklas 667     var frm = document.forms['annotations'];
6938 19 Aug 15 nicklas 668     var target = event.currentTarget;
6938 19 Aug 15 nicklas 669     try
6938 19 Aug 15 nicklas 670     {
6938 19 Aug 15 nicklas 671       if (at.multiplicity == 1) 
6938 19 Aug 15 nicklas 672       {
6938 19 Aug 15 nicklas 673         // If only a single value is accepted the event target holds the new value
6938 19 Aug 15 nicklas 674         annotate.setSingleValue(selectedAnnotation, target.value);
6938 19 Aug 15 nicklas 675       }
6938 19 Aug 15 nicklas 676       else if (at.enumeration)
6938 19 Aug 15 nicklas 677       {
6938 19 Aug 15 nicklas 678         // If the annotation is a multi-valued enumeration the input fields can be either a
6938 19 Aug 15 nicklas 679         // group of checkboxes or a select control allowing multiple selections.
6938 19 Aug 15 nicklas 680         if (target.type == 'checkbox') target = frm[target.name]; // An array of all checkboxes in the group
6938 19 Aug 15 nicklas 681         var values = [];
6938 19 Aug 15 nicklas 682         for (var i = 0; i < target.length; i++)
6938 19 Aug 15 nicklas 683         {
6938 19 Aug 15 nicklas 684           if (target[i].checked || target[i].selected) 
6938 19 Aug 15 nicklas 685           {
6938 19 Aug 15 nicklas 686             values[values.length] = target[i].value;
6938 19 Aug 15 nicklas 687           }
6938 19 Aug 15 nicklas 688         }
6938 19 Aug 15 nicklas 689         annotate.setMultipleValues(selectedAnnotation, values);
6938 19 Aug 15 nicklas 690       }
6938 19 Aug 15 nicklas 691       else
6938 19 Aug 15 nicklas 692       {
6938 19 Aug 15 nicklas 693         // Otherwise we use the 'multi-values' control and update the currently
6955 28 Sep 15 nicklas 694         // selected option (but note that we can't use 'selectedIndex' property of the
6955 28 Sep 15 nicklas 695         // list control, since it may already point to the future selection
6955 28 Sep 15 nicklas 696         var selectedIndex = frm['multi-values'].selectedIndex;
6955 28 Sep 15 nicklas 697         if (selectedMultiIndex >= 0)
6938 19 Aug 15 nicklas 698         {
6955 28 Sep 15 nicklas 699           annotate.setIndexedValue(selectedAnnotation, selectedMultiIndex, target.value);
6938 19 Aug 15 nicklas 700           var multiValues = frm['multi-values'];
6938 19 Aug 15 nicklas 701           if (!target.value)
6938 19 Aug 15 nicklas 702           {
6955 28 Sep 15 nicklas 703             multiValues[selectedMultiIndex] = null;
6955 28 Sep 15 nicklas 704             selectedMultiIndex = -1;
6938 19 Aug 15 nicklas 705           }
6938 19 Aug 15 nicklas 706           else
6938 19 Aug 15 nicklas 707           {
6955 28 Sep 15 nicklas 708             multiValues[selectedMultiIndex].text = target.value;
6938 19 Aug 15 nicklas 709           }
6938 19 Aug 15 nicklas 710         }
6938 19 Aug 15 nicklas 711       }
6938 19 Aug 15 nicklas 712     }
6938 19 Aug 15 nicklas 713     catch (errorMessage)
6938 19 Aug 15 nicklas 714     {
6938 19 Aug 15 nicklas 715       event.preventDefault();
6938 19 Aug 15 nicklas 716       Forms.showNotification(event.currentTarget, errorMessage);
6938 19 Aug 15 nicklas 717     }
6938 19 Aug 15 nicklas 718   }
6938 19 Aug 15 nicklas 719   
6955 28 Sep 15 nicklas 720   // To catch the case if 'new' was clicked but no value was entered
6955 28 Sep 15 nicklas 721   annotate.valueOnBlur = function(event)
6955 28 Sep 15 nicklas 722   {
6981 08 Oct 15 nicklas 723     if (!selectedAnnotation || selectedMultiIndex < 0) return;
6955 28 Sep 15 nicklas 724     
6955 28 Sep 15 nicklas 725     var frm = document.forms['annotations'];
6955 28 Sep 15 nicklas 726     
6955 28 Sep 15 nicklas 727     if (event.currentTarget.value == '' && frm['multi-values'][selectedMultiIndex].isNewValue) 
6955 28 Sep 15 nicklas 728     {
6955 28 Sep 15 nicklas 729       // This will remove the new but empty value
6955 28 Sep 15 nicklas 730       Events.sendChangeEvent(event.currentTarget);
6955 28 Sep 15 nicklas 731     }
6955 28 Sep 15 nicklas 732     else
6955 28 Sep 15 nicklas 733     {
6955 28 Sep 15 nicklas 734       frm['multi-values'][selectedMultiIndex].isNewValue = false;
6955 28 Sep 15 nicklas 735     }
6955 28 Sep 15 nicklas 736   }
6955 28 Sep 15 nicklas 737   
6938 19 Aug 15 nicklas 738   /**
6938 19 Aug 15 nicklas 739     Event handler that handle changes to the selected unit.
6938 19 Aug 15 nicklas 740   */
6938 19 Aug 15 nicklas 741   annotate.unitOnChange = function(event)
6938 19 Aug 15 nicklas 742   {
6942 31 Aug 15 nicklas 743     annotate.setUnit(selectedAnnotation, parseInt(event.currentTarget.value));
6938 19 Aug 15 nicklas 744   }
6938 19 Aug 15 nicklas 745
6943 01 Sep 15 nicklas 746   /**
6946 07 Sep 15 nicklas 747     Toggle the checkbox for all primary annotations. Holding down
6946 07 Sep 15 nicklas 748     CTRL/SHIFT/ALT will selected or deselect all.
6946 07 Sep 15 nicklas 749   */
6946 07 Sep 15 nicklas 750   annotate.checkAllPrimary = function(event)
6946 07 Sep 15 nicklas 751   {
6946 07 Sep 15 nicklas 752     var specialKey = event.altKey || event.ctrlKey || event.shiftKey;
6946 07 Sep 15 nicklas 753     var first = null;
6946 07 Sep 15 nicklas 754     for (var i = 0; i < annotations.length; i++)
6946 07 Sep 15 nicklas 755     {
6946 07 Sep 15 nicklas 756       var entry = annotations[i];
7926 24 Feb 21 nicklas 757       if (entry.visible && entry.source == 'PRIMARY')
6946 07 Sep 15 nicklas 758       {
6946 07 Sep 15 nicklas 759         var checkbox = Doc.element('check.'+entry.id);
7206 19 Oct 16 nicklas 760         if (checkbox)
7206 19 Oct 16 nicklas 761         {
7206 19 Oct 16 nicklas 762           if (first == null) first = checkbox.checked;
7206 19 Oct 16 nicklas 763           checkbox.checked = specialKey ? !first : !checkbox.checked;
7206 19 Oct 16 nicklas 764         }
6946 07 Sep 15 nicklas 765       }
6946 07 Sep 15 nicklas 766     }
6946 07 Sep 15 nicklas 767   }
6946 07 Sep 15 nicklas 768   
6946 07 Sep 15 nicklas 769   /**
6946 07 Sep 15 nicklas 770     Toggle the checkbox for all inherited/cloned annotations. Holding down
6946 07 Sep 15 nicklas 771     CTRL/SHIFT/ALT will selected or deselect all.
6946 07 Sep 15 nicklas 772   */
6946 07 Sep 15 nicklas 773   annotate.checkAllInherited = function(event)
6946 07 Sep 15 nicklas 774   {
6946 07 Sep 15 nicklas 775     var specialKey = event.altKey || event.ctrlKey || event.shiftKey;
6946 07 Sep 15 nicklas 776     var first = null;
6946 07 Sep 15 nicklas 777     for (var i = 0; i < annotations.length; i++)
6946 07 Sep 15 nicklas 778     {
6946 07 Sep 15 nicklas 779       var entry = annotations[i];
7926 24 Feb 21 nicklas 780       if (entry.visible && entry.source != 'PRIMARY')
6946 07 Sep 15 nicklas 781       {
6946 07 Sep 15 nicklas 782         var checkbox = Doc.element('check.'+entry.id);
7206 19 Oct 16 nicklas 783         if (checkbox)
7206 19 Oct 16 nicklas 784         {
7206 19 Oct 16 nicklas 785           if (first == null) first = checkbox.checked;
7206 19 Oct 16 nicklas 786           checkbox.checked = specialKey ? !first : !checkbox.checked;
7206 19 Oct 16 nicklas 787         }
6946 07 Sep 15 nicklas 788       }
6946 07 Sep 15 nicklas 789     }
6946 07 Sep 15 nicklas 790   }
6946 07 Sep 15 nicklas 791   
6946 07 Sep 15 nicklas 792   /**
6945 04 Sep 15 nicklas 793     Call the given method for all annotations that
6945 04 Sep 15 nicklas 794     have been checked. The method must take a single
6945 04 Sep 15 nicklas 795     parameter which is the entry object with the
6945 04 Sep 15 nicklas 796     annotation information.
6945 04 Sep 15 nicklas 797     @return The return value of the method when called
6945 04 Sep 15 nicklas 798       on the current selected annotation or null if the
6945 04 Sep 15 nicklas 799       selected annotation is not checked
6945 04 Sep 15 nicklas 800    */
6945 04 Sep 15 nicklas 801   annotate.forAllChecked = function(method)
6945 04 Sep 15 nicklas 802   {
6945 04 Sep 15 nicklas 803     var returnValue = null;
6945 04 Sep 15 nicklas 804     var numChecked = 0;
6945 04 Sep 15 nicklas 805     for (var i = 0; i < annotations.length; i++)
6945 04 Sep 15 nicklas 806     {
6945 04 Sep 15 nicklas 807       var entry = annotations[i];
7206 19 Oct 16 nicklas 808       var checkbox = Doc.element('check.'+entry.id);
7206 19 Oct 16 nicklas 809       if (checkbox && checkbox.checked)
6945 04 Sep 15 nicklas 810       {
6945 04 Sep 15 nicklas 811         numChecked++;
6945 04 Sep 15 nicklas 812         var rv = method.call(null, entry);
6945 04 Sep 15 nicklas 813         if (entry == selectedAnnotation) returnValue = rv;
6945 04 Sep 15 nicklas 814       }
6945 04 Sep 15 nicklas 815     }
6945 04 Sep 15 nicklas 816     if (numChecked == 0)
6945 04 Sep 15 nicklas 817     {
6945 04 Sep 15 nicklas 818       Forms.showNotification('annotation-list', 'Please select annotations first...', null, 'pointer-left');
6945 04 Sep 15 nicklas 819     }
6945 04 Sep 15 nicklas 820     return returnValue;
6945 04 Sep 15 nicklas 821   }
6945 04 Sep 15 nicklas 822   
6945 04 Sep 15 nicklas 823   /**
6945 04 Sep 15 nicklas 824     Synchronizes checked CLONED annotations.
6945 04 Sep 15 nicklas 825   */
6945 04 Sep 15 nicklas 826   annotate.syncAllCheckedClones = function()
6945 04 Sep 15 nicklas 827   {
6945 04 Sep 15 nicklas 828     if (annotate.forAllChecked(annotate.syncClone))
6945 04 Sep 15 nicklas 829     {
6945 04 Sep 15 nicklas 830       annotate.selectAnnotation(selectedAnnotation.id);
6945 04 Sep 15 nicklas 831     }
6945 04 Sep 15 nicklas 832   }
6945 04 Sep 15 nicklas 833   
6945 04 Sep 15 nicklas 834   /**
6945 04 Sep 15 nicklas 835     Synchronizes the currently selected CLONED annotation
6945 04 Sep 15 nicklas 836    */
6945 04 Sep 15 nicklas 837   annotate.syncSelectedClone = function()
6945 04 Sep 15 nicklas 838   {
6945 04 Sep 15 nicklas 839     annotate.syncClone(selectedAnnotation);
6945 04 Sep 15 nicklas 840     annotate.selectAnnotation(selectedAnnotation.id);
6945 04 Sep 15 nicklas 841   }
6945 04 Sep 15 nicklas 842   
6945 04 Sep 15 nicklas 843   /**
6943 01 Sep 15 nicklas 844     Syncs a cloned value with the parent items value.
6945 04 Sep 15 nicklas 845     @returns TRUE if the entry was synced, FALSE if not.
6943 01 Sep 15 nicklas 846   */
6945 04 Sep 15 nicklas 847   annotate.syncClone = function(entry)
6943 01 Sep 15 nicklas 848   {
6945 04 Sep 15 nicklas 849     if (entry.source != 'CLONED') return false;
6945 04 Sep 15 nicklas 850     if (!entry.inherited) return false;
6943 01 Sep 15 nicklas 851     
6945 04 Sep 15 nicklas 852     annotate.setMultipleValues(entry, entry.inherited.values);
6945 04 Sep 15 nicklas 853     annotate.setUnit(entry, entry.inherited.unit);
6945 04 Sep 15 nicklas 854     entry.annotation.lastUpdate = entry.inherited.lastUpdate;
6945 04 Sep 15 nicklas 855     entry.modified = SYNCED;
6945 04 Sep 15 nicklas 856     annotate.updateIcon(entry);
6943 01 Sep 15 nicklas 857     
6945 04 Sep 15 nicklas 858     return true;
6943 01 Sep 15 nicklas 859   }
6943 01 Sep 15 nicklas 860   
6945 04 Sep 15 nicklas 861   
6943 01 Sep 15 nicklas 862   /**
6945 04 Sep 15 nicklas 863     Converts checked INHERITED annotations to CLONED annotations.
6945 04 Sep 15 nicklas 864   */
6945 04 Sep 15 nicklas 865   annotate.convertAllCheckedToCloned = function()
6945 04 Sep 15 nicklas 866   {
6945 04 Sep 15 nicklas 867     if (annotate.forAllChecked(annotate.convertToCloned))
6945 04 Sep 15 nicklas 868     {
6945 04 Sep 15 nicklas 869       annotate.selectAnnotation(selectedAnnotation.id);
6945 04 Sep 15 nicklas 870     }
6945 04 Sep 15 nicklas 871   }
6945 04 Sep 15 nicklas 872
6945 04 Sep 15 nicklas 873   /**
6945 04 Sep 15 nicklas 874     Converts the selected annotation to a CLONED annotation.
6945 04 Sep 15 nicklas 875   */
6945 04 Sep 15 nicklas 876   annotate.convertSelectedToCloned = function()
6945 04 Sep 15 nicklas 877   {
6945 04 Sep 15 nicklas 878     annotate.convertToCloned(selectedAnnotation);
6945 04 Sep 15 nicklas 879     annotate.selectAnnotation(selectedAnnotation.id);
6945 04 Sep 15 nicklas 880   }
6945 04 Sep 15 nicklas 881
6945 04 Sep 15 nicklas 882   /**
6943 01 Sep 15 nicklas 883     Converts an INHERITED annotation to a CLONED annotation.
6943 01 Sep 15 nicklas 884   */
6945 04 Sep 15 nicklas 885   annotate.convertToCloned = function(entry)
6943 01 Sep 15 nicklas 886   {
6945 04 Sep 15 nicklas 887     if (entry.source != 'INHERITED') return false;
6943 01 Sep 15 nicklas 888     
6945 04 Sep 15 nicklas 889     var ann = entry.annotation;
6945 04 Sep 15 nicklas 890     var inherited = entry.inherited;
6943 01 Sep 15 nicklas 891     
6945 04 Sep 15 nicklas 892     entry.source = 'CLONED';
6945 04 Sep 15 nicklas 893     entry.modified = CONVERTED;
6943 01 Sep 15 nicklas 894     ann.values = inherited.values;
6943 01 Sep 15 nicklas 895     ann.unit = inherited.unit;
6945 04 Sep 15 nicklas 896     annotate.updateIcon(entry);
6945 04 Sep 15 nicklas 897
6945 04 Sep 15 nicklas 898     return true;
6943 01 Sep 15 nicklas 899   }
6943 01 Sep 15 nicklas 900
6943 01 Sep 15 nicklas 901   /**
6945 04 Sep 15 nicklas 902     Converts checked CLONED annotations to INHERITED annotations.
6945 04 Sep 15 nicklas 903   */
6945 04 Sep 15 nicklas 904   annotate.convertAllCheckedToInherited = function()
6945 04 Sep 15 nicklas 905   {
6945 04 Sep 15 nicklas 906     if (annotate.forAllChecked(annotate.convertToInherited))
6945 04 Sep 15 nicklas 907     {
6945 04 Sep 15 nicklas 908       annotate.selectAnnotation(selectedAnnotation.id);
6945 04 Sep 15 nicklas 909     }
6945 04 Sep 15 nicklas 910   }
6945 04 Sep 15 nicklas 911
6945 04 Sep 15 nicklas 912   /**
6943 01 Sep 15 nicklas 913     Converts a CLONED annotation to an INHERITED annotation.
6946 07 Sep 15 nicklas 914     If the annotation is not CLONED or if the parent item
6946 07 Sep 15 nicklas 915     is unknown, nothing is done.
6943 01 Sep 15 nicklas 916   */
6945 04 Sep 15 nicklas 917   annotate.convertToInherited = function(entry)
6943 01 Sep 15 nicklas 918   {
6945 04 Sep 15 nicklas 919     if (entry.source != 'CLONED') return false;
6943 01 Sep 15 nicklas 920     
6945 04 Sep 15 nicklas 921     var ann = entry.annotation;
6945 04 Sep 15 nicklas 922     var inherited = entry.inherited;
6946 07 Sep 15 nicklas 923     if (!inherited) return false;
6943 01 Sep 15 nicklas 924     
6945 04 Sep 15 nicklas 925     entry.source = 'INHERITED';
6945 04 Sep 15 nicklas 926     entry.modified = CONVERTED;
6943 01 Sep 15 nicklas 927     ann.values = [];
6943 01 Sep 15 nicklas 928     ann.unit = null;
6945 04 Sep 15 nicklas 929     annotate.updateIcon(entry);
6945 04 Sep 15 nicklas 930     return true;
6943 01 Sep 15 nicklas 931   }
6943 01 Sep 15 nicklas 932
6946 07 Sep 15 nicklas 933   /**
6946 07 Sep 15 nicklas 934     Delete all checked annotations.
6946 07 Sep 15 nicklas 935   */
6945 04 Sep 15 nicklas 936   annotate.deleteAllChecked = function()
6945 04 Sep 15 nicklas 937   {
6945 04 Sep 15 nicklas 938     if (annotate.forAllChecked(annotate.deleteAnnotation))
6945 04 Sep 15 nicklas 939     {
6945 04 Sep 15 nicklas 940       annotate.selectAnnotation(selectedAnnotation.source == 'PRIMARY' ? selectedAnnotation.id : null);
6945 04 Sep 15 nicklas 941     }
6945 04 Sep 15 nicklas 942   }
6943 01 Sep 15 nicklas 943   
6946 07 Sep 15 nicklas 944   /**
6946 07 Sep 15 nicklas 945     Delete an annotation. PRIMARY annotations have all their values removed.
6946 07 Sep 15 nicklas 946     INHERITED/CLONED annotations are deleted.
6946 07 Sep 15 nicklas 947   */
6945 04 Sep 15 nicklas 948   annotate.deleteAnnotation = function(entry)
6945 04 Sep 15 nicklas 949   {
6945 04 Sep 15 nicklas 950     if (entry.source == 'PRIMARY')
6945 04 Sep 15 nicklas 951     {
6946 07 Sep 15 nicklas 952       entry.modified = MODIFIED;
6945 04 Sep 15 nicklas 953       entry.annotation.values = [];
6945 04 Sep 15 nicklas 954       entry.annotation.unit = null;
6945 04 Sep 15 nicklas 955       annotate.updateIcon(entry);
6945 04 Sep 15 nicklas 956     }
6945 04 Sep 15 nicklas 957     else
6945 04 Sep 15 nicklas 958     {
6946 07 Sep 15 nicklas 959       entry.modified = DELETE;
6945 04 Sep 15 nicklas 960       Doc.hide(entry.id);
6945 04 Sep 15 nicklas 961     }
6945 04 Sep 15 nicklas 962     return true;
6945 04 Sep 15 nicklas 963   }
6945 04 Sep 15 nicklas 964   
6947 08 Sep 15 nicklas 965   /**
6947 08 Sep 15 nicklas 966     Open a popup dialog for selecting parent annotations
6947 08 Sep 15 nicklas 967     that should be inherited.
6947 08 Sep 15 nicklas 968   */
6947 08 Sep 15 nicklas 969   annotate.addInheritedAnnotations = function(event)
6947 08 Sep 15 nicklas 970   {
6947 08 Sep 15 nicklas 971     var url = 'inherit.jsp?ID='+App.getSessionId();
6947 08 Sep 15 nicklas 972     url += '&item_type='+Data.get('page-data', 'item-type');
6947 08 Sep 15 nicklas 973     url += '&item_id='+Data.get('page-data', 'item-id');
6947 08 Sep 15 nicklas 974     url += '&callback='+event.currentTarget.id;
6947 08 Sep 15 nicklas 975     
6947 08 Sep 15 nicklas 976     // Items marked for DELETE should show up in the dialog
6947 08 Sep 15 nicklas 977     var deleted = [];
6947 08 Sep 15 nicklas 978     for (var i = 0; i < annotations.length; i++)
6947 08 Sep 15 nicklas 979     {
6947 08 Sep 15 nicklas 980       var entry = annotations[i];
6947 08 Sep 15 nicklas 981       if (entry.source != 'PRIMARY' && entry.modified == DELETE && entry.annotation.id)
6947 08 Sep 15 nicklas 982       {
6947 08 Sep 15 nicklas 983         deleted[deleted.length] = entry.annotation.id;
6947 08 Sep 15 nicklas 984       }
6947 08 Sep 15 nicklas 985     }
6947 08 Sep 15 nicklas 986     url += '&deleted='+deleted.join(',');
6947 08 Sep 15 nicklas 987     
6947 08 Sep 15 nicklas 988     if (parents.length)
6947 08 Sep 15 nicklas 989     {
6947 08 Sep 15 nicklas 990       url += '&parents='+parents.join('&parents=');
6947 08 Sep 15 nicklas 991     }
6947 08 Sep 15 nicklas 992     
6947 08 Sep 15 nicklas 993     Dialogs.openPopup(url, 'InheritAnnotations', 750, 500);
6947 08 Sep 15 nicklas 994   }
6947 08 Sep 15 nicklas 995   
6947 08 Sep 15 nicklas 996   annotate.setParents = function(newParents)
6947 08 Sep 15 nicklas 997   {
6947 08 Sep 15 nicklas 998     parents = newParents;
6947 08 Sep 15 nicklas 999   }
6947 08 Sep 15 nicklas 1000   
6947 08 Sep 15 nicklas 1001   /**
6947 08 Sep 15 nicklas 1002     Event handler for removing an inherited annotation.
6947 08 Sep 15 nicklas 1003   */
6947 08 Sep 15 nicklas 1004   annotate.onRemoveInheritedAnnotation = function(event)
6947 08 Sep 15 nicklas 1005   {
6947 08 Sep 15 nicklas 1006     var inheritedId = event.detail.id;
6947 08 Sep 15 nicklas 1007     for (var i = 0; i < annotations.length; i++)
6947 08 Sep 15 nicklas 1008     {
6947 08 Sep 15 nicklas 1009       var entry = annotations[i];
6947 08 Sep 15 nicklas 1010       if (entry.inherited && entry.inherited.id == inheritedId)
6947 08 Sep 15 nicklas 1011       {
6947 08 Sep 15 nicklas 1012         annotate.deleteAnnotation(entry);
6947 08 Sep 15 nicklas 1013         return;
6947 08 Sep 15 nicklas 1014       }
6947 08 Sep 15 nicklas 1015     }
6947 08 Sep 15 nicklas 1016   }
6947 08 Sep 15 nicklas 1017   
6947 08 Sep 15 nicklas 1018   /**
6947 08 Sep 15 nicklas 1019     Event handler for adding an inherited annotation. Note
6947 08 Sep 15 nicklas 1020     that the annotation may be an annotation that is already
6947 08 Sep 15 nicklas 1021     inherited but has been marked for DELETE. In this case the
6947 08 Sep 15 nicklas 1022     DELETE should be cancelled.
6947 08 Sep 15 nicklas 1023   */
6947 08 Sep 15 nicklas 1024   annotate.onAddInheritedAnnotation = function(event)
6947 08 Sep 15 nicklas 1025   {
6947 08 Sep 15 nicklas 1026     Doc.show('inherited-list');
6947 08 Sep 15 nicklas 1027     var inheritedId = event.detail.id;
6981 08 Oct 15 nicklas 1028     var clone = event.detail.clone;
6947 08 Sep 15 nicklas 1029     
6947 08 Sep 15 nicklas 1030     // Check if we have info about this annotation already
6947 08 Sep 15 nicklas 1031     for (var i = 0; i < annotations.length; i++)
6947 08 Sep 15 nicklas 1032     {
6947 08 Sep 15 nicklas 1033       var entry = annotations[i];
6947 08 Sep 15 nicklas 1034       if (entry.inherited && entry.inherited.id == inheritedId)
6947 08 Sep 15 nicklas 1035       {
6947 08 Sep 15 nicklas 1036         entry.modified = INHERITED;
6981 08 Oct 15 nicklas 1037         if (clone && entry.source != 'CLONED')
6981 08 Oct 15 nicklas 1038         {
6981 08 Oct 15 nicklas 1039           annotate.convertToCloned(entry);
6981 08 Oct 15 nicklas 1040         }
6981 08 Oct 15 nicklas 1041         else if (!clone && entry.source != 'INHERITED')
6981 08 Oct 15 nicklas 1042         {
6981 08 Oct 15 nicklas 1043           annotate.convertToInherited(entry);
6981 08 Oct 15 nicklas 1044         }
6947 08 Sep 15 nicklas 1045         Doc.show(entry.id);
6947 08 Sep 15 nicklas 1046         return;
6947 08 Sep 15 nicklas 1047       }
6947 08 Sep 15 nicklas 1048     }
6947 08 Sep 15 nicklas 1049     
6947 08 Sep 15 nicklas 1050     // Load info about this annotation
6947 08 Sep 15 nicklas 1051     var url = 'ajax.jsp?ID='+App.getSessionId();
6947 08 Sep 15 nicklas 1052     url += '&cmd=GetAnnotationInfoForInherit';
6947 08 Sep 15 nicklas 1053     url += '&item_id='+inheritedId;
6947 08 Sep 15 nicklas 1054     
6947 08 Sep 15 nicklas 1055     var request = Ajax.getXmlHttpRequest();
6947 08 Sep 15 nicklas 1056     request.open("GET", url, true);
6947 08 Sep 15 nicklas 1057     request.send(null);
6981 08 Oct 15 nicklas 1058     var callback = clone ? annotate.inheritInfoLoadedAndClone : annotate.inheritInfoLoaded;
6981 08 Oct 15 nicklas 1059     Ajax.setReadyStateHandler(request, callback, callback);
6947 08 Sep 15 nicklas 1060   }
6947 08 Sep 15 nicklas 1061   
6947 08 Sep 15 nicklas 1062   /**
6981 08 Oct 15 nicklas 1063     Callback that converts the inherited annotation to a cloned
6981 08 Oct 15 nicklas 1064     annotation.
6981 08 Oct 15 nicklas 1065   */
6981 08 Oct 15 nicklas 1066   annotate.inheritInfoLoadedAndClone = function(request)
6981 08 Oct 15 nicklas 1067   {
6981 08 Oct 15 nicklas 1068     var entry = annotate.inheritInfoLoaded(request);
6981 08 Oct 15 nicklas 1069     annotate.convertToCloned(entry);
6981 08 Oct 15 nicklas 1070   }
6981 08 Oct 15 nicklas 1071   
6981 08 Oct 15 nicklas 1072   /**
6947 08 Sep 15 nicklas 1073     Callback after we have got information about an annotation
6947 08 Sep 15 nicklas 1074     that we should inherit.
6947 08 Sep 15 nicklas 1075   */
6947 08 Sep 15 nicklas 1076   annotate.inheritInfoLoaded = function(request)
6947 08 Sep 15 nicklas 1077   {
6947 08 Sep 15 nicklas 1078     var response = JSON.parse(request.responseText);
6947 08 Sep 15 nicklas 1079     if (response.status != 'ok')
6947 08 Sep 15 nicklas 1080     {
6947 08 Sep 15 nicklas 1081       App.debug(request.responseText);
6947 08 Sep 15 nicklas 1082       return;
6947 08 Sep 15 nicklas 1083     }
6947 08 Sep 15 nicklas 1084     
6947 08 Sep 15 nicklas 1085     var entry = response.info;
6947 08 Sep 15 nicklas 1086     entry.modified = INHERITED;
6947 08 Sep 15 nicklas 1087     
6947 08 Sep 15 nicklas 1088     annotations[annotations.length] = entry;
6947 08 Sep 15 nicklas 1089     annotate.createAnnotationEntryInList(entry, true);
6981 08 Oct 15 nicklas 1090     return entry;
6947 08 Sep 15 nicklas 1091   }
6947 08 Sep 15 nicklas 1092   
6938 19 Aug 15 nicklas 1093   annotate.addMultiValue = function(event)
6938 19 Aug 15 nicklas 1094   {
6938 19 Aug 15 nicklas 1095     if (!selectedAnnotation) return;
6938 19 Aug 15 nicklas 1096     
6955 28 Sep 15 nicklas 1097     var at = selectedAnnotation.annotationType;
6955 28 Sep 15 nicklas 1098
6938 19 Aug 15 nicklas 1099     var frm = document.forms['annotations'];
6955 28 Sep 15 nicklas 1100     var valueElement = frm[at.valueType+'-input'];
6955 28 Sep 15 nicklas 1101     
6938 19 Aug 15 nicklas 1102     var multiValues = frm['multi-values'];
6938 19 Aug 15 nicklas 1103     var errorMessage = null;
6938 19 Aug 15 nicklas 1104     try
6938 19 Aug 15 nicklas 1105     {
6955 28 Sep 15 nicklas 1106       // If one item is already selected, we create a new entry
6955 28 Sep 15 nicklas 1107       if (selectedMultiIndex >= 0)
6938 19 Aug 15 nicklas 1108       {
6938 19 Aug 15 nicklas 1109         // Add a new option
6938 19 Aug 15 nicklas 1110         errorMessage = annotate.setIndexedValue(selectedAnnotation, multiValues.length, '');
6938 19 Aug 15 nicklas 1111         if (!errorMessage)
6938 19 Aug 15 nicklas 1112         {
6955 28 Sep 15 nicklas 1113           var opt = new Option('<new>', '', false, true);
6955 28 Sep 15 nicklas 1114           opt.isNewValue = true;
6955 28 Sep 15 nicklas 1115           multiValues[multiValues.length] = opt;
6955 28 Sep 15 nicklas 1116           selectedMultiIndex = multiValues.length-1;
6938 19 Aug 15 nicklas 1117           valueElement.value = '';
6938 19 Aug 15 nicklas 1118         }
6938 19 Aug 15 nicklas 1119       }
6938 19 Aug 15 nicklas 1120       else if (valueElement.value != '')
6938 19 Aug 15 nicklas 1121       {
6938 19 Aug 15 nicklas 1122         // Add the current value
6938 19 Aug 15 nicklas 1123         errorMessage = annotate.setIndexedValue(selectedAnnotation, multiValues.length, valueElement.value);
6938 19 Aug 15 nicklas 1124         if (!errorMessage)
6938 19 Aug 15 nicklas 1125         {
6938 19 Aug 15 nicklas 1126           multiValues[multiValues.length] = new Option(valueElement.value, '', false, false);
6938 19 Aug 15 nicklas 1127           valueElement.value = '';
6938 19 Aug 15 nicklas 1128         }
6938 19 Aug 15 nicklas 1129       }
6938 19 Aug 15 nicklas 1130       valueElement.focus();
6938 19 Aug 15 nicklas 1131     }
6938 19 Aug 15 nicklas 1132     catch (errorMessage)
6938 19 Aug 15 nicklas 1133     {
6938 19 Aug 15 nicklas 1134       Forms.showNotification('btnMultiAdd', errorMessage, null, 'pointer-left');
6938 19 Aug 15 nicklas 1135     }
6938 19 Aug 15 nicklas 1136   }
6938 19 Aug 15 nicklas 1137   
6938 19 Aug 15 nicklas 1138   annotate.removeMultiValue = function()
6938 19 Aug 15 nicklas 1139   {
6955 28 Sep 15 nicklas 1140     if (!selectedAnnotation) return;
6955 28 Sep 15 nicklas 1141
6938 19 Aug 15 nicklas 1142     var frm = document.forms['annotations'];
6955 28 Sep 15 nicklas 1143     var selectedIndex = frm['multi-values'].selectedIndex;
6938 19 Aug 15 nicklas 1144     
6955 28 Sep 15 nicklas 1145     if (selectedIndex >= 0)
6955 28 Sep 15 nicklas 1146     {
6955 28 Sep 15 nicklas 1147       // Clear the current value, and send a 'change' event to let the 
6955 28 Sep 15 nicklas 1148       // regular event handlers take care of the removal
6955 28 Sep 15 nicklas 1149       var at = selectedAnnotation.annotationType;
6955 28 Sep 15 nicklas 1150       var valueElement = frm[at.valueType+'-input'];
6955 28 Sep 15 nicklas 1151       valueElement.value = '';
6955 28 Sep 15 nicklas 1152       Events.sendChangeEvent(valueElement);
6955 28 Sep 15 nicklas 1153     }
6938 19 Aug 15 nicklas 1154   }
6955 28 Sep 15 nicklas 1155     
6938 19 Aug 15 nicklas 1156   /**
6938 19 Aug 15 nicklas 1157     Event handler for the 'multi-values' selection list. This should change
6938 19 Aug 15 nicklas 1158     the value that is currently being edited to the selected option.
6938 19 Aug 15 nicklas 1159   */
6955 28 Sep 15 nicklas 1160   annotate.multiValueOnClick = function(event)
6938 19 Aug 15 nicklas 1161   {
6938 19 Aug 15 nicklas 1162     if (!selectedAnnotation) return;
6955 28 Sep 15 nicklas 1163     
6955 28 Sep 15 nicklas 1164     var at = selectedAnnotation.annotationType;
6955 28 Sep 15 nicklas 1165     var ann = selectedAnnotation.annotation;
6955 28 Sep 15 nicklas 1166     
6938 19 Aug 15 nicklas 1167     var frm = document.forms['annotations'];
6955 28 Sep 15 nicklas 1168     selectedMultiIndex = event.currentTarget.selectedIndex;
6955 28 Sep 15 nicklas 1169     if (selectedMultiIndex >= 0)
6938 19 Aug 15 nicklas 1170     {
6955 28 Sep 15 nicklas 1171       var valueElement = frm[at.valueType+'-input'];
6955 28 Sep 15 nicklas 1172       valueElement.value = ann.values[selectedMultiIndex];
6955 28 Sep 15 nicklas 1173       valueElement.focus();
6938 19 Aug 15 nicklas 1174     }
6938 19 Aug 15 nicklas 1175   }
6938 19 Aug 15 nicklas 1176   
6945 04 Sep 15 nicklas 1177   
6945 04 Sep 15 nicklas 1178   annotate.getIcon = function(entry)
6938 19 Aug 15 nicklas 1179   {
6938 19 Aug 15 nicklas 1180     var icon;
6938 19 Aug 15 nicklas 1181     var ann = entry.annotation;
6938 19 Aug 15 nicklas 1182     
6945 04 Sep 15 nicklas 1183     if (entry.source == 'PRIMARY')
6938 19 Aug 15 nicklas 1184     {
6945 04 Sep 15 nicklas 1185       // 'x' for has values, empty otherwise
6945 04 Sep 15 nicklas 1186       icon = (ann && ann.values.length > 0) ? 'notrequired_values.png' : 'notrequired_novalues.png';
6938 19 Aug 15 nicklas 1187     }
6945 04 Sep 15 nicklas 1188     else if (entry.source == 'INHERITED')
6945 04 Sep 15 nicklas 1189     {
6945 04 Sep 15 nicklas 1190       // Always the same 'x' with an anchor
6945 04 Sep 15 nicklas 1191       icon = 'inherited.png'
6945 04 Sep 15 nicklas 1192     }
6938 19 Aug 15 nicklas 1193     else
6938 19 Aug 15 nicklas 1194     {
6945 04 Sep 15 nicklas 1195       // Cloned annotations
6945 04 Sep 15 nicklas 1196       if (!entry.inherited)
6945 04 Sep 15 nicklas 1197       {
6945 04 Sep 15 nicklas 1198         // No parent item
6945 04 Sep 15 nicklas 1199         icon = 'cloned-noparent.png';
6945 04 Sep 15 nicklas 1200       }
6945 04 Sep 15 nicklas 1201       else if (entry.inherited.lastUpdate > ann.lastUpdate)
6945 04 Sep 15 nicklas 1202       {
6945 04 Sep 15 nicklas 1203         // The parent annotation has been updated
6945 04 Sep 15 nicklas 1204         icon = 'cloned-outofsync.png';
6945 04 Sep 15 nicklas 1205       }
6945 04 Sep 15 nicklas 1206       else
6945 04 Sep 15 nicklas 1207       {
6945 04 Sep 15 nicklas 1208         icon = 'cloned.png';
6945 04 Sep 15 nicklas 1209       }
6938 19 Aug 15 nicklas 1210     }
6945 04 Sep 15 nicklas 1211     return icon;
6945 04 Sep 15 nicklas 1212   }
6945 04 Sep 15 nicklas 1213   
6945 04 Sep 15 nicklas 1214   /**
6945 04 Sep 15 nicklas 1215     Update the icon for the annotation. The icon is different depending on if
6945 04 Sep 15 nicklas 1216     there are values or not for the annotation.
6945 04 Sep 15 nicklas 1217   */
6945 04 Sep 15 nicklas 1218   annotate.updateIcon = function(entry)
6945 04 Sep 15 nicklas 1219   {
6945 04 Sep 15 nicklas 1220     var icon = annotate.getIcon(entry);
6938 19 Aug 15 nicklas 1221     var img = Doc.element('icon.'+entry.id);
6938 19 Aug 15 nicklas 1222     img.src = App.getRoot()+'images/'+icon;
6938 19 Aug 15 nicklas 1223   }
6938 19 Aug 15 nicklas 1224   
6938 19 Aug 15 nicklas 1225   /**
6938 19 Aug 15 nicklas 1226     Open the calendar dialog for the selected annotation.
6938 19 Aug 15 nicklas 1227   */ 
6938 19 Aug 15 nicklas 1228   annotate.openCalendar = function(event)
6938 19 Aug 15 nicklas 1229   {
6938 19 Aug 15 nicklas 1230     var at = selectedAnnotation.annotationType;
6938 19 Aug 15 nicklas 1231     var title = at.name;
6938 19 Aug 15 nicklas 1232     var useTime = at.valueType == 'TIMESTAMP';
6938 19 Aug 15 nicklas 1233     var format = Data.get('page-data', useTime ? 'datetime-format' : 'date-format');
6938 19 Aug 15 nicklas 1234     Dialogs.openCalendar(at.valueType+'-input', title, format, useTime);
6938 19 Aug 15 nicklas 1235   }
6938 19 Aug 15 nicklas 1236   
6938 19 Aug 15 nicklas 1237   /**
6938 19 Aug 15 nicklas 1238     Open the text zoom dialog for the selected annotation.
6938 19 Aug 15 nicklas 1239   */ 
6938 19 Aug 15 nicklas 1240   annotate.openTextZoom = function(event)
6938 19 Aug 15 nicklas 1241   {
6938 19 Aug 15 nicklas 1242     var at = selectedAnnotation.annotationType;
6938 19 Aug 15 nicklas 1243     var title = at.name;
6938 19 Aug 15 nicklas 1244     Dialogs.openZoom(at.valueType+'-input', title);
6938 19 Aug 15 nicklas 1245   }
6938 19 Aug 15 nicklas 1246
6938 19 Aug 15 nicklas 1247   /**
6938 19 Aug 15 nicklas 1248     Copy all modified annotation values to the given form as hidden fields.
6938 19 Aug 15 nicklas 1249   */
6938 19 Aug 15 nicklas 1250   annotate.saveModifiedAnnotationToForm = function(frm)
6938 19 Aug 15 nicklas 1251   {
6938 19 Aug 15 nicklas 1252     var modified = [];
6938 19 Aug 15 nicklas 1253     for (var entryNo = 0; entryNo < annotations.length; entryNo++)
6938 19 Aug 15 nicklas 1254     {
6938 19 Aug 15 nicklas 1255       var entry = annotations[entryNo];
7206 19 Oct 16 nicklas 1256       if (entry.annotatePermission && entry.modified)
6938 19 Aug 15 nicklas 1257       {
6938 19 Aug 15 nicklas 1258         var tmp = {};
6938 19 Aug 15 nicklas 1259         modified[modified.length] = tmp;
6943 01 Sep 15 nicklas 1260         tmp.source = entry.source;
6943 01 Sep 15 nicklas 1261         tmp.modified = entry.modified;
6938 19 Aug 15 nicklas 1262         tmp.annotationTypeId = entry.annotationType.id;
6947 08 Sep 15 nicklas 1263         if (entry.annotation)
6947 08 Sep 15 nicklas 1264         {
6947 08 Sep 15 nicklas 1265           tmp.values = entry.annotation.values;
6947 08 Sep 15 nicklas 1266           tmp.annotationId = entry.annotation.id;
6947 08 Sep 15 nicklas 1267           tmp.unitId = entry.annotation.unit;
6955 28 Sep 15 nicklas 1268           if (tmp.modified == MODIFIED && tmp.values.length == 0)
6955 28 Sep 15 nicklas 1269           {
6955 28 Sep 15 nicklas 1270             tmp.modified = DELETE;
6955 28 Sep 15 nicklas 1271           }
6947 08 Sep 15 nicklas 1272         }
6947 08 Sep 15 nicklas 1273         if (entry.inherited)
6947 08 Sep 15 nicklas 1274         {
6947 08 Sep 15 nicklas 1275           tmp.inheritedId = entry.inherited.id;
6947 08 Sep 15 nicklas 1276         }
6938 19 Aug 15 nicklas 1277       }
6938 19 Aug 15 nicklas 1278     }
6938 19 Aug 15 nicklas 1279     
6955 28 Sep 15 nicklas 1280     //alert(JSON.stringify(modified));
6943 01 Sep 15 nicklas 1281     
6938 19 Aug 15 nicklas 1282     if (frm.modifiedAnnotations)
6938 19 Aug 15 nicklas 1283     {
6938 19 Aug 15 nicklas 1284       frm.modifiedAnnotations.value = JSON.stringify(modified);
6938 19 Aug 15 nicklas 1285     }
6938 19 Aug 15 nicklas 1286     else
6938 19 Aug 15 nicklas 1287     {
6938 19 Aug 15 nicklas 1288       Forms.addHidden(frm, 'modifiedAnnotations', JSON.stringify(modified));
6938 19 Aug 15 nicklas 1289     }
6938 19 Aug 15 nicklas 1290     
6938 19 Aug 15 nicklas 1291   }
6938 19 Aug 15 nicklas 1292   
6938 19 Aug 15 nicklas 1293   /**
6938 19 Aug 15 nicklas 1294     Save the annotations in standalone mode.
6938 19 Aug 15 nicklas 1295   */
6938 19 Aug 15 nicklas 1296   annotate.save = function()
6938 19 Aug 15 nicklas 1297   {
6938 19 Aug 15 nicklas 1298     var frm = document.forms['modified'];
6938 19 Aug 15 nicklas 1299     annotate.saveModifiedAnnotationToForm(frm);
6938 19 Aug 15 nicklas 1300     frm.submit();
6938 19 Aug 15 nicklas 1301   }
6938 19 Aug 15 nicklas 1302   
6938 19 Aug 15 nicklas 1303   return annotate;
6938 19 Aug 15 nicklas 1304 }();
6938 19 Aug 15 nicklas 1305
6938 19 Aug 15 nicklas 1306 Doc.onLoad(Annotate.initPage);
6938 19 Aug 15 nicklas 1307
6938 19 Aug 15 nicklas 1308