Changeset 6938


Ignore:
Timestamp:
Aug 19, 2015, 9:17:33 AM (6 years ago)
Author:
Nicklas Nordborg
Message:

References #1941: Store experimental factor values as part experiments

Started with redesigning the annotations edit dialog. The idea is to include both primary and inherited/cloned annotations in the "Annotations" tab and manage all types of annotations there. The "Inherited annotations" tab will be removed.

So far, the new implementation will list all types of annotations. PRIMARY and CLONED annotations are editable, INHERITED annotations only display some information. Support for multi-valued annotations is not implemeted.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/clients/web/net/sf/basedb/clients/web/Base.java

    r6930 r6938  
    9292import javax.servlet.ServletRequest;
    9393import javax.servlet.http.Cookie;
     94
     95import org.json.simple.JSONArray;
     96import org.json.simple.JSONObject;
     97import org.json.simple.parser.JSONParser;
     98import org.json.simple.parser.ParseException;
    9499
    95100
     
    14121417    if (modified != null)
    14131418    {
    1414       String[] modifiedAnnotations = modified.split(",");
    1415       AnnotationSet oldAs = oldItem != null && oldItem.isAnnotated() ?
    1416         oldItem.getAnnotationSet() : null;
     1419      JSONArray jsonModified = null;
     1420      try
     1421      {
     1422        jsonModified = (JSONArray)new JSONParser().parse(modified);
     1423      }
     1424      catch (ParseException ex)
     1425      {
     1426        throw new BaseException(ex);
     1427      }
     1428     
     1429      //String[] modifiedAnnotations = modified.split(",");
     1430      //AnnotationSet oldAs = oldItem != null && oldItem.isAnnotated() ?
     1431      //  oldItem.getAnnotationSet() : null;
    14171432      AnnotationSet newAs = newItem.getAnnotationSet();
    1418       if (oldItem == newItem)
     1433      /*if (oldItem == newItem)
    14191434      {
    14201435        // The items were not loaded in separate sessions, the protocol has to be
     
    14231438        if (p != null) dc.reattachItem(p, false);
    14241439      }
     1440      */
     1441     
     1442      for (int entryNo = 0; entryNo < jsonModified.size(); entryNo++)
     1443      {
     1444        JSONObject jsonA = (JSONObject)jsonModified.get(entryNo);
     1445        Number annotationId = (Number)jsonA.get("annotationId");
     1446        Number annotationTypeId = (Number)jsonA.get("annotationTypeId");
     1447        JSONArray jsonValues = (JSONArray)jsonA.get("values");
     1448       
     1449        AnnotationType at = AnnotationType.getById(dc, annotationTypeId.intValue());
     1450        Annotation a = null;
     1451        if (annotationId != null)
     1452        {
     1453          a = Annotation.getById(dc, annotationId.intValue());
     1454        }
     1455        else if (jsonValues != null && jsonValues.size() > 0)
     1456        {
     1457          a = newAs.getAnnotation(at);
     1458        }
     1459       
     1460        if (a == null) continue;
     1461       
     1462        Type valueType = at.getValueType();
     1463        Number unitId = (Number)jsonA.get("unitId");
     1464        Unit unit = unitId == null ? null : Unit.getById(dc, unitId.intValue());
     1465        if (jsonValues == null || jsonValues.size() == 0)
     1466        {
     1467          newAs.removeAnnotation(at);
     1468        }
     1469        else
     1470        {
     1471          Object[] oValues = new Object[jsonValues.size()];
     1472          Formatter<?> formatter = FormatterFactory.getTypeFormatter(dc.getSessionControl(), valueType);
     1473          for (int j = 0; j < oValues.length; ++j)
     1474          {
     1475            oValues[j] = formatter.parseString((String)jsonValues.get(j));
     1476          }
     1477          a.setValues(Arrays.asList(oValues), unit);
     1478        }
     1479       
     1480       
     1481      }
     1482     
     1483      /*
    14251484      for (int i = 0; i < modifiedAnnotations.length; ++i)
    14261485      {
     
    14591518        }
    14601519      }
     1520      */
    14611521    }
    14621522   
  • trunk/www/common/annotations/annotate.js

    r6610 r6938  
    3131  var selectedIndex;
    3232 
    33   /**
    34     Initialize all input fields were we want to detect changes to values. Most fields react to
    35     the 'change' event, but radio-buttons and check-boxes react to the 'click' event.
    36   */
    37   annotate.initSingleValues = function(element, autoInit)
    38   {
    39     if (autoInit == 'detect-change')
    40     {
    41       var eventType = element.type == 'radio' || element.type == 'checkbox' ? 'click' : 'change';
    42       Events.addEventHandler(element, eventType, annotate.valueOnChange);
    43     }
    44   }
    45   Doc.addElementInitializer(annotate.initSingleValues);
    46  
     33
    4734  annotate.initPage = function()
    4835  {
     
    5138    Buttons.addClickHandler('btnSave', annotate.save);
    5239   
     40    // Parse the current annotation information which contain value type, current values, etc.
     41    annotations = Data.json('page-data', 'annotations');
     42    // Loop through all annotations and build the selection list
     43    var firstInherited = false;
     44    for (var i = 0; i < annotations.length; i++)
     45    {
     46      var ann = annotations[i];
     47      if (!firstInherited && ann.source != 'PRIMARY')
     48      {
     49        annotate.createAnnotationEntryInList(annotations[i], true);
     50        firstInherited = true;
     51      }
     52      else
     53      {
     54        annotate.createAnnotationEntryInList(annotations[i], false);
     55      }
     56    }
     57
     58    // Event handlers for input fields
     59    Events.addEventHandler('STRING-input', 'change', annotate.valueOnChange);
     60    Events.addEventHandler('TEXT-input', 'change', annotate.valueOnChange);
     61    Buttons.addClickHandler('TEXT-zoom', annotate.openTextZoom);
     62    Events.addEventHandler('INT-input', 'keypress', Events.integerOnly);
     63    Events.addEventHandler('INT-input', 'change', annotate.valueOnChange);
     64    Events.addEventHandler('LONG-input', 'keypress', Events.integerOnly);
     65    Events.addEventHandler('LONG-input', 'change', annotate.valueOnChange);
     66    Events.addEventHandler('FLOAT-input', 'keypress', Events.numberOnly);
     67    Events.addEventHandler('FLOAT-input', 'change', annotate.valueOnChange);
     68    Events.addEventHandler('DOUBLE-input', 'keypress', Events.numberOnly);
     69    Events.addEventHandler('DOUBLE-input', 'change', annotate.valueOnChange);
     70    Events.addEventHandler('DATE-input', 'change', annotate.valueOnChange);
     71    Buttons.addClickHandler('DATE-calendar', annotate.openCalendar);
     72    Events.addEventHandler('TIMESTAMP-input', 'change', annotate.valueOnChange);
     73    Buttons.addClickHandler('TIMESTAMP-calendar', annotate.openCalendar);
     74    Events.addEventHandler('BOOLEAN-input-NULL', 'click', annotate.valueOnChange);
     75    Events.addEventHandler('BOOLEAN-input-TRUE', 'click', annotate.valueOnChange);
     76    Events.addEventHandler('BOOLEAN-input-FALSE', 'click', annotate.valueOnChange);
     77    Events.addEventHandler('ENUM-SINGLE-input', 'change', annotate.valueOnChange);
     78    Events.addEventHandler('ENUM-MULTIPLE-input', 'change', annotate.valueOnChange);
     79
     80    /*
    5381    // Buttons for multi-valued annotations
    5482    Buttons.addClickHandler('btnMultiAdd', annotate.addMultiValue);
     
    5684    Events.addEventHandler('multi-values', 'click', annotate.multiValueOnClick);
    5785   
    58     // Parse the current annotation information which contain value type, current values, etc.
    59     annotations = Data.json('page-data', 'annotations');
    6086   
    6187    // The category list box is used to filter visible annotations
     88    */
    6289    Events.addEventHandler('categories', 'change', annotate.categoryOnChange);
    6390    annotate.categoryOnChange();
    6491   
    65     // Loop through all annotation...
    66     for (var i = 0; i < annotations.length; i++)
    67     {
    68       var annotation = annotations[i];
    69       annotations['ID'+annotation.id] = annotation;
    70       // set the icon
    71       annotate.updateIcon(annotation);
    72       // add event handler for selecting the annotation
    73       Events.addEventHandler('prompt.'+annotation.id, 'click', annotate.annotationOnClick);
    74      
    75       // Attach event handler that are specific to certain value types
    76       var valueType = annotation.valueType;
    77       var fieldName = 'value.'+annotation.id;
    78       if (!annotation.enumeration)
    79       {
    80         if (valueType == 'INT' || valueType == 'LONG')
    81         {
    82           // Block non-numeric keys from INT and LONG fields
    83           Events.addEventHandler(fieldName, 'keypress', Events.integerOnly);
    84         }
    85         else if (valueType == 'FLOAT' || valueType == 'DOUBLE')
    86         {
    87           // Block non-numeric keys from FLOAT and DOUBLE fields
    88           Events.addEventHandler(fieldName, 'keypress', Events.numberOnly);
    89         }
    90         else if (valueType == 'DATE' || valueType == 'TIMESTAMP')
    91         {
    92           // Add click handler to open calendar dialog for date/timestamp fields
    93           Buttons.addClickHandler('btn.'+annotation.id, annotate.openCalendar);
    94         }
    95         if (annotation.unit)
    96         {
    97           Events.addEventHandler('unit.'+annotation.id, 'change', annotate.unitOnChange);
    98         }
    99       }
    100     }
     92    // Unit selection
     93    Events.addEventHandler('unit', 'change', annotate.unitOnChange);
    10194   
    10295    // Select the initial annotation
    10396    var annotationTypeId = Data.int('page-data', 'annotation-type-id');
    104     if (annotationTypeId) annotate.selectAnnotation(annotationTypeId)
    105   }
    106  
     97    var annotationId = Data.int('page-data', 'annotation-id');
     98    if (annotationId)
     99    {
     100      annotate.selectAnnotation(annotationTypeId+'-'+annotationId);
     101    }
     102    else if (annotationTypeId)
     103    {
     104      annotate.selectAnnotation(annotationTypeId)
     105    }
     106    else
     107    {
     108      annotate.selectAnnotation(null);
     109    }
     110  }
     111 
     112  /**
     113    Create an entry for the given annotation/annotation type
     114    in the list.
     115  */
     116  annotate.createAnnotationEntryInList = function(entry, firstInherited)
     117  {
     118    var ann = entry.annotation;
     119    var at = entry.annotationType;
     120   
     121    if (firstInherited)
     122    {
     123      var fi = document.createElement('div');
     124      fi.className = 'first-inherited';
     125      Doc.element('annotation-list').appendChild(fi);
     126    }
     127   
     128    var div = document.createElement('div');
     129    div.className = 'param interactable';
     130    div.id = entry.id;
     131    div.title = Strings.encodeTags(at.name);
     132   
     133    var html = '';
     134    var icon = ann.values.length > 0 ? 'notrequired_values.png' : 'notrequired_novalues.png';
     135    html += '<span class="icon">';
     136    html += '<img id="icon.'+entry.id+'" src="../../images/'+icon+'">';
     137    html += '</span>';
     138    // DEBUG!!
     139    //html += entry.source;
     140   
     141    html += '<span class="label">';
     142    if (at.removed) html += '<img src="../../images/deleted.png">';
     143    if (at.protocolParameter) html += '<img src="../../images/parameter.png">';
     144    html += Strings.encodeTags(at.name)+'</span>';
     145    html += '</div>';
     146    div.innerHTML = html;
     147   
     148    Events.addEventHandler(div, 'click', annotate.annotationOnClick);
     149    Doc.element('annotation-list').appendChild(div);
     150  }
    107151 
    108152  /**
     
    115159    var frm = document.forms['annotations'];
    116160    var categoryId = parseInt(frm.categories.value);
    117     for (var i = 0; i < annotations.length; i++)
    118     {
    119       var annotation = annotations[i];
     161   
     162    for (var entryNo = 0; entryNo < annotations.length; entryNo++)
     163    {
     164      var entry = annotations[entryNo];
     165      var at = entry.annotationType;
     166
    120167      var show = false;
    121168      if (categoryId == -1)
     
    124171        show = true;
    125172      }
    126       else if (categoryId == -2 && annotation.parameter)
     173      else if (categoryId == -2 && at.protocolParameter)
    127174      {
    128175        // show protocol parameters
    129176        show = true;
    130177      }
    131       else if (categoryId == 0 && annotation.categories.length == 0 && !annotation.parameter)
     178      else if (categoryId == 0 && at.categories.length == 0 && !at.protocolParameter)
    132179      {
    133180        // show uncategorized
     
    137184      {
    138185        // show the selected category
    139         for (var j = 0; j < annotation.categories.length; j++)
    140         {
    141           if (annotation.categories[j] == categoryId) show = true;
    142         }
    143       }
    144       Doc.showHide('prompt.'+annotation.id, show);
    145     }
    146   }
    147  
    148   /**
    149     Select the given annotation. This will mark the annotation in the main list
    150     and display the input fields associated with it.
    151   */
    152   annotate.selectAnnotation = function(annotationTypeId)
     186        for (var categoryNo = 0; categoryNo < at.categories.length; categoryNo++)
     187        {
     188          if (at.categories[categoryNo] == categoryId)
     189          {
     190            show = true;
     191            break;
     192          }
     193        }
     194      }
     195     
     196      Doc.showHide(entry.id, show);
     197    }
     198  }
     199 
     200  /**
     201    Get the annotation entry for the given id.
     202    Returns null if not found.
     203  */
     204  annotate.getEntryById = function(entryId)
     205  {
     206    for (var i = 0; i < annotations.length; i++)
     207    {
     208      if (annotations[i].id == entryId)
     209      {
     210        return annotations[i];
     211      }
     212    }
     213    return null;
     214  }
     215 
     216 
     217  /**
     218    Select the given annotation entry. This will mark the annotation
     219    in the main list, display the input fields associated with it
     220    and populate the input fields with the current value(s).
     221  */
     222  annotate.selectAnnotation = function(entryId)
    153223  {
    154224    if (selectedAnnotation)
    155225    {
    156       // Hide current div
    157       Doc.hide('section.'+selectedAnnotation.id);
    158       Doc.removeClass('prompt.'+selectedAnnotation.id, 'selected');
    159     }
    160     selectedAnnotation = annotations['ID'+annotationTypeId];
    161     selectedIndex = -1;
    162     Doc.show('section.'+annotationTypeId);
    163     Doc.addClass('prompt.'+annotationTypeId, 'selected');
     226      Doc.removeClass(selectedAnnotation.id, 'selected');
     227    }
    164228
    165229    var frm = document.forms['annotations'];
    166     var valueElement = frm['value.'+annotationTypeId];
    167     if (valueElement.focus) valueElement.focus();
    168 
    169     if (selectedAnnotation.enumeration)
    170     {
    171       Doc.hide('valuecontainer');
     230    // Mark the selected annotation and make sure the
     231    // category list doesn't hide it
     232    selectedAnnotation = annotate.getEntryById(entryId);
     233
     234    var classes = [];
     235    var valueElement;
     236   
     237    if (selectedAnnotation == null)
     238    {
     239      classes.push('none-selected');
     240      if (annotations.length == 0)
     241      {
     242        classes.push('no-annotations');
     243      }
     244    }
     245    else
     246    {
     247     
     248      Doc.addClass(entryId, 'selected');
     249      if (Doc.element(entryId).style.display=='none')
     250      {
     251        // Make sure the entry is not hidden because a different
     252        // category is selected
     253        frm.categories.selectedIndex = 0;
     254        annotate.categoryOnChange();
     255      }
     256     
     257      var at = selectedAnnotation.annotationType;
     258      var ann = selectedAnnotation.annotation;
     259     
     260      annotate.showNameAndOtherInfo(at);
     261      classes.push('selected');
     262      classes.push(selectedAnnotation.source);
     263      if (at.description) classes.push('has-description');
     264     
     265      if (selectedAnnotation.source != 'PRIMARY')
     266      {
     267        var inherited = selectedAnnotation.inherited;
     268        if (inherited)
     269        {
     270          var symbol = inherited.unitSymbol ? ' ' + inherited.unitSymbol : '';
     271          Doc.element('inherited-values').innerHTML = Strings.encodeTags(inherited.values.join(symbol+', ')+symbol);
     272          Doc.element('inherited-item').innerHTML = Strings.encodeTags(inherited.from.name) + ' <span class="itemsubtype">('+inherited.from.type+')</span>';
     273        }
     274        else
     275        {
     276          classes.push('inherited-missing');
     277        }
     278      }
     279     
     280      if (!at.enumeration)
     281      {
     282        // Just display the correct input section
     283        classes.push(at.valueType);
     284        valueElement = frm[at.valueType+'-input'];
     285      }
     286      else
     287      {
     288        // We need to populate the selection list or
     289        // generate radiobuttons/checkboxes
     290        var symbol = at.defaultUnit ? ' ' + at.defaultSymbol : '';
     291        if (at.displayAsList)
     292        {
     293          classes.push(at.multiplicity == 1 ? 'ENUM-SINGLE' : 'ENUM-MULTIPLE');
     294          var list = Doc.element(at.multiplicity == 1 ? 'ENUM-SINGLE-input' : 'ENUM-MULTIPLE-input');
     295          annotate.initEnumList(list, at.enumeration, at.multiplicity == 1, symbol);
     296          valueElement = list;         
     297        }
     298        else
     299        {
     300          classes.push('ENUM-RADIO-CHECKBOX');
     301          var tmp = annotate.initEnumCheckboxes(at.enumeration, at.multiplicity == 1, symbol);
     302          Doc.element('ENUM-RADIO-CHECKBOX').innerHTML = '';
     303          Doc.element('ENUM-RADIO-CHECKBOX').appendChild(tmp);
     304          valueElement = frm['check'];
     305        }
     306      }
     307   
     308      if (at.units)
     309      {
     310        classes.push('has-unit')
     311        annotate.initUnitList(at.units, ann && ann.unit || at.defaultUnit);
     312      }
     313     
     314      // Fill form with current values
     315      var values = ann.values.length > 0 ? ann.values : [''];
    172316      if (valueElement.type && valueElement.type.indexOf('select') == 0)
    173317      {
    174318        // selection list
    175         Forms.selectListOptions(valueElement, selectedAnnotation.values);
    176       }
    177       else if (selectedAnnotation.multiplicity == 1)
    178       {
    179         // radio buttons
    180         var value = selectedAnnotation.values.length > 0 ? selectedAnnotation.values[0] : '';
    181         Forms.checkRadio(valueElement, value);
     319        Forms.selectListOptions(valueElement, values);
     320      }
     321      else if (valueElement.length)
     322      {
     323        // radio buttons or checkboxes
     324        if (at.multiplicity == 1)
     325        {
     326          Forms.checkRadio(valueElement, values[0]);
     327        }
     328        else
     329        {
     330          Forms.checkCheckBoxes(valueElement, values);
     331        }
    182332      }
    183333      else
    184334      {
    185         // check boxes
    186         Forms.checkCheckBoxes(valueElement, selectedAnnotation.values);
    187       }
    188     }
    189     else if (selectedAnnotation.multiplicity == 1)
    190     {
    191       Doc.hide('valuecontainer');
    192       if (selectedAnnotation.values.length > 0)
    193       {
    194         if (valueElement.length) // ie. radio buttons for boolean parameter
    195         {
    196           Forms.checkRadio(valueElement, selectedAnnotation.values[0]);
     335        // regular input field
     336        if (at.multiplicity == 1)
     337        {
     338          valueElement.value = values[0];
    197339        }
    198340        else
    199341        {
    200           valueElement.value = selectedAnnotation.values[0];
    201         }
     342          // TODO - multivalues annotation
     343        }
     344      }
     345    }
     346    Doc.element('selected-container').className = classes.join(' ');
     347    if (valueElement && valueElement.focus) valueElement.focus();
     348   
     349      /*
     350      else if (at.multiplicity == 1)
     351      {
     352        if (ann && ann.values && ann.values.length > 0)
     353        {
     354          if (valueElement.length) // ie. radio buttons for boolean parameter
     355          {
     356            Forms.checkRadio(valueElement, ann.values[0]);
     357          }
     358          else
     359          {
     360           
     361            valueElement.value = ann.values[0];
     362          }
     363        }
     364      }
     365      */
     366      /*
     367      else
     368      {
     369        var multiValues = frm['multi-values'];
     370        multiValues.length = 0;
     371        for (var i = 0; i < selectedAnnotation.values.length; i++)
     372        {
     373          multiValues[multiValues.length] = new Option(selectedAnnotation.values[i]);
     374        }
     375        var mult = Doc.element('multiplicity');
     376        mult.innerHTML = selectedAnnotation.multiplicity == 0 ? '' : '(Max '+selectedAnnotation.multiplicity+' values)';
     377        Doc.show('valuecontainer');
     378      }
     379      */
     380
     381   
     382  }
     383 
     384  /**
     385    Display information about the annotation.
     386  */
     387  annotate.showNameAndOtherInfo = function(at)
     388  {
     389    Doc.element('selected-name').innerHTML = Strings.encodeTags(at.name);
     390    Doc.element('selected-description').innerHTML = at.description || '';
     391   
     392    var typeSummary = at.valueType;
     393    if (at.enumeration)
     394    {
     395      if (at.multiplicity == 0)
     396      {
     397        typeSummary = "Select one or more";
     398      }
     399      else if (at.multiplicity == 1)
     400      {
     401        typeSummary = "Select one";
     402      }
     403      else
     404      {
     405        typeSummary = "Select 1‒"+at.multiplicity;
    202406      }
    203407    }
    204408    else
    205409    {
    206       var multiValues = frm['multi-values'];
    207       multiValues.length = 0;
    208       for (var i = 0; i < selectedAnnotation.values.length; i++)
    209       {
    210         multiValues[multiValues.length] = new Option(selectedAnnotation.values[i]);
    211       }
    212       var mult = Doc.element('multiplicity');
    213       mult.innerHTML = selectedAnnotation.multiplicity == 0 ? '' : '(Max '+selectedAnnotation.multiplicity+' values)';
    214       Doc.show('valuecontainer');
    215     }
     410      if (at.minValue != null && at.maxValue != null)
     411      {
     412        typeSummary += ': '+at.minValue+'-'+at.maxValue;
     413      }
     414      else if (at.minValue != null)
     415      {
     416        typeSummary += ' &gt;= '+at.minValue;
     417      }
     418      else if (at.maxValue != null)
     419      {
     420        typeSummary += ' &lt;= '+at.maxValue;
     421      }
     422    }
     423    Doc.element('selected-type').innerHTML = typeSummary;
     424  }
     425 
     426  /**
     427    Initialize the units list with the given units.
     428    'selected' is the id of the unit that should be
     429    selected.
     430   */
     431  annotate.initUnitList = function(units, selected)
     432  {
     433    var unitList = Doc.element('unit');
     434    unitList.length = 0;
     435    for (var unitNo = 0; unitNo < units.length; unitNo++)
     436    {
     437      var unit = units[unitNo];
     438      var option = new Option(unit.symbol, unit.id, selected == unit.id);
     439      option.title = unit.description;
     440      unitList[unitList.length] = option;
     441    }
     442  }
     443 
     444  /**
     445    Fill the given <select> list with the given
     446    options. If 'notSpecified' is set, the first
     447    option will be 'not specified'.
     448  */
     449  annotate.initEnumList = function(list, values, notSpecified, unit)
     450  {
     451    list.length = 0;
     452    if (notSpecified)
     453    {
     454      list[0] = new Option('- not specified -', '');
     455      list[0].className = 'not-specified';
     456    }
     457    for (var valueNo = 0; valueNo < values.length; valueNo++)
     458    {
     459      var value = values[valueNo];
     460      list[list.length] = new Option(value+unit, value);
     461    }
     462  }
     463 
     464  /**
     465    Generate checkboxes or radiobuttons for an enumeration
     466    annotation.
     467  */
     468  annotate.initEnumCheckboxes = function(values, radio, unit)
     469  {
     470    var tmp = document.createDocumentFragment();
     471    var ctlType = radio ? 'radio' : 'checkbox';
     472    if (radio)
     473    {
     474      var noop = annotate.createRadioOrCheckBox(ctlType, '', '- not specified -');
     475      noop.className = 'not-specified';
     476      tmp.appendChild(noop);
     477    }
     478    for (var valueNo = 0; valueNo < values.length; valueNo++)
     479    {
     480      var value = values[valueNo];
     481      tmp.appendChild(annotate.createRadioOrCheckBox(ctlType, value, value+unit));
     482    }
     483    return tmp;
     484  }
     485
     486  /**
     487    Create a <input> element that is either a radio och checkbox.
     488  */
     489  annotate.createRadioOrCheckBox = function(type, value, text)
     490  {
     491    var ctl = document.createElement('input');
     492    ctl.type = type;
     493    ctl.name = 'check';
     494    ctl.value = value;
     495    Events.addEventHandler(ctl, 'click', annotate.valueOnChange);
     496    var lbl = document.createElement('label');
     497    lbl.appendChild(ctl);
     498    lbl.appendChild(document.createTextNode(text));
     499    lbl.appendChild(document.createElement('br'));
     500    return lbl;
    216501  }
    217502 
     
    221506  annotate.annotationOnClick = function(event)
    222507  {
    223     var annotationTypeId = Data.int(event.currentTarget, 'annotation-type-id');
    224     annotate.selectAnnotation(annotationTypeId);
     508    annotate.selectAnnotation(event.currentTarget.id);
    225509  }
    226510 
     
    247531  annotate.setMultipleValues = function(annotation, values)
    248532  {
    249     if (annotation.multiplicity > 0 && values.length > annotation.multiplicity)
    250     {
    251       throw 'Max '+annotation.multiplicity+' values allowed';
    252     }
    253     annotation.values = values;
     533    var at = annotation.annotationType;
     534    var ann = annotation.annotation;
     535   
     536    if (at.multiplicity > 0 && values.length > at.multiplicity)
     537    {
     538      throw 'Max '+at.multiplicity+' values allowed';
     539    }
     540    ann.values = values;
    254541    annotation.modified = true;
    255542    annotate.updateIcon(annotation);
     
    260547    is not accepted an exception is thrown.
    261548  */
     549  /*
    262550  annotate.setIndexedValue = function(annotation, index, value)
    263551  {
     
    285573    annotate.updateIcon(annotation);
    286574  }
     575  */
    287576 
    288577  /**
     
    291580  annotate.setUnit = function(annotation, unit)
    292581  {
    293     annotation.unit = unit;
     582    annotation.annotation.unit = unit;
    294583    annotation.modified = true;
    295584  }
     
    304593    if (!selectedAnnotation) return;
    305594   
     595    var at = selectedAnnotation.annotationType;
    306596    var frm = document.forms['annotations'];
    307597    var target = event.currentTarget;
    308598    try
    309599    {
    310       if (selectedAnnotation.multiplicity == 1)
     600      if (at.multiplicity == 1)
    311601      {
    312602        // If only a single value is accepted the event target holds the new value
    313603        annotate.setSingleValue(selectedAnnotation, target.value);
    314604      }
    315       else if (selectedAnnotation.enumeration)
     605      /*
     606      else if (at.enumeration)
    316607      {
    317608        // If the annotation is a multi-valued enumeration the input fields can be either a
     
    347638        }
    348639      }
     640      */
    349641    }
    350642    catch (errorMessage)
     
    363655  }
    364656
     657  /*
    365658  annotate.addMultiValue = function(event)
    366659  {
     
    415708    frm['value.'+selectedAnnotation.id].focus();
    416709  }
     710  */
    417711 
    418712  /**
     
    420714    the value that is currently being edited to the selected option.
    421715  */
     716  /*
    422717  annotate.multiValueOnClick = function()
    423718  {
     
    431726    }
    432727  }
     728  */
    433729 
    434730  /**
     
    436732    there are values or not for the annotation.
    437733  */
    438   annotate.updateIcon = function(annotation)
     734  annotate.updateIcon = function(entry)
    439735  {
    440736    var icon;
    441     if (annotation.values.length == 0)
    442     {
    443       icon = annotation.required ? 'required_novalues.png' : 'notrequired_novalues.png';
     737    var ann = entry.annotation;
     738   
     739    if (ann && ann.values.length > 0)
     740    {
     741      icon = ann.required ? 'required_values.png' : 'notrequired_values.png';
    444742    }
    445743    else
    446744    {
    447       icon = annotation.required ? 'required_values.png' : 'notrequired_values.png';
    448     }
    449     var img = Doc.element('icon.'+annotation.id);
     745      icon = ann.required ? 'required_novalues.png' : 'notrequired_novalues.png';
     746    }
     747    var img = Doc.element('icon.'+entry.id);
    450748    img.src = App.getRoot()+'images/'+icon;
    451749  }
     
    456754  annotate.openCalendar = function(event)
    457755  {
    458     var textarea = 'value.'+selectedAnnotation.id;
    459     var title = selectedAnnotation.name;
    460     var useTime = selectedAnnotation.valueType == 'TIMESTAMP';
     756    var at = selectedAnnotation.annotationType;
     757    var title = at.name;
     758    var useTime = at.valueType == 'TIMESTAMP';
    461759    var format = Data.get('page-data', useTime ? 'datetime-format' : 'date-format');
    462     Dialogs.openCalendar(textarea, title, format, useTime);
     760    Dialogs.openCalendar(at.valueType+'-input', title, format, useTime);
     761  }
     762 
     763  /**
     764    Open the text zoom dialog for the selected annotation.
     765  */
     766  annotate.openTextZoom = function(event)
     767  {
     768    var at = selectedAnnotation.annotationType;
     769    var title = at.name;
     770    Dialogs.openZoom(at.valueType+'-input', title);
    463771  }
    464772
     
    469777  {
    470778    var modified = [];
    471     for (var i = 0; i < annotations.length; i++)
    472     {
    473       var annotation = annotations[i];
    474       if (annotation.modified)
    475       {
    476         modified[modified.length] = annotation.id;
    477         for (var j = 0; j < annotation.values.length; j++)
    478         {
    479           Forms.addHidden(frm, annotation.id, annotation.values[j]);
    480         }
    481         if (annotation.unit) Forms.addHidden(frm, 'unit:'+annotation.id, annotation.unit);
    482       }
    483     }
     779    for (var entryNo = 0; entryNo < annotations.length; entryNo++)
     780    {
     781      var entry = annotations[entryNo];
     782      if (entry.modified && entry.source != 'INHERITED')
     783      {
     784        var tmp = {};
     785        modified[modified.length] = tmp;
     786        tmp.values = entry.annotation.values;
     787        tmp.annotationId = entry.annotation.id;
     788        tmp.annotationTypeId = entry.annotationType.id;
     789        tmp.unitId = entry.annotation.unit;
     790      }
     791    }
     792   
     793    alert(JSON.stringify(modified));
     794   
    484795    if (frm.modifiedAnnotations)
    485796    {
    486       frm.modifiedAnnotations.value = modified.join(',');
     797      frm.modifiedAnnotations.value = JSON.stringify(modified);
    487798    }
    488799    else
    489800    {
    490       Forms.addHidden(frm, 'modifiedAnnotations', modified.join(','));
    491     }
     801      Forms.addHidden(frm, 'modifiedAnnotations', JSON.stringify(modified));
     802    }
     803   
    492804  }
    493805 
  • trunk/www/common/annotations/annotate.jsp

    r6610 r6938  
    2525  @version 2.0
    2626--%>
    27 <%@page import="org.json.simple.JSONObject"%>
    28 <%@page import="org.json.simple.JSONArray"%>
    2927<%@ page pageEncoding="UTF-8" session="false"
    3028  import="net.sf.basedb.core.SessionControl"
     
    6361  import="net.sf.basedb.clients.web.formatter.FormatterSettings"
    6462  import="net.sf.basedb.util.Values"
     63  import="org.json.simple.JSONObject"
     64  import="org.json.simple.JSONArray"
    6565  import="java.util.ArrayList"
    6666  import="java.util.List"
     
    7474<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
    7575<%!
    76 private String minMax(Object min, Object max)
     76
     77
     78private JSONObject makeJSON(DbControl dc, AnnotationType at, Annotation a, boolean isProtocolParameter, Set<AnnotationTypeCategory> allCategories)
    7779{
    78   StringBuilder minMax = new StringBuilder();
    79   if (min != null && max != null)
    80   {
    81     minMax.append(": ").append(min).append("‒").append(max);
    82   }
    83   else if (min != null)
    84   {
    85     minMax.append(" >= ").append(min);
    86   }
    87   else if (max != null)
    88   {
    89     minMax.append(" <= ").append(max);
    90   }
    91   return minMax.toString();
     80  // Create the JSON objects for holding all info
     81  // The base object has 'id', 'source', 'annotationType' and 'annotation'
     82  JSONObject json = new JSONObject();
     83  json.put("id", ""+at.getId() + (a!=null ? "-" + a.getId() : ""));
     84  // If 'a' is null this is a primary annotation that has no current values
     85  json.put("source", a == null ? "PRIMARY" : a.getSource().name());
     86
     87  JSONObject jsonAt = new JSONObject();
     88  json.put("annotationType", jsonAt);
     89  JSONObject jsonA = new JSONObject();
     90  json.put("annotation", jsonA);
     91  JSONArray jsonValues = new JSONArray();
     92  jsonA.put("values", jsonValues);
     93
     94  // Load annotation type information
     95  Type valueType = at.getValueType();
     96  Formatter formatter = FormatterFactory.getTypeFormatter(dc.getSessionControl(), valueType);
     97 
     98  jsonAt.put("id", at.getId());
     99  jsonAt.put("name", at.getName());
     100  jsonAt.put("valueType", valueType.name());
     101  jsonAt.put("multiplicity", at.getMultiplicity());
     102  jsonAt.put("description", HTML.encodeTags(at.getDescription()));
     103  jsonAt.put("removed", at.isRemoved());
     104  jsonAt.put("protocolParameter", isProtocolParameter);
     105
     106  if (valueType == Type.STRING)
     107  {
     108    jsonAt.put("maxLength", at.getMaxLength());
     109  }
     110  else if (valueType == Type.INT || valueType == Type.LONG)
     111  {
     112    jsonAt.put("minValue", at.getMinValueLong());
     113    jsonAt.put("maxValue", at.getMaxValueLong());
     114  }
     115  else if (valueType == Type.FLOAT || valueType == Type.DOUBLE)
     116  {
     117    jsonAt.put("minValue", at.getMinValueDouble());
     118    jsonAt.put("maxValue", at.getMaxValueDouble());
     119  }
     120 
     121  // Enumeration
     122  if (at.isEnumeration())
     123  {
     124    List<?> values = at.getValues();
     125    JSONArray jsonEnum = new JSONArray();
     126    for (Object val : values)
     127    {
     128      jsonEnum.add(formatter.format(val));
     129    }
     130    jsonAt.put("enumeration", jsonEnum);
     131    jsonAt.put("displayAsList", at.getDisplayAsList());
     132  }
     133 
     134  // Units
     135  if (at.supportUnits())
     136  {
     137    Unit defaultUnit = at.getDefaultUnit();
     138    jsonAt.put("defaultUnit", defaultUnit.getId());
     139    jsonAt.put("defaultSymbol", defaultUnit.getDisplaySymbol());
     140   
     141    if (!at.isEnumeration())
     142    {
     143      ItemQuery<Unit> unitQuery = at.getUsableUnits();
     144      if (unitQuery.count(dc) == 0)
     145      {
     146        unitQuery = at.getQuantity().getUnits();
     147      }
     148      else
     149      {
     150        unitQuery.reset();
     151      }
     152      unitQuery.order(Orders.desc(Hql.property("referenceFactor")));
     153      unitQuery.order(Orders.asc(Hql.property("displaySymbol")));
     154      List<Unit> units = new ArrayList<Unit>(unitQuery.list(dc));
     155      if (!units.contains(defaultUnit)) units.add(defaultUnit);
     156     
     157      Unit currentUnit = a != null ? a.getUnit() : null;
     158      if (currentUnit != null && !units.contains(currentUnit)) units.add(currentUnit);
     159     
     160      JSONArray jsonUnits = new JSONArray();
     161      for (Unit unit : units)
     162      {
     163        JSONObject jsonUnit = new JSONObject();
     164        jsonUnit.put("id", unit.getId());
     165        jsonUnit.put("description", HTML.encodeTags(unit.getName() + " - " + unit.getDescription()));
     166        jsonUnit.put("symbol", HTML.encodeTags(unit.getDisplaySymbol()));
     167        jsonUnits.add(jsonUnit);
     168      }
     169      jsonAt.put("units", jsonUnits);
     170    }
     171  }
     172 
     173  // Categories
     174  JSONArray jsonCategories = new JSONArray();
     175  ItemQuery<AnnotationTypeCategory> categoryQuery = at.getCategories();
     176  categoryQuery.include(Include.MINE, Include.OTHERS, Include.SHARED, Include.IN_PROJECT);
     177  categoryQuery.join(Hql.innerJoin("annotationTypes", "atp"));
     178  categoryQuery.restrict(Restrictions.eq(Hql.alias("atp"), Hql.entity(at)));
     179  for (AnnotationTypeCategory category : categoryQuery.list(dc))
     180  {
     181    allCategories.add(category);
     182    jsonCategories.add(category.getId());
     183  }
     184  jsonAt.put("categories", jsonCategories);
     185
     186 
     187  if (a != null)
     188  {
     189    createJSON(jsonA, dc, a, formatter, false);
     190   
     191    if (a.getSource() != Annotation.Source.PRIMARY)
     192    {
     193      Annotation inherited = a.getInheritedFrom();
     194      if (inherited != null)
     195      {
     196        JSONObject jsonInherited = new JSONObject();
     197        createJSON(jsonInherited, dc, inherited, formatter, true);
     198        Annotatable inheritedFrom = inherited.getAnnotationSet().getItem(dc);
     199        JSONObject jsonFrom = new JSONObject();
     200        jsonFrom.put("id", inheritedFrom.getId());
     201        jsonFrom.put("name", ((Nameable)inheritedFrom).getName());
     202        jsonFrom.put("type", inheritedFrom.getType().name());
     203        jsonInherited.put("from", jsonFrom);
     204        json.put("inherited", jsonInherited);
     205      }
     206    }
     207
     208  }
     209
     210  return json;
    92211}
     212
     213private void createJSON(JSONObject json, DbControl dc, Annotation a, Formatter formatter, boolean formatAll)
     214{
     215  json.put("id", a.getId());
     216 
     217  Unit currentUnit = a.getUnit();
     218  if (currentUnit != null)
     219  {
     220    json.put("unit", currentUnit.getId());
     221    json.put("unitSymbol", currentUnit.getDisplaySymbol());
     222  }
     223 
     224  // Populate the values array
     225  List values = a.getValues(null);
     226  if (values != null)
     227  {
     228    JSONArray jsonValues = new JSONArray();
     229    json.put("values", jsonValues);
     230   
     231    for (Object value : values)
     232    {
     233      // Dates should be formatted to strings using the current date(time) format
     234      if (formatAll || value instanceof Date)
     235      {
     236        value = formatter.format(value);
     237      }
     238      jsonValues.add(value.toString());
     239    }
     240  }
     241 
     242}
     243
    93244%>
    94245<%
     
    100251final int protocolId = Values.getInt(request.getParameter("protocol_id"), -1);
    101252final int subtypeId = Values.getInt(request.getParameter("subtype_id"), -1);
    102 final int annotationTypeId = Values.getInt(request.getParameter("annotationtype_id"));
     253final int annotationId = Values.getInt(request.getParameter("annotation_id"));
     254int annotationTypeId = Values.getInt(request.getParameter("annotationtype_id"));
    103255final boolean standalone = Values.getBoolean(request.getParameter("standalone"));
    104256
     
    107259{
    108260  // Date and time formats
    109   Formatter<Date> dateFormatter = FormatterFactory.getDateFormatter(sc);
    110261  String dateFormat = FormatterSettings.getDateFormat(sc);
    111262  String htmlDateFormat = HTML.encodeTags(dateFormat);
    112   Formatter<Date> dateTimeFormatter = FormatterFactory.getDateTimeFormatter(sc);
    113263  String dateTimeFormat = FormatterSettings.getDateTimeFormat(sc);
    114264  String htmlDateTimeFormat = HTML.encodeTags(dateTimeFormat);
     265 
     266  Annotatable item = null;
     267 
     268  if (annotationId != 0)
     269  {
     270    Annotation a = Annotation.getById(dc, annotationId);
     271    item = a.getAnnotationSet().getItem();
     272    annotationTypeId = a.getAnnotationType().getId();
     273  }
     274  else if (itemId != 0)
     275  {
     276    item = (Annotatable)itemType.getById(dc, itemId);
     277  }
     278  final boolean writePermission = item == null ? true : item.hasPermission(Permission.WRITE);
    115279 
    116280  // Load the current item and it's protocol
    117281  // NOTE! User may have selected a different protocol in the form than what is
    118282  // currently saved so if a protocol_id is sent in the request we use that
    119   final Annotatable item = itemId == 0 ? null : (Annotatable)itemType.getById(dc, itemId);
    120   final boolean writePermission = item == null ? true : item.hasPermission(Permission.WRITE);
    121283  Protocol protocol = null;
    122284  boolean readProtocol = true;
     
    163325  {}
    164326 
     327  //selectedCategoryName = "Test"; // DEBUG!!
     328 
    165329  if (standalone)
    166330  {
     
    187351  final ItemQuery<AnnotationType> parameterQuery = Base.getProtocolParametersQuery(protocol);
    188352
    189   // Query to retrieve the categories of an annotation type
    190   final ItemQuery<AnnotationTypeCategory> categoryQuery = AnnotationTypeCategory.getQuery();
    191   categoryQuery.include(Include.MINE, Include.OTHERS, Include.SHARED, Include.IN_PROJECT);
    192   categoryQuery.join(Hql.innerJoin("annotationTypes", "atp"));
    193   categoryQuery.restrict(Restrictions.eq(Hql.alias("atp"), Expressions.parameter("annotationType")));
    194 
    195353  // Holds all categories that we have found
    196354  final Set<AnnotationTypeCategory> allCategories =
     
    199357  // Load existing annotations
    200358  AnnotationSet as = null;
    201   Map<AnnotationType, Annotation> existing = new HashMap<AnnotationType, Annotation>();
     359  Map<AnnotationType, Annotation> primary = new HashMap<AnnotationType, Annotation>();
     360  List<Annotation> inherited = new ArrayList<Annotation>();
    202361  if (item != null && item.isAnnotated())
    203362  {
    204363    // Load the existing annotations
    205364    as = item.getAnnotationSet();
    206     List<Annotation> annotations = as.getAnnotations().list(dc);
     365    ItemQuery<Annotation> aQuery = as.getAnnotations(null);
     366    aQuery.order(Orders.asc(Hql.property("annotationType.name")));
     367    List<Annotation> annotations = aQuery.list(dc);
    207368    for (Annotation a : annotations)
    208369    {
    209370      try
    210371      {
    211         existing.put(a.getAnnotationType(), a);
     372        if (a.getSource() == Annotation.Source.PRIMARY)
     373        {
     374          primary.put(a.getAnnotationType(), a);
     375        }
     376        else
     377        {
     378          inherited.add(a);
     379        }
    212380      }
    213381      catch (PermissionDeniedException ex)
     
    223391  Set<AnnotationType> protocolParameters = new HashSet<AnnotationType>();
    224392  annotationTypes.addAll(annotationTypeQuery.list(dc));
    225   annotationTypes.addAll(existing.keySet());
     393  annotationTypes.addAll(primary.keySet());
    226394  if (annotationTypeId != 0)
    227395  {
     
    238406  for (AnnotationType at : annotationTypes)
    239407  {
    240     // Load existing values and unit if they exists
    241     Type valueType = at.getValueType();
    242     List values = null;
    243     Unit unit = at.getDefaultUnit();
    244     if (existing != null && existing.containsKey(at))
    245     {
    246       Annotation a = existing.get(at);
    247       unit = a.getUnit();
    248       values = a.getValues(null);
    249     }
    250     if (at.isRemoved() && values == null) continue;
    251    
    252     JSONObject jsonAt = new JSONObject();
    253     JSONArray jsonValues = new JSONArray();
    254     JSONArray jsonCategories = new JSONArray();
    255     jsonAt.put("id", at.getId());
    256     jsonAt.put("name", at.getName());
    257     jsonAt.put("valueType", valueType.name());
    258     jsonAt.put("multiplicity", at.getMultiplicity());
    259     jsonAt.put("enumeration", at.isEnumeration());
    260     jsonAt.put("parameter", protocolParameters.contains(at));
    261     jsonAt.put("unit", unit == null ? 0 : unit.getId());
    262     jsonAt.put("values", jsonValues);
    263     jsonAt.put("categories", jsonCategories);
    264     jsonAnnotations.add(jsonAt);
    265    
    266     // Populate the values array
    267     if (values != null)
    268     {
    269       for (Object value : values)
    270       {
    271         // Dates should be formatted to strings using the current date(time) format
    272         if (value instanceof Date)
    273         {
    274           if (valueType == Type.TIMESTAMP)
    275           {
    276             value = dateTimeFormatter.format((Date)value);
    277           }
    278           else
    279           {
    280             value = dateFormatter.format((Date)value);
    281           }
    282         }
    283         jsonValues.add(value.toString());
    284       }
    285     }
    286     // Populate the categories
    287     boolean checkCategoryNameAgainstSubtype = at.getId() == annotationTypeId;
    288     boolean foundCategoryForSubtype = false;
    289     categoryQuery.setParameter("annotationType", at.getId(), Type.INT);
    290     for (AnnotationTypeCategory category : categoryQuery.list(dc))
    291     {
    292       if (checkCategoryNameAgainstSubtype)
    293       {
    294         if (category.getName().equals(selectedCategoryName)) foundCategoryForSubtype = true;
    295       }
    296       allCategories.add(category);
    297       jsonCategories.add(category.getId());
    298     }
    299     if (checkCategoryNameAgainstSubtype && !foundCategoryForSubtype) selectedCategoryName = null;
     408    Annotation a = primary.get(at);
     409    if (at.isRemoved() && a == null) continue;
     410    JSONObject json = makeJSON(dc, at, a, protocolParameters.contains(at), allCategories);
     411    jsonAnnotations.add(json);
     412  }
     413  for (Annotation a : inherited)
     414  {
     415    AnnotationType at = a.getAnnotationType();
     416    JSONObject json = makeJSON(dc, at, a, false, allCategories);
     417    jsonAnnotations.add(json);
    300418  }
    301419  %>
    302420  <base:page type="<%=standalone ? "popup" : "iframe"%>" title="<%=title%>">
    303   <base:head scripts="~annotate.js" styles="parameters.css" />
     421  <base:head scripts="~annotate.js" styles="parameters.css">
     422  <style>
     423  .first-primary:before
     424  {
     425    content: '― Primary Annotations ―';
     426    font-variant: small-caps;
     427    font-size: 80%;
     428    font-weight: bold;
     429    color: #999999;
     430  }
     431 
     432  .first-inherited:before
     433  {
     434    content: '― Inherited & Cloned ―';
     435    font-variant: small-caps;
     436    font-size: 80%;
     437    font-weight: bold;
     438    color: #999999;
     439  }
     440 
     441  #selected-name
     442  {
     443    font-weight: bold;
     444  }
     445 
     446  #selected-description
     447  {
     448    margin-left: 0px;
     449    margin-right: 0px;
     450    display: none;
     451  }
     452 
     453  #none-selected
     454  {
     455    display: none;
     456    margin-top: 2em;
     457  }
     458 
     459  #selected-container > div
     460  {
     461    display: none;
     462  }
     463 
     464  #selected-container.none-selected #none-selected
     465  {
     466    display: block;
     467  }
     468  #selected-container.none-selected.no-annotations #none-selected
     469  {
     470    display: none;
     471  }
     472 
     473  #selected-container.selected #info-container
     474  {
     475    display: block;
     476  }
     477 
     478  #selected-container.has-description #selected-description
     479  {
     480    display: block;
     481  }
     482
     483  #selected-container.INHERITED #inherited-container,
     484  #selected-container.CLONED #inherited-container
     485  {
     486    display: block;
     487  }
     488
     489  #selected-container.inherited-missing #inherited-missing
     490  {
     491    display: block;
     492  }
     493  #selected-container.inherited-missing #inherited-container
     494  {
     495    display: none;
     496  }
     497 
     498  #selected-container.PRIMARY #input-container,
     499  #selected-container.CLONED #input-container
     500  {
     501    display: block;
     502  }
     503 
     504  #input-container > div
     505  {
     506    display: none;
     507  }
     508 
     509  #selected-container.ENUM-SINGLE #ENUM-SINGLE
     510  {
     511    display: block;
     512  }
     513  #selected-container.ENUM-MULTIPLE #ENUM-MULTIPLE
     514  {
     515    display: block;
     516  }
     517  #selected-container.ENUM-RADIO-CHECKBOX #ENUM-RADIO-CHECKBOX
     518  {
     519    display: block;
     520  }
     521  #selected-container.STRING #STRING-container
     522  {
     523    display: block;
     524  }
     525  #selected-container.TEXT #TEXT-container
     526  {
     527    display: block;
     528  }
     529  #selected-container.INT #INT-container
     530  {
     531    display: block;
     532  }
     533  #selected-container.LONG #LONG-container
     534  {
     535    display: block;
     536  }
     537  #selected-container.FLOAT #FLOAT-container
     538  {
     539    display: block;
     540  }
     541  #selected-container.DOUBLE #DOUBLE-container
     542  {
     543    display: block;
     544  }
     545  #selected-container.BOOLEAN #BOOLEAN-container
     546  {
     547    display: block;
     548  }
     549  #selected-container.DATE #DATE-container
     550  {
     551    display: block;
     552  }
     553  #selected-container.TIMESTAMP #TIMESTAMP-container
     554  {
     555    display: block;
     556  }
     557  #selected-container.has-unit .numeric
     558  {
     559    float: left;
     560    margin-right: 0.25em;
     561  }
     562  #selected-container.has-unit #unit-container
     563  {
     564    display: block;
     565  }
     566  .not-specified
     567  {
     568    font-style: italic;
     569  }
     570  </style>
     571  </base:head>
    304572  <base:body>
    305573    <%
     
    315583      data-annotations="<%=HTML.encodeTags(jsonAnnotations.toJSONString()) %>"
    316584      data-annotation-type-id="<%=annotationTypeId%>"
     585      data-annotation-id="<%=annotationId %>"
    317586      data-date-format="<%=htmlDateFormat%>"
    318587      data-datetime-format="<%=htmlDateTimeFormat%>"
     
    351620        </div>
    352621       
    353         <div class="absolutefull parameterlist topborder"
     622        <div id="annotation-list" class="absolutefull parameterlist topborder"
    354623          style="top: 2em; bottom: 3em;">
     624          <div class="first-primary"></div>
    355625          <%
    356           if (annotationTypes.size() == 0)
     626          if (annotationTypes.size() == 0 && inherited.size() == 0)
    357627          {
    358628            %>
     
    361631            </div>
    362632            <%
    363           }
    364           else
    365           {
    366             for (AnnotationType at : annotationTypes)
    367             {
    368               boolean isParameter = protocolParameters.contains(at);
    369               String label = HTML.encodeTags(at.getName());
    370               String icon = "";
    371               if (at.isRemoved()) icon += "<img src=\"../../images/deleted.png\" alt=\"\">";
    372               if (protocolParameters.contains(at)) icon += "<img src=\"../../images/parameter.png\" alt=\"\">";
    373               %>
    374               <div class="param interactable" id="prompt.<%=at.getId()%>" title="<%=label%>" data-annotation-type-id="<%=at.getId()%>">
    375                 <span class="icon"><img id="icon.<%=at.getId()%>" src="../../images/notrequired_novalues.png" alt=""></span>
    376                 <span class="label"><%=icon%><%=label%></span>
    377               </div>
    378               <%
    379             }
    380633          }
    381634          %>
     
    416669        <br>
    417670        </div>
    418         <%
    419         for (AnnotationType at : annotationTypes)
    420         {
    421           Annotation a = as != null && as.hasAnnotation(at) ? as.getAnnotation(at) : null;
    422           int multiplicity = at.getMultiplicity();
    423           String inputName = "value."+at.getId();
    424           Type valueType = at.getValueType();
    425           %>
    426           <div id="section.<%=at.getId()%>" style="display: none;">
    427           <%
    428           if (at.isEnumeration())
    429           {
    430             String select = null;
    431             if (multiplicity == 0)
    432             {
    433               select = "Select one or more";
    434             }
    435             else if (multiplicity == 1)
    436             {
    437               select = "Select one";
    438             }
    439             else
    440             {
    441               select = "Select 1‒"+multiplicity;
    442             }
    443             List<?> values = at.getValues();
    444             Formatter f = FormatterFactory.getTypeFormatter(sc, at.getValueType());
    445             String unitSymbol = "";
    446             if (at.supportUnits()) unitSymbol = "&nbsp;" + at.getDefaultUnit().getDisplaySymbol();
    447             %>
    448             <b><%=HTML.encodeTags(at.getName())%></b> (<%=select%>)<br>
    449             <%
    450             if (at.getDisplayAsList())
    451             {
    452               if (multiplicity == 1)
    453               {
    454                 %>
    455                 <select name="<%=inputName%>" id="<%=inputName%>" class="auto-init" data-auto-init="detect-change">
    456                 <option value="" style="font-style: italic;">- not specified -
    457                 <%
    458               }
    459               else
    460               {
    461                 %>
    462                 <select name="<%=inputName%>" multiple size="10" class="auto-init" data-auto-init="detect-change">
    463                 <%
    464               }
    465               for (Object value : values)
    466               {
    467                 String encoded = f.format(value);
    468                 %>
    469                 <option value="<%=encoded%>"><%=encoded%><%=unitSymbol%>
    470                 <%
    471               }
    472               %>
     671       
     672        <div id="selected-container">
     673          <div id="none-selected" class="messagecontainer note">
     674            <base:icon image="goback.png" /> Select an annotation.
     675          </div>
     676
     677          <div id="info-container">
     678            <span id="selected-name">Name</span>
     679            (<span id="selected-type">type</span>)
     680          </div>
     681         
     682          <div id="inherited-container">
     683            <span id="inherited-values"></span><br>
     684            Inherited from <span id="inherited-item"></span>
     685          </div>
     686         
     687          <div id="inherited-missing">
     688            Cloned from an unknown item.
     689          </div>
     690       
     691          <div id="input-container">
     692         
     693            <div id="ENUM-SINGLE">
     694              <select name="ENUM-SINGLE-input" id="ENUM-SINGLE-input"
     695                style="min-width: 5em;">
    473696              </select>
    474               <%
    475             }
    476             else
    477             {
    478               String checkType = multiplicity == 1 ? "radio" : "checkbox";
    479               int i = 0;
    480               if (multiplicity == 1)
    481               {
    482                 %>
    483                 <input name="<%=inputName%>" id="<%=inputName%>.0" type="radio" class="auto-init" data-auto-init="detect-change"
    484                   checked value=""><label for="<%=inputName%>.0"><i>- not specified -</i></label><br>
    485                 <%
    486                 i++;
    487               }
    488               for (Object value : values)
    489               {
    490                 String encoded = f.format(value);
    491                 %>
    492                 <input name="<%=inputName%>" id="<%=inputName%>.<%=i%>" type="<%=checkType%>" class="auto-init" data-auto-init="detect-change"
    493                   value="<%=encoded%>"><label for="<%=inputName%>.<%=i%>"><%=encoded%><%=unitSymbol%></label><br>
    494                 <%
    495                 i++;
    496               }
    497             }
    498           }
    499           else if (valueType == Type.INT || valueType == Type.LONG)
    500           {
    501             %>
    502             <b><%=HTML.encodeTags(at.getName())%></b>
    503             (<%=valueType.toString()%><%=minMax(at.getMinValueLong(), at.getMaxValueLong())%>)<br>
    504             <input class="text auto-init" data-auto-init="detect-change" type="text" name="<%=inputName%>" id="<%=inputName%>" value="" style="width: 12em;" maxlength="20">
    505             <%
    506           }
    507           else if (valueType == Type.FLOAT || valueType == Type.DOUBLE)
    508           {
    509             %>
    510             <b><%=HTML.encodeTags(at.getName())%></b>
    511             (<%=valueType.toString()%><%=minMax(at.getMinValueDouble(), at.getMaxValueDouble())%>)<br>
    512             <input class="text auto-init" data-auto-init="detect-change" type="text" name="<%=inputName%>" id="<%=inputName%>" value="" style="width: 12em;" maxlength="20">
    513             <%
    514           }
    515           else if (valueType == Type.STRING)
    516           {
    517             Integer maxLength = at.getMaxLength();
    518             if (maxLength == null) maxLength = 255;
    519             %>
    520             <b><%=HTML.encodeTags(at.getName())%></b> (String)<br>
    521             <input class="text auto-init" data-auto-init="detect-change" type="text" name="<%=inputName%>" id="<%=inputName%>" value="" maxlength="<%=maxLength%>">
    522             <%
    523           }
    524           else if (valueType == Type.TEXT)
    525           {
    526             int height = at.getHeight() <= 0 ? 6 : at.getHeight();
    527             if (height > 20) height = 20;
    528             %>
    529             <b><%=HTML.encodeTags(at.getName())%></b> (Text)<br>
    530             <table style="width: 100%;">
    531             <tr>
     697            </div>
     698             
     699            <div id="ENUM-MULTIPLE">
     700              <select name="ENUM-MULTIPLE-input" id="ENUM-MULTIPLE-input"
     701                multiple size="10" style="min-width: 5em;">
     702              </select>
     703            </div>
     704             
     705            <div id="ENUM-RADIO-CHECKBOX">
     706              radios/checkboxes
     707            </div>
     708       
     709            <div id="STRING-container">
     710              <input name="STRING-input" id="STRING-input"
     711                type="text" class="text"
     712                maxlength="255" value="">
     713            </div>
     714           
     715            <div id="TEXT-container">
     716              <table style="width: 100%;">
     717              <tr>
     718                <td>
     719                <textarea name="TEXT-input" id="TEXT-input"
     720                  class="text" rows="5"></textarea>
     721                </td>
     722                <td style="width: 20px;">
     723                  <base:icon
     724                    id="TEXT-zoom"
     725                    image="zoom.png"
     726                    tooltip="Edit in larger window"
     727                  />
     728                </td>
     729              </tr>
     730              </table>
     731            </div>
     732           
     733            <div id="INT-container" class="numeric">
     734              <input
     735                name="INT-input" id="INT-input"
     736                class="text" type="text"
     737                value="" style="width: 12em;" maxlength="20">
     738            </div>
     739
     740            <div id="LONG-container" class="numeric">
     741              <input
     742                name="LONG-input" id="LONG-input"
     743                class="text" type="text"
     744                value="" style="width: 12em;" maxlength="20">
     745            </div>
     746           
     747            <div id="FLOAT-container" class="numeric">
     748              <input
     749                name="FLOAT-input" id="FLOAT-input"
     750                class="text" type="text"
     751                value="" style="width: 12em;" maxlength="20">
     752            </div>
     753
     754            <div id="DOUBLE-container" class="numeric">
     755              <input
     756                name="DOUBLE-input" id="DOUBLE-input"
     757                class="text" type="text"
     758                value="" style="width: 12em;" maxlength="20">
     759            </div>
     760         
     761            <div id="unit-container">
     762              <select name="unit" id="unit" style="min-width: 5em;"></select>
     763            </div>
     764           
     765            <div id="DATE-container">
     766              <table>
     767              <tr>
    532768              <td>
    533               <textarea class="text auto-init" data-auto-init="detect-change" name="<%=inputName%>" id="<%=inputName%>" rows="<%=height%>"></textarea>
     769                <input
     770                  name="DATE-input" id="DATE-input"
     771                  class="text" type="text"
     772                  value="" style="width: 15em;" maxlength="20"
     773                  title="Enter date in format: <%=htmlDateFormat%>">
    534774              </td>
    535               <td style="width: 20px;">
    536                 <base:zoom textarea="<%=inputName%>" title="<%=HTML.encodeTags(at.getName())%>" tooltip="Edit in larger window" />
    537               </td>
    538             </tr>
    539             </table>
    540             <%
    541           }
    542           else if (valueType == Type.BOOLEAN)
    543           {
    544             %>
    545             <b><%=HTML.encodeTags(at.getName())%></b><br>
    546             <input type="radio" name="<%=inputName%>" id="<%=inputName%>.null" value="" checked
    547               class="auto-init" data-auto-init="detect-change"><label for="<%=inputName%>.null"><i>- not specified -</i></label><br>
    548             <input type="radio" name="<%=inputName%>" id="<%=inputName%>.true" value="true"
    549               class="auto-init" data-auto-init="detect-change"><label for="<%=inputName%>.true">true</label><br>
    550             <input type="radio" name="<%=inputName%>" id="<%=inputName%>.false" value="false"
    551               class="auto-init" data-auto-init="detect-change"><label for="<%=inputName%>.false">false</label>
    552             <%
    553           }
    554           else if (valueType == Type.DATE)
    555           {
    556             %>
    557             <table>
    558             <tr>
    559             <td>
    560               <b><%=HTML.encodeTags(at.getName())%></b> (Date)<br>
    561               <input class="text auto-init" data-auto-init="detect-change" type="text" name="<%=inputName%>" id="<%=inputName%>" value="" style="width: 15em;"
    562                 maxlength="20" title="Enter date in format: <%=htmlDateFormat%>">
    563             </td>
    564             <td>
    565                 <br>
     775              <td>
    566776                <base:button
    567                   id="<%="btn."+at.getId()%>"
     777                  id="DATE-calendar"
    568778                  image="calendar.png"
    569779                  title="Calendar&hellip;"
    570780                  tooltip="Select a date from a calendar"
    571781                />
    572             </td>
    573             </tr>
    574             </table>
    575             <%
    576           }
    577           else if (valueType == Type.TIMESTAMP)
    578           {
    579             %>
    580             <table>
    581             <tr>
    582             <td>
    583               <b><%=HTML.encodeTags(at.getName())%></b> (Timestamp)<br>
    584               <input class="text auto-init" data-auto-init="detect-change" type="text" name="<%=inputName%>" id="<%=inputName%>" value="" style="width: 20em;"
    585                 maxlength="30" title="Enter date + time in format: <%=htmlDateTimeFormat%>">
    586             </td>
    587             <td>
    588                 <br>
     782              </td>
     783              </tr>
     784              </table>
     785            </div>
     786           
     787            <div id="TIMESTAMP-container">
     788              <table>
     789              <tr>
     790              <td>
     791                <input
     792                  name="TIMESTAMP-input" id="TIMESTAMP-input"
     793                  class="text" type="text"
     794                  value="" style="width: 15em;" maxlength="20"
     795                  title="Enter date + time in format: <%=htmlDateTimeFormat%>">
     796              </td>
     797              <td>
    589798                <base:button
    590                   id="<%="btn."+at.getId()%>"
     799                  id="TIMESTAMP-calendar"
    591800                  image="calendar.png"
    592801                  title="Calendar&hellip;"
    593                   tooltip="Select date and time from a calendar" 
     802                  tooltip="Select date and time from a calendar"
    594803                />
    595             </td>
    596             </tr>
    597             </table>
    598             <%
    599           }
    600           if (at.supportUnits() && !at.isEnumeration())
    601           {
    602             ItemQuery<Unit> unitQuery = at.getUsableUnits();
    603             if (unitQuery.count(dc) == 0)
    604             {
    605               unitQuery = at.getQuantity().getUnits();
    606             }
    607             else
    608             {
    609               unitQuery.reset();
    610             }
    611             unitQuery.order(Orders.desc(Hql.property("referenceFactor")));
    612             unitQuery.order(Orders.asc(Hql.property("displaySymbol")));
    613             List<Unit> units = unitQuery.list(dc);
    614             Unit current = a != null ? a.getUnit() : null;
    615             if (current == null) current = at.getDefaultUnit();
    616             %>
    617             <select name="unit.<%=at.getId()%>" id="unit.<%=at.getId()%>">
    618             <%
    619             boolean hasSelected = false;
    620             for (Unit unit : units)
    621             {
    622               String selected = "";
    623               if (unit.equals(current))
    624               {
    625                 selected = " selected";
    626                 hasSelected = true;
    627               }
    628               %>
    629               <option value="<%=unit.getId()%>" <%=selected%>
    630                 title="<%=HTML.encodeTags(unit.getName() + " - " + unit.getDescription()) %>"
    631                 ><%=HTML.encodeTags(unit.getDisplaySymbol())%>
    632               <%
    633             }
    634             if (!hasSelected && current != null)
    635             {
    636               %>
    637               <option value="<%=current.getId()%>" selected
    638                 title="<%=HTML.encodeTags(current.getName() + " - " + current.getDescription()) %>"
    639                 ><%=HTML.encodeTags(current.getDisplaySymbol())%>
    640               <%
    641             }
    642             %>
    643             </select>
    644             <%
    645           }
    646           if (at.getDescription() != null)
    647           {
    648             %>
    649             <div class="messagecontainer help" style="margin-left: 0px; margin-right: 0px;">
    650             <%=HTML.niceFormat(at.getDescription())%>
    651             </div>
    652             <%
    653           }
    654           %>
     804              </td>
     805              </tr>
     806              </table>
     807            </div>
     808         
     809            <div id="BOOLEAN-container">
     810              <label class="not-specified"><input type="radio" name="BOOLEAN-input" id="BOOLEAN-input-NULL"
     811                value="" checked>- not specified -</label><br>
     812              <label><input type="radio" name="BOOLEAN-input" id="BOOLEAN-input-TRUE"
     813                value="true">true</label><br>
     814              <label><input type="radio" name="BOOLEAN-input" id="BOOLEAN-input-FALSE"
     815                value="false">false</label>
     816            </div>
    655817          </div>
    656           <%
    657         }
    658         %>
     818         
     819          <div id="selected-description" class="messagecontainer help">
     820          </div>
     821        </div>
     822 
    659823      </div>
    660824    </div>
  • trunk/www/common/annotations/list.js

    r6600 r6938  
    8181  {
    8282    var target = event.currentTarget;
    83     var annotationTypeId = Data.get(target, 'annotation-type');
     83    var annotationId = Data.int(target, 'annotation');
    8484    var url =  App.getRoot() + 'common/annotations/annotate.jsp?ID='+App.getSessionId();
     85    url += '&annotation_id='+Data.int(target, 'annotation');;
    8586    url += '&item_type='+Data.get(target, 'item-type');
    8687    url += '&item_id='+Data.get(target, 'item-id');
  • trunk/www/common/annotations/list_annotations.jsp

    r6937 r6938  
    196196      display: none;
    197197    }
     198   
     199    .edit-annotation:before
     200    {
     201      display: inline-block;
     202      content: "∙";
     203      color: #999999;
     204      padding-right: 0.25em;
     205      padding-left: 1px;
     206      text-decoration: none;
     207    }
    198208  </style>
    199209  </base:head>
     
    308318                  /><%=Base.getLinkedName(ID, at, false, true)%></tbl:cell>
    309319                  <tbl:cell column="values"><%=values == null || values.size() == 0 ? "<i>- no values -</i>" : Values.getString(values, ", ", true, formatter)%>
    310                   <%
     320                    <%
    311321                    if (writePermission)
    312322                    {
    313                       %>: <base:icon image="edit.png" subclass="auto-init link"
    314                         data-auto-init="edit-annotation" data-annotation-type="<%=at.getId()%>"
    315                         data-item-type="<%=itemType.name()%>" data-item-id="<%=itemId %>"
    316                         tooltip="Modify the values of this annotation" />
     323                      %><base:icon image="edit.png" subclass="edit-annotation auto-init link"
     324                        data-auto-init="edit-annotation"
     325                        data-annotation="<%=a!=null ? a.getThisAnnotationId() : 0 %>"
     326                        data-annotation-type="<%=at.getId()%>"
     327                        data-item-type="<%=itemType.name()%>"
     328                        data-item-id="<%=itemId %>"
     329                        tooltip="Modify the values of this annotation"
     330                      />
    317331                      <%
    318332                    }
     
    336350        data-all-of-category="<%=allOfCategory%>"
    337351      ></div>
    338      
    339352    </base:section>
    340353
     
    416429                      if (writePermission)
    417430                      {
    418                         %>: <base:icon image="edit.png" subclass="auto-init link"
    419                           data-auto-init="edit-annotation" data-annotation-type="<%=at.getId()%>"
    420                           data-item-type="<%=itemType.name()%>" data-item-id="<%=itemId %>"
    421                           tooltip="Modify the values of this protocol parameter" />
     431                        %><base:icon image="edit.png" subclass="edit-annotation auto-init link"
     432                          data-auto-init="edit-annotation"
     433                          data-annotation="<%=a!=null ? a.getThisAnnotationId() : 0 %>"
     434                          data-annotation-type="<%=at.getId()%>"
     435                          data-item-type="<%=itemType.name()%>"
     436                          data-item-id="<%=itemId %>"
     437                          tooltip="Modify the values of this protocol parameter"
     438                        />
    422439                        <%
    423440                      }
     
    557574                    "<i>- no values -</i>" : Values.getString(values, ", ", true, formatter)%>
    558575                  <%
    559                   if (writeInherited && fromItem != null)
     576                  if (writePermission)
    560577                  {
    561                     %>: <base:icon image="edit.png" subclass="auto-init link"
    562                       data-auto-init="edit-annotation" data-annotation-type="<%=at.getId()%>"
    563                       data-item-type="<%=fromItem.getType().name()%>" data-item-id="<%=fromItem.getId() %>"
    564                       tooltip="Modify the values of this annotation" />
     578                    %><base:icon image="edit.png" subclass="edit-annotation auto-init link"
     579                      data-auto-init="edit-annotation"
     580                      data-annotation="<%= a.getThisAnnotationId()%>"
     581                      data-annotation-type="<%=at.getId()%>"
     582                      data-item-type="<%=itemType.name()%>"
     583                      data-item-id="<%=itemId %>"
     584                      tooltip="Modify the values of this annotation"
     585                    />
    565586                    <%
    566587                  }
Note: See TracChangeset for help on using the changeset viewer.