/**
 * Object definition for voc & term prop output
 */
function IndexProp(key,value) {
  this.key   = key;
  this.value = value;
}


/****************************
 * shared utility object    *
 ***************************/
var Util = new Object({
  // css props
  size_props     : ['height', 'padding-top', 'padding-bottom', 'margin-top', 'margin-bottom'],

  // browser behaviour boolean
  browse_defview : document.defaultView && document.defaultView.getComputedStyle,

  // vars used in ajax
  show           : null,
  hide           : null,
  show_langs     : null,
  hide_langs     : null,

  /**
   * changes the image colour of a [+] or [-] from blue to white / vice-versa on mouse over
   */
  over : function(img) {
    var srch = '';
    if (img.src.indexOf('topsingle-') > 0) {
      srch = 'topsingle';
    } else if (img.src.indexOf('top-') > 0) {
      srch = 'top';
    } else if (img.src.indexOf('mid-') > 0) {
      srch = 'mid';
    } else if (img.src.indexOf('bottom-') > 0) {
      srch = 'bottom';
    } else if (img.src.indexOf('non-') > 0) {
      srch = 'non';
    }  

    if (srch != '') {
      if (img.src.indexOf('over') == -1) {
        var root = img.src.substring(0,img.src.indexOf(srch));
        var end  = img.src.substring(img.src.indexOf(srch)+srch.length);
        img.src  = root+srch+'over'+end;
      }
    }
  },


  /**
   * reverses above functions effect
   */
  out : function(img) {
    if (img.src.indexOf('over')>-1) {
      img.src = img.src.substring(0,img.src.indexOf('over'))+img.src.substring(img.src.indexOf('over')+4);
    }
  },


  /**
   * swaps the tree image of a node from plus to minus / vice-versa
   */
  switchImage : function(obj) {
    var img = null;
    if (obj.nodeName.toLowerCase()=='img') {
      img = obj;
    } else {
      img = obj.getElementsByTagName('img')[0];
    }

    if (img!=null) {
      var t = 'minus';

      if (img.src.indexOf('minus') > -1) {
        pos = img.src.indexOf('minus');
        t   = 'plus';
      } else {
        pos = img.src.indexOf('plus');
      }

      img.src = img.src.substring(0, pos)+t+'.gif';
    }
  },


  /**
   * Removes the tree/expansion image from the given object
   */
  removeImage : function(obj) {
    var img = null;
    if (obj.nodeName=='img' || obj.nodeName=='IMG') {
      img = obj;
    } else {
      img = obj.getElementsByTagName('img')[0];
    }

    if (img!=null) {
      var src = img.src;

      if (src.indexOf('minus') > -1) {
        pos = src.indexOf('minus');
      } else {
        pos = src.indexOf('plus');
      }

      src = src.substring(0, pos);

      if (src.indexOf('over')>-1) {
        src = src.substring(0, src.indexOf('over'));
      }
    
      if (src.substring(src.length-1)!='-') src += '-';
 
      img.src = src+'line.gif';
      img.onclick='';
      img.onmouseover='';
      img.onmouseout='';
    }
  },


  /**
   * simple array contains method returning a boolean as JavaScript has no such built in function
   */
  arrayContains : function(arr, val) {
    for (var m in arr) {
      if (arr[m]==val) return true;
    }
    return false;
  },


  /**
   * get the final part of a string, either after last / or # or just return the string itself
   */
  trimURI : function(uri) {
    var display = uri.substring(uri.lastIndexOf('/')+1);
    if (display==null) display = uri.substring(uri.lastIndexOf('#')+1);
    if (display==null) display = uri;

    display = display.substring(0,1).toUpperCase()+display.substring(1);
    return display;
  },


  /**
   * build a table row with two cols, first is header second is value. if value is null return empty string (ie, no row created)
   */
  buildTableRow : function(header, data) {
    var row = '';
    if (data!=null && data!='' && data!='null') {
      row = '<tr><td class="expBtn">&nbsp;</td><th class="fix">'+header+'</th><td class="data">'+data+'</td></tr>';
    }

    return row;
  },


  /**
   * gets the terms url out of the onclick attribute of the given object
   */
  extractTermUrl : function(term_node) {
    var onclick_attr = $(term_node).parent().parent().children('span').attr('onclick')+'';
    var prefix       = 'viewTerm(this.parentNode, "';

    var url = onclick_attr.substring(onclick_attr.indexOf(prefix)+prefix.length);
    url     = url.substring(0, url.lastIndexOf('"'));
    return url;
  },


  /**
   * Returns a boolean to describe whether the function parameter is a JavaScript object that has member properties
   */
  isPopulatedObject : function(obj) {
    if (obj!=null) {
      if (typeof obj == 'object') {
        for (var member in obj) {
          if (member!=null && obj[member]!=null) {
            return true;
          }
        }
      }
    }
    return false;
  },


  /**
   * Displays the loading text and enables a blocking glasspane over the page
   */
  showLoading : function(obj) {
    document.body.style.cursor = 'progress'; 
    $('#glasspane').show();

    if (obj=='voc_list') {
      $('#tree_cont').html('<span class="loading">'+VAR_LOADING_TEXT+'</span>');
    } else if (obj!=null) {
      if ($(obj).hasClass('fauxlink')){
        var html = $(obj).html();
        $(obj).html(html+' <span class="loading">'+VAR_LOADING_TEXT+'</span>'); 
      } else {
        var html = $(obj).children('span.fauxlink').html();
        $(obj).children('span.fauxlink').html(html+' <span class="loading">'+VAR_LOADING_TEXT+'</span>'); 
      }
    }
  },


  /**
   * Reverses the above function 
   */
  hideLoading : function() {
    document.body.style.cursor='auto';
    $('#glasspane').hide();
    $('span.loading').remove();
  },


  /**
   * Cross browser viewport height function
   */
  getBrowserHeight : function() {
    var height = 0;
 
    if (typeof window.innerHeight != 'undefined') {
      height = window.innerHeight;

    } else if (typeof document.documentElement!='undefined' && 
               typeof document.documentElement.clientHeight!='undefined' && document.documentElement.clientHeight!=0) {
      height = document.documentElement.clientHeight;
    } else {
      height = document.getElementsByTagName('body')[0].clientHeight;
    } 

    return height;
  },


  /**
   * Resizes the elements as specified by their IDs in the functions array parameter to be fixed to a relative size of the screens height.
   */
  sizeUpBoxes : function(arr) {
    //var height = this.getBrowserHeight();
    var height = $(window).height();

    // size of header, footer, hardcoded size is for shadow on top and bottom, h2 height plus some spacing
    var rem = $('#header').outerHeight(true)+(110)+$('#content h2').outerHeight(true)+$('#footer').outerHeight(true)+16/*Margins*/;
 
    if ($('#search').attr('id') != null) {
      rem += $('#search').outerHeight(true);
    }
    
    if ($('.pagination').attr('id') != null) {
      rem += $('.pagination').outerHeight(true);
    } 
   
    if ($('#rInfo').attr('id')!=null) {
      rem += $('#rInfo').outerHeight(true);
    }

    height = height-rem;
     
    $('#iefix .mid').height(height);
    
  },


  /**
   * Gets the computed height of the element.
   */
  getHeight : function(element_id) {
    var val     = 0;
    var element = document.getElementById(element_id);
  
    if (element!=null) {
      var curr  = element.currentStyle;
  
      for (var member in this.size_props) {
        var prop = this.size_props[member];

        if (this.browse_defview) {
          val = this.incPx(val, document.defaultView.getComputedStyle(element, "").getPropertyValue(prop));
        } else if (curr) {
          val = this.incPx(val, element.currentStyle[prop]);
        } else {
          val = this.incPx(val, element.style[prop]);
        }
      }
    } 
    return val;
  },


  /**
   * Increments a string value of a pixel based number with the given (second) parameter)
   */
  incPx : function(one, two) {
    var px1 = this.pxVal(one);
    var px2 = this.pxVal(two);
    var result = 0;

    if (isNaN(parseInt(px1))==false) result += parseInt(px1);
    if (isNaN(parseInt(px2))==false) result += parseInt(px2);

    return result;
  },


  /**
   * returns the value in pixels from computed style
   */
  pxVal : function(val) {
    var px_val = 0;

    if (val!=null) {
      if (typeof val=='string') {
        var pos = val.indexOf('px');
        if (pos>-1) val = val.substring(0, pos);
        if (isNaN(parseInt(val))==false) px_val = val;
 
      } else if (typeof val=='number') {
        px_val = val;
      }
    }
    return px_val;
  },


  /**
   * Returns a data string to append to all AJAX URL calls to stop IE caching.
   */
  getDateString : function() {
    var d = new Date();
    return d.getDate()+d.getHours()+d.getMinutes()+d.getMilliseconds();
  },


  /**
   * Sets alt and title tag on img specified by id
   */
  setAltAndTitle : function(id,text) {
    $(id).attr('alt', text);
    $(id).attr('title', text);
  },


  /**
   * switches the image and resizes the node
   */
  switchAndResize : function(node,height) {
    if (isNaN(parseInt(height))==false) {
      $(node).css('height', height+'px');
    } else {
      $(node).css('height', height);
    }
    Util.switchImage(node);
  },


  // Shared AJAX routines 

  /**
   * Displays errors in the info pane.
   */
  displayError : function(errors) {
    if (errors!=null) {
      var err = errors[VAR_ERROR_TEXT]+'<ul>';

      for (var i=0; i<errors[VAR_ERRORS].length; i++) {
        err += '<li>'+errors[VAR_ERRORS][i]+'</li>';
        if (i<(errors.length-1)) err += '</ul>';
      }
      $(VAR_INFO_ELEMENT).empty();
      $(VAR_INFO_ELEMENT).append(err);
    }
  },


  /**
   * Deals with viewing a vocab 
   * fetches vocab from webservice and builds json object
   * called when a user clicks a vocab name
   */
  viewVocab : function(node, url) {
    $.ajax({
      type: VAR_HTTP_METHOD,
      url:  VAR_URL_INFO.replace('_url_', url)+'?nocache='+Util.getDateString(),
      dataType: 'json',
      global: false,
      beforeSend: Util.showLoading(node),
      success: function(data) {
        if (data[VAR_ERRORS]!=null) {
          Util.displayError(data);
        } else {
          Util.highlightNode(node);
          var vocab        = data['vocab'];
          var readables    = data['readables'];
          var export_urls  = data['export_urls'];
          var props        = vocab[VAR_PROPS];
          var parsed_props = new Object();

          // grab the localised strings that need to be used outside this function
          Util.show_langs = readables[VAR_LANGS_SHOW];
          Util.hide_langs = readables[VAR_LANGS_HIDE];

          // first pull out the properties we want displaying in order
          for (var i=0; i<data['schema'].length; i++) {
            parsed_props[data['schema'][i]] = new IndexProp(null, null);
          }

          // work through the props in the actual vocab, add any non schema ones onto the end of the list
          for (var uri in props) {
            var prop = props[uri];
            parsed_props[uri] = new IndexProp(props[uri][VAR_NAME], props[uri][VAR_VALUE]);
          }

          // id, auth, profile, status, max rev
         // parsed_props[VAR_URI_ID]   = new IndexProp(readables[VAR_IDEN_KEY], vocab[VAR_IDENTIFIER]);
        //  parsed_props[VAR_URI_AUTH] = new IndexProp(readables[VAR_AUTH_KEY], vocab[VAR_AUTHORITY]);
        //  parsed_props['prof']       = new IndexProp(readables[VAR_PROF_KEY], vocab[VAR_VOC_PROFILE]);
        if(vocab[VAR_STATUS]!=null)
        {
          parsed_props['stat']       = new IndexProp(readables[VAR_STAT_KEY], vocab[VAR_STATUS]);
        }
         // parsed_props['maxr']       = new IndexProp(readables[VAR_MAXR_KEY], data[VAR_MAXR_VAL]);
          parsed_props['numt']       = new IndexProp(readables[VAR_TERM_COUNT_KEY], vocab[VAR_TERM_COUNT]);

          // display property information
          var info = '<table><tr><td class="expcol">&nbsp;</td><th colspan="2" class="sec_head">'+readables[VAR_VOC_INFO]+'</th></tr>';
          for (var uri in parsed_props) {
            var prop_title = parsed_props[uri].key;
            if (prop_title==null) prop_title = Util.trimURI(uri);

            if (vocab[VAR_LOC_PROPS]!=null && vocab[VAR_LOC_PROPS][uri]!=null) {
              var th = parsed_props[uri].key;
              var td = parsed_props[uri].value;
              var id = th.replace(' ','')+'Lang';

              td += '<span id="'+id+'table" class="hiddenTableWrapper"><table>';
              
              for (var lang in vocab[VAR_LOC_PROPS][uri]) {
                td += '<tr><td>'+vocab[VAR_LOC_PROPS][uri][lang][VAR_VALUE]+'</td><td class="lang">'+lang+'</td></tr>';
              }
              td += '</table></span>';

              info += '<tr><td class="topalign">';
              info += '<img id="'+id+'img" src="images/tree/non-plus.gif" class="cursor" onclick="Util.toggleLangTable(\''+id+'\')" onmouseover="Util.over(this)" onmouseout="Util.out(this) "alt="'+Util.show_langs+'" title="'+Util.show_langs+'"/>';
              info += '</td><th class="fix">'+prop_title+'</th><td>'+td+'</td></tr>';
            } else {
              info += Util.buildTableRow(prop_title, parsed_props[uri].value);
            }
          }    
          
          
          // if user is logged in and exporters are available show download form
          // no true object reflection in JS so need to check that this object represents an associative array
          if (Util.isPopulatedObject(export_urls)) {
            info += '<tr><td colspan="3">&nbsp;</td></tr>';
            info += '<tr><td>&nbsp;</td><td colspan="2">'+readables[VAR_DOWNLOAD_TEXT_KEY]+'</td></tr>';
            info += '<tr><td>&nbsp;</td><td colspan="2" style="text-align: center"><select id="downloadselect">';
            for (var text in export_urls) {
              info += '<option value="'+export_urls[text]+'">'+text+'</option>';
            }
            info += '</select>&nbsp;&nbsp;';
            info += '<input type="button" value="'+readables[VAR_DOWNLOAD_KEY]+'" onclick="Util.doDownload(\'downloadselect\')"/></td></tr>';
          }

          info += '</table>';
          $(VAR_INFO_ELEMENT).empty();
          $(VAR_INFO_ELEMENT).append(info);
        }
        Util.hideLoading();
      }
    });
  },


  /** 
   * Deals with viewing a term 
   * fetches term from webservice and builds json object
   * called when a user clicks a term
   */
  viewTerm : function(node, url) {
    $.ajax({
      type: VAR_HTTP_METHOD,
      url:  VAR_URL_INFO.replace('_url_', url)+'?nocache='+Util.getDateString(),
      dataType: 'json', 
      global: false,
      beforeSend: Util.showLoading(node), 
      success: function(data) {
        if (data[VAR_ERRORS]!=null) {
          Util.displayError(data);

        } else {
          Util.highlightNode(node);
          var term         = data['term'];
          var readables    = data['readables'];
          var props        = term[VAR_PROPS];
          var parsed_props = new Object();
          var term_auth    = term[VAR_SRC_VOC_AUTH]==null ? term[VAR_VOC_AUTH] : term[VAR_SRC_VOC_AUTH];

          // grab the localised strings that need to be used outside this function
          Util.show_langs = readables[VAR_LANGS_SHOW];
          Util.hide_langs = readables[VAR_LANGS_HIDE];
          Util.show       = readables[VAR_SHOW];
          Util.hide       = readables[VAR_HIDE];

          // first pull out the properties we want displaying in order
          for (var i=0; i<data['schema'].length; i++) {
            parsed_props[data['schema'][i]] = new IndexProp(null, null);
          }

          // work through the props in the actual term
          for (var uri in props) {
            var prop = props[uri];
            parsed_props[uri] = new IndexProp(prop[VAR_NAME], prop[VAR_VALUE]);
          }

         // parsed_props[VAR_URI_ID]       = new IndexProp(readables[VAR_IDEN_KEY],      term[VAR_IDENTIFIER]);
         // if (term[VAR_TERM_TYPE]!=null) {
         //   parsed_props[VAR_URI_TERMTYPE] = new IndexProp(readables[VAR_TERM_TYPE_KEY], term[VAR_TERM_TYPE]);
        //  }
        //  parsed_props['au']             = new IndexProp(readables[VAR_AUTH_KEY],      term_auth);
        
        if(term[VAR_STATUS]!=null)
        {
          parsed_props['st']             = new IndexProp(readables[VAR_STAT_KEY],      term[VAR_STATUS]);
        }
        //  parsed_props[VAR_URI_SORTKEY]  = new IndexProp(readables[VAR_SORT_KEY_KEY],  term[VAR_SORT_KEY]);

          var info = '<table>';

          // display vocab information
          info += '<tr><td class="expcol">&nbsp;</td><th colspan="2" class="sec_head">'+readables[VAR_VOC_INFO]+'</th></tr>';
          info += '<tr><td class="expcol">&nbsp;</td><th class="fix" width="100">'+readables[VAR_VOCAB_ID_KEY]+'</th><td>'+term[VAR_VOC_IDENTIFIER]+'</th></tr>';
          var voc_name_key = term[VAR_VOC_IDENTIFIER]+':'+term[VAR_VOC_AUTH];
          if (data['voc_names']!=null && data['voc_names'][voc_name_key]!=null) {
            info += '<tr><td class="expcol">&nbsp;</td>';
            info += '<th class="fix">'+readables[VAR_VOCAB_NAME_KEY]+'</th>';
            info += '<td>'+data['voc_names'][voc_name_key]+'</td></tr>';
          }
          info += '<tr><td colspan="3">&nbsp;</td></tr>';
          info += '<tr><td class="expcol">&nbsp;</td><th colspan="2" class="sec_head">'+readables[VAR_TERM_INFO]+'</th></tr>';

          // display property information
          for (var uri in parsed_props) {
            var prop_title = parsed_props[uri].key;
            if (prop_title==null) prop_title = Util.trimURI(uri);
            if (term[VAR_LOC_PROPS]!=null && term[VAR_LOC_PROPS][uri]!=null) {
              var th = parsed_props[uri].key;
              var id = th.replace(' ','')+'Lang';
              var td = parsed_props[uri].value+'<span id="'+id+'table" class="hiddenTableWrapper"><table>';

              for (var lang in term[VAR_LOC_PROPS][uri]) {
                td += '<tr><td>'+term[VAR_LOC_PROPS][uri][lang][VAR_VALUE]+'</td><td class="lang">'+lang+'</td></tr>';
              }
              td += '</table></span>';

              info += '<tr><td class="topalign">';
              info += '<img id="'+id+'img" onclick="Util.toggleLangTable(\''+id+'\')" src="images/tree/non-plus.gif" class="cursor" onmouseover="Util.over(this)" onmouseout="Util.out(this)" alt="'+Util.show_langs+'" title="'+Util.show_langs+'" />';
              info += '</td><th class="fix">'+prop_title+'</th><td>'+td+'</td></tr>';
            } else {
              info += Util.buildTableRow(prop_title, parsed_props[uri].value);
            }
          }

          // term rels
          var rels      = term[VAR_TERM_RELS];
          var rel_types = data[VAR_REL_TYPES];
          info += '<tr><td colspan="3">&nbsp;</td></tr>';
          if (rels.length>0) {
            var rel_vid = data[VAR_LOOKUP_MODE]==VAR_LOOKUP_BY_LONG ? term[VAR_VOC_HEADER_ID] : term[VAR_VOC_IDENTIFIER];
            var url = '/'+term[VAR_VOC_AUTH]+'/'+rel_vid+'/';
            info += '<tr><td class="topalign">';
            info += '<img id="relsimg" src="images/tree/non-plus.gif" class="cursor" onclick="Util.toggleRels()"';
            info += ' onmouseover="Util.over(this)" onmouseout="Util.out(this)" alt="'+Util.show+'" title="'+Util.show+'"/>';

            info += '</td><th colspan="2">'+readables[VAR_RELS_KEY]+'</th></tr>';
            info += '<tr><td class="expcol">&nbsp;</td><td colspan="2"><table id="termrels">';
            for (var i=0; i<rels.length; i++) {
              var rel      = rels[i];
              var rel_type = rel_types[rel[VAR_RELCODE]];
              var rid      = data[VAR_LOOKUP_MODE]==VAR_LOOKUP_BY_LONG ? rel[VAR_HEADER_ID] : rel[VAR_IDENTIFIER];
              var rname    = rel[VAR_DISPLAY_NAME];
              if (rname==null) rname= VAR_UNNAMED;

              info += '<tr><th><span title="'+rel_type[VAR_NAME]+'" class="rel '+rel_type[VAR_REL_BASE_TYPE]+'">';
              info += rel_type[VAR_MNEMONIC]+'</span></th>';
              info += '<td><span class="fauxlink" onclick="Util.viewTerm(null,\''+url+'term/'+rid+'\')">'
              info += rname+'</span></td></tr>';
            }
            info += '</table></td></tr>';
           
          } 
          else 
          {
            info += '<tr><td class="expcol">&nbsp;</td><td colspan="2"><em>'+readables[VAR_NO_RELS_KEY]+'</em></td></tr>';
          }

          // term occurences
          var occs = data['other_occs'];
          info += '<tr><td colspan="3">&nbsp;</td></tr>';
          if (occs.length>0) {
            info += '<tr><td class="topalign">';
            info += '<img id="occsimg" src="images/tree/non-plus.gif" class="cursor" onclick="Util.toggleOccs()" onmouseover="Util.over(this)" onmouseout="Util.out(this)" alt="'+Util.show+'" title="'+Util.show+'"/>';
            info += '</td><th colspan="2">'+readables[VAR_OCCS_KEY]+'</th></tr>';
            info += '<tr><td>&nbsp;</td><td colspan="2"><table id="termoccs">';
            for (var i=0; i<occs.length; i++) {
              var occ      = occs[i];
              var voc_id   = data[VAR_LOOKUP_MODE]==VAR_LOOKUP_BY_LONG ? occ[VAR_VOC_REF][VAR_HEADER_ID] : occ[VAR_VOC_REF][VAR_IDENTIFIER];
              var occ_id   = data[VAR_LOOKUP_MODE]==VAR_LOOKUP_BY_LONG ? occ[VAR_HEADER_ID] : occ[VAR_IDENTIFIER];

              var voc_auth = occ[VAR_VOC_REF][VAR_AUTHORITY][VAR_CODE];
              var url      = '/'+voc_auth+'/'+voc_id+'/term/'+occ_id;
              url=url.replace(/#/g,"%23");
              var voc_name = data['voc_names'][occ[VAR_VOC_REF][VAR_IDENTIFIER]+':'+voc_auth];
              if (voc_name==null) voc_name = occ[VAR_VOC_REF][VAR_IDENTIFIER];
              info += '<tr><td><span class="fauxlink" onclick="Util.viewTerm(null,\''+url+'\')">'+voc_name+'</span></td></tr>';
            }
            info += '</table></td></tr>';
          } else {
            info += '<tr><td class="expcol">&nbsp;</td><td colspan="2"><em>'+readables[VAR_NO_OCCS_KEY]+'</em></td></tr>';
          }

          if (term[VAR_SRC_VOC_ID]!=null) {
            info += '<tr><td colspan="3">&nbsp;</td></tr>';
            var voc_iden = term[VAR_SRC_VOC_ID];
            var voc_auth = term[VAR_SRC_VOC_AUTH];
            var voc_name = data['voc_names'][voc_iden+':'+voc_auth];
            var rep_text = '';

            if (voc_name!=null) {
              var vid     = data[VAR_LOOKUP_MODE]==VAR_LOOKUP_BY_LONG ? term[VAR_SRC_VOC_HEAD_ID] : voc_iden;
              var src_url = '/'+voc_auth+'/'+vid;
              rep_text    = '<span class="fauxlink" onclick="Util.viewVocab(null, \''+src_url+'\')">'+voc_name+'</span>';
              rep_text    = readables[VAR_TERM_SRC].replace('_vocid_', rep_text);
            } else {
              rep_text = readables[VAR_TERM_SRC_ID].replace('_vocid_', voc_iden)
            }

            info += '<tr><td>&nbsp;</td><td colspan="2">'+rep_text+'</td></tr>';
          }
          info += '</table>';

          $(VAR_INFO_ELEMENT).empty();
          $(VAR_INFO_ELEMENT).append(info);
           if(rels.length>0 && rels.length<16)
            {
                Util.toggleRels();
            }
            
            
            if(occs.length>0 && occs.length<6)
            {
                Util.toggleOccs();
            }
           
        }
        Util.hideLoading();
        
      }
    });
  },


  /**
   * Toggles the display of a specific language table
   */
  toggleLangTable : function(id_prefix) {
    var tableid = '#'+id_prefix+'table';
    var imgid   = '#'+id_prefix+'img';

    if ($(tableid).css('display')=='none') {
      if (Util.hide_langs==null || Util.hide_langs=='null') Util.hide_langs='';
      Util.setAltAndTitle(imgid,Util.hide_langs);
      $(tableid).slideDown('fast');
    } else {
      if (Util.hide_langs==null || Util.hide_langs=='null') Util.show_langs='';
      Util.setAltAndTitle(imgid,Util.show_langs);
      $(tableid).slideUp('fast');
    }
    Util.switchImage(document.getElementById(id_prefix+'img'));
  },


  /**
   * Simply toggles the display of the termrels table
   */
  toggleRels : function() {
    if ($('#termrels').css('display')=='none') {
      Util.setAltAndTitle('#relsimg', Util.hide);
      $('#termrels').slideDown('fast');
    } else {
      Util.setAltAndTitle('#relsimg', Util.show);
      $('#termrels').slideUp('fast');
    }

    Util.switchImage(document.getElementById('relsimg'));
  },


  /**
   * Simply toggles the display of the termoccs table
   */
  toggleOccs : function() {
    if ($('#termoccs').css('display')=='none') {
      if (Util.hide==null || Util.hide=='null') Util.hide='';
      Util.setAltAndTitle('#occsimg', Util.hide);
      $('#termoccs').slideDown('fast');
    } else {
      if (Util.show==null || Util.show=='null') Util.show='';
      Util.setAltAndTitle('#occsimg', Util.show);
      $('#termoccs').slideUp('fast');
    }
    Util.switchImage(document.getElementById('occsimg'));
  },

  
  /**
   * Shows highlight css around the selected node (and removes all othere highlighted items)
   */
  
  highlightNode : function(node) {
    $('.highlight').removeClass('highlight');
    if (node!=null) {
      if (node.tagName=='LI' || node.tagName=='li') {
        $(node).children('.fauxlink').addClass('highlight');
      } else {
        $(node).addClass('highlight');
      }
    }
  },


  /**
   * Downloads a vocab in the format selected
   */
  doDownload : function(select) {
    var url = $('#'+select).val();
    if (url!=null) {
      window.location.assign(url+'?nocache='+Util.getDateString());
    }
  }
});
