//
// Copyright (c) 2007-2010 Textensor Limited, creators of publicationslist.org
//
// For licensing info / suggestions / problems
// contact support@publicationslist.org
//
//

// The schema of bibtex in JS
var helpByArticleType = {
  "article": "An article from a journal or magazine.",
  "book" : "A book with an explicit publisher.",
  "booklet" : "A work that is printed and bound, but without a named publisher or sponsoring institution.",
  "inbook" : "A part of a book, which may be a chapter (or section or whatever) and/or a range of pages.",
  "incollection" : "A part of a book having its own title.",
  "inproceedings" : "An article in a conference proceedings.",
  "manual" : "Technical documentation.",
  "mastersthesis" : "A Master's thesis.",
  "misc" : "For use when nothing else fits.",
  "phdthesis" : "A Ph.D. thesis.",  
  "proceedings" : "The proceedings of a conference.",
  "techreport" : "A report published by a school or other institution, usually numbered within a series.",  
  "unpublished" : "A document having an author and title, but not formally published."
};

var displayType = {
  "article": "Journal articles",
  "book" : "Books",
  "booklet" : "Booklets",
  "inbook" : "Book chapters", 
  "incollection" : "Book chapters", 
  "inproceedings" : "Conference papers",
  "manual" : "Technical manuals",
  "mastersthesis" : "Masters theses",
  "misc" : "Other",
  "phdthesis" : "PhD theses",  
  "proceedings" : "Conference proceedings", 
  "techreport" : "Technical reports", 
  "unpublished" : "Other"
};

// List of fields by type, in order of display
// everything has author, year, note, key
var commonFields = ["abstract", "note", "tags", "url", "doi"];
  
// unused fields: "eid", "annote", "archive", "key"
var fieldsByType = {
  "article" : ["author", "year",  "title", "journal", "volume", "number", "pages", "month"],
  "book" : ["author", "year", "title",  "editor", "address", "publisher", "volume", 
            "series", "edition", "isbn"],
  "booklet" : ["author", "year", "title", "howpublished", "address"],
  "inbook" : ["author", "year", "title", "chapter", "editor", "pages", "address", "publisher", "volume", "series", "edition", "isbn"],
  "incollection" : [ "author", "year", "title", "booktitle", 						
                     "editor", "pages", "organization", "address", "publisher", "isbn"],
  "inproceedings" : ["author", "year", "title", "booktitle", "editor", "pages", "organization", "address", "publisher"],
  "manual" : [ "author", "year", "title", "organization", "address", "edition"],  
  "mastersthesis" : ["author", "year", "title", "school", "address"],
  "misc" : ["author", "year", "title", "howpublished", "sectionheading"],
  "phdthesis" : ["author", "year", "title", "school", "address"],
  "proceedings" : ["title", "year", "editor", "address", "publisher", "organization"],
  "techreport" : ["author", "year", "title", "institution", "series", "number",  "address"],
  "unpublished" : ["author", "year", "title"]
};

// rot images by type *** TODO
var imagesByType = {
  "article" : "laf/r-ja.png",
  "book" : "laf/r-book.png",
  "booklet" : "laf/r-booklet.png",
  "inbook" : "laf/r-chapter.png",
  "incollection" : "laf/r-chapter.png",
  "inproceedings" : "laf/r-conf.png",
  "manual" : "laf/r-manual.png",
  "mastersthesis" : "laf/r-thesis.png",
  "misc" : "laf/r-other.png",
  "phdthesis" : "laf/r-thesis.png",
  "proceedings" : "laf/r-proceedings.png",
  "techreport" : "laf/r-report.png",
  "unpublished" : "laf/r-other.png"
};

// A style.
var plosStyle = {
  "year" : { "pre":"(", post:")"}, 
  "title" : { "pre": "&nbsp;", "post":"&nbsp;" },
  "volume" : { "post":":" },
  "number" : { "post":"." },
  "address" : { "post": ":" },
  "url" : { "pre": "Available:" },
  "booktitle" : { "pre": "In:" },
  "editor" : { "pre": "Edited by:", "post" : ". " },
  "doi" : { "pre": "doi:" },
  "sectionheading" : { "pre": "[", "post":"]" },
  "isbn" : { "pre" : "isbn:"}
};

// Form style for fields
var lengthByField = {
  "journal" : 40,
	"howpublished" : 40,
	"address" : 80,
	"author" : 79, // never share a line
	"title" : 240,
	"month" : 5,
	"year" : 5,
	"booktitle" : 80,
	"volume" : 4,
	"number" : 5,
	"series" : 40,
	"editor" : 60,
	"publisher" : 60,
	"school" : 80,
	"organization" : 80,
	"chapter" : 5,
	"edition" : 10,
	"pages" : 10,
  "institution"  : 40,
  "type" : 40,
  "isbn" : 10
	};


var helpByField = {
  "journal" : "The name of the journal",
  "howpublished" : "How something strange has been published. The first word should be capitalized.",
  "address" : "The city or address of the publisher or other type of institution.",
  "author" : "Use commas for multiple authors, e.g. Alex N. Other, Joe Bloggs, Jane Doe",
  "title" : "The title of the article",
  "month" : "The month in which the work was published or, for an unpublished work, in which it was written.",
  "year" : "e.g. 2007",
  "booktitle" : "The title of the book",
  "volume" : "The volume of a journal or multi-volume book.",
  "number" : "The number of a journal, magazine, technical report, or of a work in a series.",
  "series" : "The name of a series or set of books.",
  "editor" : "Name(s) of editor(s), separated by commas",
  "publisher" : "The publisher's name.",
  "school" : "The name of the school where a thesis was written.",
  "organization" : "The organization that sponsors a conference or that publishes a manual.",
  "chapter" : "A chapter (or section or whatever) number",
  "edition" : "The edition of a book - for example, 'Second'.",
  "pages" : "One or more page numbers or range of numbers, such as 42-111 or 7,41,73-9710",
  "institution"  : "The sponsoring institution of a technical report.",
  "type" : "The type of a technical report - for example, 'Research Note'",
  "annote" : "Annotation describing the significance of the publication."
}; 



var optionalFields = {
  "number" : 1,
  "pages" : 1,
  "organization" : 1,
  "address" : 1,
  "publisher" : 1,
  "editor" : 1,
  "series" : 1,
  "edition" : 1,
  "month" : 1,
  "isbn" : 1
  
};


var hideIfCollapsed = {
  "abstract" : 1,
  "note" : 1,
  "tags" : 1
};

function getDisplayName(field, atype) {
  var dname = displayNameByField[field];

  if (atype=='inproceedings' && field=='booktitle') { return "Proceedings title"; }
  else if (atype=='incollection' && field=='title') { return "Chapter title"; }
  else return dname;
}

function isOptional(field, atype) {
  if (field=='volume' && (atype=='book' || atype=='inbook')) { return true; }
  return optionalFields[field];
}


var displayNameByField = {
  "journal" : "Journal",
	"howpublished" : "How Published",
	"address" : "Address",
	"volume" : "Volume",
	"author" : "Authors",
	"title" : "Title",
	"month" : "Month",
	"year" : "Year",
	"number" : "Number",
	"series" : "Series",
	"chapter" : "Chapter",
	"editor" : "Edited by",
	"publisher" : "Publisher",
	"school" : "School",
    "booktitle" : "Book Title",
	"organization" : "Organization",
	"edition" : "Edition",
	"pages" : "Pages",
	"type" : "Type of publication",
	"institution"  : "Institution",
  "isbn" : "ISBN"
};

function findLinkEnd(str, pos) {
  var end = str.length;
  var found = false;
  for (var i=pos; !found && i<str.length; i++) {
    var ch = str.charAt(i);
    if (ch==' ' || ch=="\n" || ch=="\r" || ch=="\t") {
      end = i;
      found = true;
    }
  }
  return end;
}

// Linkify plain text
function linkify(txt) {  
  
  var ret = "";
  do {
    var pos = txt.indexOf("http://", 0);
    if (pos != -1) {
      var epos = findLinkEnd(txt, pos);
      var link = txt.substr(pos, epos - pos);
      ret += txt.substr(0, pos);
      ret += " <a href='"+link+"'>"+link+"</a> ";
      txt = txt.substr(epos);
    }
    else {
      ret += txt;
    }
  } while (pos != -1);

  return ret;
  
}

function getDisplayType(atype) {
  if (displayType[atype]) { return displayType[atype]; }
  return "Misc";
}

function trim(str) {
  if (!str) { return ""; }
  return str.replace(/^\s+/g, '').replace(/\s+$/g, '');
}

function splitTags(tags) {
  var commasplit =  tags.split(",");
  if (tags.indexOf(";") != -1) {
    var semisplit =  tags.split(";");
    if (semisplit.length > commasplit.length) { return semisplit; }
  }
  return commasplit;
}



// Is str a valid surname?
function validSurname(str) {
  if (str.length <=1) { return false; }  
  var ich = str.substr(0,1);  
  //  alert("ICH is "+ich);
  if (ich == ich.toUpperCase()) {
	if (str.length > 3) { 
	  return true; 
	}
	if (str != str.toUpperCase()) {
	  return true;
	}
  }  
  return false;  
}

function validInitials(str) {
  if (str == "") { return true; }
  var init = str.substr(0,1);
  var sameupper = (str == str.toUpperCase());
  var samelower = (str == str.toLowerCase());
  if (sameupper || samelower) {
	if (str.length < 4) {
	  return true;
	}
  }
  return false;
}

function appendSpace(ostr, nstr) {
  if (nstr == "") { return ostr; }
  if (ostr != "") { return ostr + " "+ nstr; }
  return nstr;
}

function prependSpace(ostr, nstr) {
  if (nstr == "") { return ostr; }
  if (ostr != "") { return nstr + " "+ ostr; }
  return nstr;
}


// Convert author name to obj : first: middle: last
function newSplitAuthor(prevauthor, author) {
  author = author.replace(/\./g, ' ');
  
  var words = author.split(" ");

  // Remove empty words and brackets
  var words2 = new Array();
  var ignore = 0;
  for (var i=0; i<words.length; i++) {
	var w = trim(words[i]);
	//	alert("word "+w);
	if (w != "") {
	  if (w.indexOf("(") != -1) {
		ignore ++;
	  }
	  else if (w.indexOf(")") != -1) {
		ignore --;
	  }
	  else if (ignore <= 0) {
		words2[words2.length] = w;
	  }
	}
  }

  words = words2;
  var num = words.length;
  //  alert("words "+words);

  if (num == 0) { return false; } // or "" "" "" ? 
  
  var first = "";
  var middle = "";
  var last = "";
  
  if (words.length > 0) { last = words[words.length -1]; }
  var lastvalid = validSurname(last);
  var lastvalidinitial = validInitials(last);

  var allinitials = true;
  for (var i=0; i<num; i++) {
	if (!validInitials(words[i])) {
	  allinitials = false;
	}
  }

  if (num == 1) {
	if (lastvalid || prevauthor == false || !lastvalidinitial || prevauthor.first != prevauthor.first.toLowerCase()) {
	  var ret = {"first" : first, "middle" : middle, "last" : last };
	  return ret;
	}
	else {
	  prevauthor["first"] = prependSpace(prevauthor["first"], last);
	  prevauthor["extended"] = true;
	  return prevauthor;
	}
  }
  else {
	first = words[0];
	firstvalid = validSurname(first);
	if (firstvalid && !lastvalid) {
	  // we're looking at Howell F W - do a swap.
	  var sncount = 1;
	  for (var n = 1; n < num; n++) {
		if (validSurname(words[n])) {
		  sncount = n + 1;
		}
		else {
		  break;
		}
	  }
	  var newwords = new Array();
	  for (var n = sncount; n < num; n++) {
		newwords[newwords.length] = words[n];
	  }
	  for (var n=0; n<sncount; n++) {
		newwords[newwords.length] = words[n];
	  }
	  words = newwords;
	  first = words[0];
	  last = words[num-1];	  
	}
	else if (allinitials && prevauthor != false && prevauthor.first == prevauthor.first.toLowerCase()) {
	  var extra = words[0];
	  for (var n=1; n<num; n++) {
		extra = appendSpace(extra, words[n]);
	  }
	  prevauthor["first"] = prependSpace(prevauthor["first"], extra);
	  prevauthor["extended"] = true;
	  return prevauthor;
	}
  }

  // OK, now just regular...

  if (words.length > 1) { 
	first = words[0]; 
  } 
  if (words.length > 2) { 
    var midstart = 1;
    var midend = words.length - 2;
    
    var mid = words[words.length-2]; 
    if (mid == "Dalla" || mid == "De" || mid == "Do" || mid == "Der" || mid == "La" || mid == "Le" || mid == "Van" || mid == "Von" || mid == mid.toLowerCase()) {
      last = mid+" "+last;
      midend --;
    }

    // Check for van der ...
    if (words.length > 3) {
      var mid = words[words.length-3];
      if (mid == "De" || mid == "Van" || mid == "Von" || mid == mid.toLowerCase()) {
        last = mid+" "+last;
        midend --;
      }      
    }
    
    if (midstart <= midend) {
      for (var i=midstart; i<=midend; i++) {
		if (middle != "") { middle += " "; }
		middle += words[i];
      }
    }
  }

  // Check for 1st name all caps and no middle
  if (validInitials(first) && middle == "" && first == first.toUpperCase()) {
	var rest = first;
	var init = first.substr(0,1);
	first = init;
	do {
	  var rest = rest.substr(1);
	  if (rest != "") {
		init = rest.substr(0,1);
		if (init) {
		  middle = appendSpace(middle, init);
		}
	  }
	  
	} while (rest);
  }
  
  var ret = {"first" : first, "middle" : middle, "last" : last };
  return ret;
}


// Convert author name to obj : first: middle: last
function authorNameToObj(str) {
  return newSplitAuthor(false, str);
}

 // Convert an author string to an array of objs
function authorStringToArray(str) {
  str = str.replace(/[\&\;]/g, ",");
  str = str.replace(/[\:\.]/g, " "); // do allow - sign
  str = str.replace(/\ and\ /g, ",");
  //  alert(str);
  var list = splitTags(str); 
  var ret = new Array();

  var prevauthor = false;

  for (var j=0; j<list.length; j++) {
    var name = trim(list[j]);
	if (name) {
	  var nextauthor = newSplitAuthor(prevauthor, name);
	  if (typeof(nextauthor.extended) != "undefined") {
		ret[ret.length -1] = nextauthor;
		prevauthor = false;
	  }
	  else if (nextauthor) {
		ret[ret.length] = nextauthor;
		prevauthor = nextauthor;
	  }
	}
  }
  return ret;
}


function removeChildren(el) {
  if (el) {
    while (el.firstChild) {
      el.removeChild(el.firstChild);
    }
  }
}

function divInnerHtml(el, txt) {
  removeChildren(el);
  var sp = document.createElement("div");
  sp.innerHTML = txt;
  el.appendChild(sp);
}

function spanInnerHtml(el, txt) {
  if (el) {
	removeChildren(el);
	var sp = document.createElement("span");
	sp.innerHTML = txt;
	el.appendChild(sp);
  }
}

// Handle toggle refs without interfering with selection.
var dragged = false;

function refDown() {
  dragged = false;
}
function refDrag() {
   dragged = true;
}
var idx = 0;
function toggleIdx() {
  toggleRef(idx);
}
function refUp(i) {
  if (!dragged) {
    idx = i;
    // Do it in timeout thread or get selection problems.
    setTimeout(toggleIdx, 10);
  }
}


// Note: a is URI encoded
function visitAuthor(a) {
  //  alert("got "+a);
  if (!dragged) {
    refDrag(); // cancel toggle...
    parent.location = rootpath+"php/authors.php?a="+a;
  }
}

// Convert authors to index links.
function linkifyAuthors(authors) {
  var ary = authorStringToArray(authors);
  var ret = "";
  for (var i=0; i<ary.length; i++) {
    var f = ary[i]["first"];
    var m = ary[i]["middle"];
    var l = ary[i]["last"];
    var link = l;
    if (m!="") { link = m+"_"+link; }
    if (f!="") { link = f+"_"+link; }
    var cma = "";
    if (i<ary.length-1) { cma = ", "; }
	var enclink = encodeURIComponent(link);
	enclink = enclink.replace(/\'/g, "%27"); // ' 
    ret += "<a class='authorlink' title='Open author index' href='javascript:visitAuthor(\""+enclink+"\")'>"+f+" "+m+" "+l+"</a>"+cma; // "</span><span class='author'>";
  }
  return ret;
}

// Fix a URL entered without http://
function httpPrefix(url) {
  if (url) {
	var init = url.substr(0,4);
	if (init != "http" && init != "ftp:") {
	  return "http://"+url;
	}
  }
  return url;
}

// Variable for tag show / hide.
var tagshowidx = 1;

// Convert a ref object to HTML.
function refToHtml(atype, ref, expanded, userid, rootpath, toggleIdx) {
  if (!atype) atype="article";
  var style = plosStyle;
  var txt = "";
  var fields = fieldsByType[atype];
  var first = true;

  //  txt += ".";


  // Do the common fields.
  txt += "<div class='fulltextlinks'>\n"; // style='float:right; padding-left : 12px; width: 64px;'>";

  if (ref["urllink"]) {
	txt += " <a class='htmllink' title='View HTML version' href='"+httpPrefix(ref.urllink)+"'><img src='"+rootpath+"page-sml.png'/></a>";
  }

  if (ref["pdflink"]) {
	txt += " <a class='pdflink' title='View PDF version' href='"+httpPrefix(ref.pdflink)+"'><img src='"+rootpath+"pdf-sml.png'/></a>";
  }
  var attachmenturl = "";

  if (ref["attachment"]) {    
    var ext = ref.attachment.lastIndexOf(".");
    var str = "";
	var tp = ""; 
    if (ext!=-1) { tp = ref.attachment.substr(ext+1); }
	
	str += tp;
	if (tp == "pdf") {
	  str = "<img src='"+rootpath+"pdf-sml.png'/>";
	}
	else {
	  str = "[" + str +"]";
	}

	txt += " <a class='pdflink' title='View local version' href='";
	
	if (ref.attachment.substring(0,4)=="http") {
	  attachmenturl = ref.attachment;
	}
	else {
	  attachmenturl = rootpath+"data/"+userid+"/"+ref.attachment;
	}
	txt += attachmenturl;
	txt += "'>"+str+"</a>";
  }
  
  if (ref["doi"]) {
    var href = ref.doi;
    if (ref.doi.substr(0,4)!="http") {
      href = "http://dx.doi.org/"+ref.doi;
    }
    txt += " &nbsp;<br/><a target='_blank' class='doilink' title='DOI: "+ref.doi+"' href='"+href+"'>DOI</a>&nbsp;";
  }

  if (ref["pubmed"]) {
    var href = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=pubmed&cmd=Retrieve&dopt=AbstractPlus&list_uids="+ref.pubmed;

    txt += " &nbsp;<br/><a target='_blank' class='pubmedlink' title='PubMed ID : "+ref.pubmed+"' href='"+href+"'>PMID</a>&nbsp;";
  }
  if (ref["repostatus"]=="accepted") {
    txt += " &nbsp;<br/><a target='repository' class='repolink' title='View Repository Copy' " +
      "href='"+ref.repourl+"'>Repository</a>&nbsp;";
  }
  txt += "</div>";


  // Is there a thumbnail?
  if (ref._thumb) {
    if (typeof(nothumbs)!="undefined" && nothumbs) {} else {
    txt += "<div class='thumbdiv'>"; 
    if (ref.attachment) {
      txt += " <a target='_blank' class='pdflink' title='View local version' href='"+attachmenturl+"'>";
    }


    var thumburl = ref._thumb;
    if (thumburl.substring(0,4) != "http") {
      // full refid can be user-123
      var refnum = "" + ref.refid; if (refnum.indexOf("-")!==-1) { refnum = refnum.substr(refnum.lastIndexOf("-")+1); }

      thumburl = rootpath+"data/"+userid+"/ref-"+refnum+"/"+ref._thumb;
    }
    txt += "<img width='80px' class='thumbimg' src='"+thumburl+"'/>";
    if (ref.attachment) {
      txt += "</a>";
    }
    txt += "</div>";
    }
  }


  /*
  if (toggleIdx != -1) {
    txt += "<span class='refbody' onmousedown='refDown()' onmousemove='refDrag()' onmouseup='refUp("+toggleIdx+")'>";
  }
  else {
  */
  txt += "<span class='refbody'>";
  //}
  for (var j=0; j<fields.length; j++) {
	var fn = fields[j];

	if (ref[fn]) {
	  if (!first) {
	    txt += " "; 
	  }
	  	 
	  var entry = trim(ref[fn]);
	  
	  if (entry) {
		if (fn=="author") {
		  entry = linkifyAuthors(entry);
		}
		var pre = "";
		var post = " ";
		if (style[fn]) { 
		  if (style[fn]["pre"]) { pre = style[fn].pre; }
		  if (style[fn]["post"]) { post = style[fn].post; }
		}
		// work-around for IE6 bug
		if (fn != "author") {// && document.all && !window.XMLHttpRequest) { 
		  // Special case for IE6
		  if (fn=="year" || fn=="month" || fn=="institution" || fn=="organization" || fn=="publisher" || fn=="series" || fn=="pages" || fn=="address" || fn=="number") { pre = " "+pre; } 
		  var ocl = " onclick='toggleRef("+toggleIdx+")'";
		  if (fn == "title") {
		    var words = entry.split(" ");
		    txt +=  "<a name='x'"+ocl+" class='ax "+fn+"'>"+pre+"</a>";
		    for (var k=0; k<words.length; k++) {
		      txt += "<a name='x'"+ocl+" class='ax "+fn+"'>"+words[k]+"</a> ";
		    }
		    txt +=  "<a name='x'"+ocl+" class='ax "+fn+"'>"+post+"</a>";
		  }
		  else {
		    txt += "<a name='x' class='ax "+fn+"'>"+pre+entry+post+"</a> ";
		  }
		}
		else {
		  txt += entry+" "; // "<a name='x' class='"+fn+"'>"+pre+entry+post+"</a> ";
		}
		//	if (document.all) { txt += "&nbsp;"; }
		first = false;
	  }
	}
  }

  txt += "&nbsp; </span>"; // end of the onclick area. nbsp needed or IE mucks up display


  if (expanded) {
	if (ref["tags"]) {
	  var list = splitTags(ref["tags"]);
	  txt += " <div class='tags'>";
	  var maxtags = 3;

	  for (var k=0; k<list.length; k++) {
		var tag = trim(list[k]);
		var cma = ""; if (k<list.length-1) { cma = ",&nbsp;&nbsp; "; }

		if (k == maxtags && list.length > maxtags) {
		  txt += "<a class='atag layout' id='sata"+tagshowidx+"' href='javascript:showAllTags("+tagshowidx+")'><i>(all "+list.length+" tags)</i></a> <span style='display:none' class='layout' id='sats"+tagshowidx+"'>";
		  tagshowidx ++;
		}

		// if (k!=0) { txt += ",&nbsp;&nbsp; "; }
		txt += " <span><a class='atag layout' href='javascript:showTag(\""+tag+"\")'>"+tag+"</a>"+cma+"</span>";
	  }

	  if (list.length > maxtags) {
		txt += "</span>";
	  }
	  txt += "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>";
	}
	
    if (ref["abstract"]) {
      txt += " <div class='abstract layout'>Abstract: "+ref["abstract"]+"</div>"; // *** need to htmlentities...
    }
    
    if (ref["note"]) {
      txt += " <div class='note layout'>Notes: "+linkify(ref["note"])+"</div>"; // *** need to htmlentities...
    }


    if (ref.repostatus || ref.repocollections) {
      txt += " <div class='note layout'>";
      if (ref["repostatus"] == "harvested") {
        txt += "This publication has been harvested by the repository and is being checked. ";
      }
      else if (ref["repostatus"] == "accepted") {
        txt += "This publication is available from the repository: ";

	if (ref["repoid"]) {
	  txt += "<a class='repolink' target='repository' href='"+ref.repourl+"'>Repository entry: "+ref.repoid+"</a> <br/>";
	}
      }
      else if (ref["repostatus"] == "rejected") {
        txt += "This publication was not accepted by the repository: ";
      }
      else if (ref["repostatus"] == "error") {
        txt += "There was a harvesting error for this item.";
      }
      else if (ref["repocollections"]!="" 
	       && ref["repocollections"]!="-"
	       && ref["attachment"]!="") {
        txt += "This publication is available for automated harvesting by the repository";
      }
	       
      
      txt += "</div>";
    }    
    
  }

  txt += "<div style='clear:right'></div>";


  return txt;
}

function showAllTags(idx) {
  var ael = document.getElementById('sata'+idx);
  var sel = document.getElementById('sats'+idx);
  if (ael) {
	ael.style.display = "none";
  }
  if (sel) {
	sel.style.display = "inline";
  }
}

function forceRepaintCB() {
  var el = document.getElementById("publistdiv");
  if (false && el) {
	document.body.removeChild(el);
	//	  alert("Removing bug");
  }
  else if (el) {	  
	var div = document.createElement("span");
	div.id = "iebug";
	div.innerHTML = "&nbsp;";
	el.style.display = "none";
	el.style.display = "block";
	//	alert("Adding pl  bug");
	el.appendChild(div);
  }
}

function forceRepaint() {
  if (document.all) {
	setTimeout(forceRepaintCB, 100);	
  }
}
//
// Utilities for publications list.
//
// Contact/licensing details on http://publicationslist.org
//
// Copyright (c) 2010 Textensor Limited (www.textensor.com)
//
//

var noexport = false;

function getReq() {
  var req;  if (window.XMLHttpRequest) {    req = new XMLHttpRequest();  }
  else {    req = new ActiveXObject("Microsoft.XMLHTTP");  }  return req;
}

function fetchURL(url) {
  var req = getReq();    
  req.open("GET", url, false);  
  req.send(null);  
  var ret = req.responseText;
  return ret;  
}

function postURL(url, args) { 
  var req = getReq();    
  req.open("POST", url, false);  
  req.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
  req.send(args);  
  var ret = req.responseText;
  return ret;  
}

 function findRef(refid) {
   for (var i=0; i<publist.length; i++) {
     if (publist[i].refid == refid) {
       return publist[i];
     }
   }
 }

 function removeRef(refid) {
   for (var i=0; i<publist.length; i++) {
     if (publist[i].refid == refid) {
       publist.splice(i,1);
       return true;
     }
   }
   return false;
 }

function maybeDelete(refid) {
  var ref = findRef(refid);
  var txt = ref.author +" (" + ref.year+") "+ ref.title;

  if (window.confirm("Really delete reference: \n"+txt+"?")) {
    document.location = "deleteRef.php?u="+userid+"&refid="+refid;
  }
}


 function exportSelected(format) {
   var txt = "";
   for (el in selectedById) {
     if (selectedById[el]) {
       if (txt != "") { txt += ","; }
       txt += el;
     }
   }  

   //  alert("txt is "+txt);
   var ret = postURL("exportRef.php?refid=export&fmt="+format+"&u="+userid, "ids="+txt);
   if (ret.substring(0,5) == "OK - ") {
     // alert("Got back "+ret);
     window.open(ret.substring(4), "_blank");
   }
   else {
     alert("Problem exporting : "+ret);
   }   
 }

 
 function deleteSelected() {
   if (window.confirm("Delete "+selectedCount+" highlighted entries?")) {
     // Get a list of selected entries.
     
     var txt = "";
     for (el in selectedById) {
       if (selectedById[el]) {
	 if (txt != "") { txt += ","; }
	 txt += el;
	 removeRef(el);
       }
     }
     
     selectedById = new Object();
     
     //  alert("Highlighted entries are "+txt);
     var ret = postURL("deleteSelected.php", "ids="+txt);
     display();
     countSelected();
     updateTags();
     updateAuthors();

     updateStatus(prevexp, prevvalid, prevpublink, false);

     alert(ret);
     //     document.location = "deleteRecent.php?u="+userid;
   }
 }
 
 

function importSelected() {
  if (window.confirm("Import "+selectedCount+" highlighted entries?")) {
     var txt = "";
     for (el in selectedById) {
       if (selectedById[el]) {
	 if (txt != "") { txt += ","; }
	 txt += el;
       }
     }
     
     var ret = postURL("importSelected.php", "ids="+txt);
     alert(ret);

   }
 }
 


 // array by refid
 var expandedRefs = new Array();
 
 function toggleRef(i) {
   if (expandedRefs[publist[i].refid]) {
     collapseRef(i);
   }
   else {
     expandRef(i);
   }
 }

 function expandRef(i) {
   var div = document.getElementById("list"+i);
   var txt = getRefHtml(i, publist[i], true, publist[i].userid);
   var d2 = document.createElement('div');
   d2.innerHTML = txt;
   removeChildren(div);
   div.appendChild(d2);

   expandedRefs[publist[i].refid] = true;

   // For search page, show the matching snippets
   if (typeof(_query_snippets) != "undefined") {
     if (publist[i]._fulltext) { // in searchutil.js
       setTimeout("fetchSnippets(" + i + ")",50);
     }
   }

 }

 function collapseRef(i) {
   var div = document.getElementById("list"+i);
   var txt = getRefHtml(i, publist[i], false, publist[i].userid);
   var d2 = document.createElement('div');
   d2.innerHTML = txt;
   removeChildren(div);
   div.appendChild(d2);
   expandedRefs[publist[i].refid] = false;
  
 }


function publish() {
  // alert("about to publish");
  var el = document.getElementById("publistdiv");
  var txt = el.innerHTML; 

  var pubform = document.getElementById("pubformid");
  var publisthtml = document.getElementById("publisthtml");
  //  alert("got "+pubform+" and "+publisthtml);
  publisthtml.value = txt;

  //  alert("sending stuff "+txt);
  pubform.submit();
  
  // alert("Posting "+txt);
}

 function isChecked(i) {
   var check = document.getElementById("check"+i);
   if (check && check.checked) {
     return true;
   }
   return false;
 }

 function toggleChecked(i, nocount) {
   var refdiv = document.getElementById("refdiv"+i);
   var editdiv = document.getElementById("editref"+i);

   var checked = isChecked(i);
   if (checked) {
     refdiv.className = "refdiv selref";
	// if (editdiv) editdiv.style.visibility = "visible";
   }
   else {
     refdiv.className = "refdiv";
	// if (editdiv) editdiv.style.visibility = "hidden";
   }
   var refid = publist[i].refid;

   selectedById[refid] = checked;

   if (nocount) {} else {
     countSelected();
   }

   //   alert("Repainting");
   forceRepaint();
 }
 
 var selectedCount = 0;

 var countByTag = false;
 var allTags = new Array();
 
 function updateTags() {
   countByTag = new Object();
   allTags = new Array();
   allTags[0] = "(no tag)";
   countByTag[allTags[0]] = 0;
   for (var i=0; i<publist.length; i++) {
     var ref = publist[i];
     var tags = ref.tags;
     if (tags) {
       var list = splitTags(tags); // tags.split(",");
       for (var j=0; j<list.length; j++) {
	 var tag = trim(list[j]);  
	 if (tag) {
	   if (!countByTag[tag]) { 
	     allTags[allTags.length] = tag; 
	     countByTag[tag] = 0;
	   }
	   countByTag[tag]++;
	 }
       }
     }
     else {
       countByTag["(no tag)"] ++;
     }
   }

   // Sort the tag list.
   allTags.sort(function(a,b) { 
		  if (a=="(no tag)") { return -1; }
		  if (a.toLowerCase() < b.toLowerCase()) { return -1; }
		  if (a.toLowerCase() > b.toLowerCase()) { return 1; }
		  return 0;
		});
   
   // Update the list.
   var el = document.getElementById("tagslist");
   if (el) {
     var txt = "";
     if (allTags.length > 1) {
       el.style.display="block";
       txt += "<b>All Tags:</b> &nbsp;";
       for (var i=1; i<allTags.length; i++) {
	 var tag = allTags[i];
	 if (tag != "") {
	   var count = countByTag[tag];
	   var cstr = (count==1) ? "" : "&nbsp;("+count+")";
	   var htag = tag.replace(" ", "&nbsp;");
	   if (i!=1) { txt += ",&nbsp;&nbsp; "; }
	   txt += "<a class='atag' href='javascript:showTags("+i+")'>"+htag+"</a>"+cstr+"";
	 }
       }
       var div = document.createElement("div");
       //div.style.fontSize = "70%";
       div.innerHTML = txt;
       removeChildren(el);
       el.appendChild(div);
     }
     else {
       el.style.display="none";
     }
   }
 }

 // Version with string
 function showTag(str) {
   selectByTag(str);
 }
 function showTags(i) {
   selectByTag(allTags[i]);
 }
 function showAuthor(str) {
   selectByAuthor(str);
 }
 function showAuthors(i) {
   selectByAuthor(allAuthors[i]);
 }

 var countByAuthor = new Object();

 function lastName(a) {
   var i = a.lastIndexOf(" ");

   // Check for Joe van Bloggs - last name van Bloggs, 
   return a.substr(i);
 }


 // Form: "F Howell"
 function normaliseAuthorObj(aobj) {
   var first = aobj.first;
   var last = aobj.last;
   if (first.length > 1) { first = first.charAt(0); }
   if (first) { return first + " " + last; }
   return last;
 }

 function normaliseAuthor(a) {
   var words = a.split(" ");
   var first = "";

   var last = "";
   if (words.length > 0) { last = words[words.length -1]; }
   if (words.length > 1) { first = words[0].charAt(0); }
   if (words.length > 2) { 
     // Check for van, de, le
     var mid = words[words.length-2];
     if (mid == "Dalla" || mid == "De" || mid == "Do" || mid == "Der" || mid == "La" || mid == "Van" || mid == "Von" || (mid != "" && mid == mid.toLowerCase())) {
       last = mid+" "+last;
       first = words[0].charAt(0); 
     }

     // Check for van der
     if (words.length > 3) {
       var mid = words[words.length-3];
       if (mid == "De" || mid == "Van" || mid == "Von" || (mid != "" && mid == mid.toLowerCase())) {
         last = mid+" "+last;
       }
     }
   }

   if (first) { return first + " " + last; }
   return last;
 }

 function updateAuthors() {
   countByAuthor = new Object();
   allAuthors = new Array();
   //   allAuthors[0] = "(no author)";
   //countByAuthor[allAuthors[0]] = 0;
   for (var i=0; i<publist.length; i++) {
     var ref = publist[i];
     var authors = ref.author;
     if (authors) {
	   
	   var list = authorStringToArray(authors);

       for (var j=0; j<list.length; j++) {
		 var obj = list[j];
		 
		 // Normalise to A Other 
		 var author = normaliseAuthorObj(obj);
		 if (author) {
		   if (!countByAuthor[author]) { 
			 allAuthors[allAuthors.length] = author; 
			 countByAuthor[author] = 0;
		   }
		   countByAuthor[author]++;
		 }
       }
     }
   }

   // Sort the author list.
   allAuthors.sort(function(a,b) { 
		  var la = lastName(a).toLowerCase();
		  var lb = lastName(b).toLowerCase();
		  if (la < lb) { return -1; }
		  if (la > lb) { return 1; }
		  return (a > b);
		});
   
   // Update the list.
   var el = document.getElementById("authorslist");
   var txt = "";
   if (allAuthors.length > 0) {
     el.style.display = "block";
     txt += "<h4>Authors</h4>";
     for (var i=0; i<allAuthors.length; i++) {
       var author = allAuthors[i];
       if (author != "") {
		 var count = countByAuthor[author];
		 var cstr = (count==1) ? "" : "&nbsp;("+count+")";
		 var hauthor = author.replace(" ", "&nbsp;");
		 if (i!=0) { txt += ",&nbsp;&nbsp; "; }
		 txt += "<a class='aauthor' href='javascript:showAuthors("+i+")'>"+hauthor+"</a>"+cstr+"";
       }
     }
     var div = document.createElement("div");
	 //     div.style.fontSize = "70%";
     div.innerHTML = txt;
     removeChildren(el);
     el.appendChild(div);
   }
   else {
     el.style.display = "none";
   }
 }


 function countSelected() {
   if ((editmode != "indexsel") && (editmode != "edit" || readonly)) { return; }
   selectedCount = 0;
   for (var i=0; i<publist.length; i++) {
     var checked = isChecked(i);
     if (checked) {
       selectedCount ++;
     }
   }

   var el = document.getElementById('selectops');
   if (selectedCount == 0) {
     // Hide the delete /export box.     
     el.style.display = "none";
   }
   else {
     // Show the delete /export box.
     el.style.display = "block";

     //     alert("Recounting - got "+selectedCount);
     var selcountid = document.getElementById('selcountid');
     var txt =  ""+selectedCount+" item";
     if (selectedCount>1) { txt+="s"; }
     selcountid.innerHTML = txt;
   }
 }

 function selectAll() {
   for (var i=0; i<publist.length; i++) {
     var check = document.getElementById("check"+i);
     if (check && !check.checked) {
       check.checked = true;
       toggleChecked(i, true);
     }
   }
   countSelected();
 }

 function selectNone() {
   for (var i=0; i<publist.length; i++) {
     var check = document.getElementById("check"+i);
     if (check && check.checked) {
       check.checked = false;
       toggleChecked(i, true);
     }
   }
   countSelected();
 }

 function selectByTag(tag) {
   var lctag = tag.toLowerCase();
   selectNone();

   var firstnum = -1;
   for (var i=0; i<publist.length; i++) {
     var ref = publist[i];
     var tags = trim(ref.tags.toLowerCase());
     var match = false;
     if (lctag == "(no tag)" && tags == "") {
       match = true;
     }
     else if (tags.indexOf(lctag) != -1) {
       var list = splitTags(tags);
       for (var j=0; j<list.length; j++) {
	 if (lctag == trim(list[j])) {
	   match = true;
	 }
       }
     }
     if (match) { 
       if (firstnum==-1) firstnum = i;
       var check = document.getElementById("check"+i);
       if (check) {
	 check.checked = true;
       }
       toggleChecked(i, true);
     }
   }
   countSelected();
   if (firstnum != -1) {	
	 jumpAnchor("#refno"+(firstnum));
   }
 }

 function selectByAuthor(author) {
   var lastauthor = lastName(author.toLowerCase());
   var nauthor = normaliseAuthor(author);

   selectNone();

   var firstnum = -1;
   for (var i=0; i<publist.length; i++) {
     var ref = publist[i];
     var authors = ref.author;
     if (authors) {
       var lauthors = authors.toLowerCase();
       var match = false;

       if (lauthors.indexOf(lastauthor) != -1) {
		 var list = authorStringToArray(authors);

		 for (var j=0; j<list.length; j++) {	 
		   if (nauthor == normaliseAuthorObj(list[j])) {
			 match = true;
		   }
		 }
       }
       if (match) { 
		 if (firstnum==-1) firstnum = i;
		 var check = document.getElementById("check"+i);
		 if (check) {
		   check.checked = true;
		 }
		 toggleChecked(i, true);
       }
     }
   }
   countSelected();
   //   alert("Done sel by author "+author);
   if (firstnum != -1) {
	 jumpAnchor("#refno"+(firstnum));
   }
 }

// Jump to anchor on same page
function jumpAnchor(a) {
  var oldloc = "" + document.location;
  var hpos = oldloc.indexOf("#");
  if (hpos != -1) {
	oldloc = oldloc.substring(0, hpos);
  }
  document.location = oldloc + a;
}

 function hideHighlight(i) {
   var refdiv = document.getElementById("refdiv"+i);
   refdiv.className = "refdiv";
 }

 function showHighlight(i) {
   var refdiv = document.getElementById("refdiv"+i);
   //   var check = document.getElementById("check"+i);
   if (isChecked(i)) {
     refdiv.className = "refdiv selref";
   }
   else {
     refdiv.className = "refdiv";
   }
 }


// Get reference for given user.
function getRefHtml(i, ref, expanded, user) {
   txt = "";

   // format : 123 or a.n.other-123
   var fullid = ref.refid;
   
   if (!user) {
     user = userid;
   }

   /*
   else {
     // Full id: includes user.
     fullid = user +"-"+ref.refid;
   }
   */   

   var sty = (editmode=='preview') ? "display:none" : "";

   var selected = selectedById[fullid];
   var seltxt = selected ? " checked='1' " : "";

   var chksty = ((editmode=="edit" && !readonly) || editmode=="indexsel") ? "" : "display:none";

   txt = "<input style='float: right; border:none; "+chksty+"' id='check"+i+"' type='checkbox' "+seltxt+" onclick='toggleChecked("+i+", false)'>";



   // Add an expand / collapse control.
   //txt += "<div style='float:left; margin-left:-2em; margin-top: -0.3em; z-index:100'>";
   txt += "<div style='float:left;'>";
   if (!expanded) {
	 txt += "<a href='javascript:expandRef("+i+")' title='Show details'><img src='"+rootpath+"laf/triangle-sml.png' /></a>";
   }
   else {
     txt += "<a href='javascript:collapseRef("+i+")' title='Hide details'><img src='"+rootpath+"laf/triangle-sml-down.png'/></a>";
   }
   txt += "</div>";

   // white border gets around Safari layout bug.
   txt += "<a name='refno"+i+"' style='position:relative; top: -80px'></a><a name='refid"+fullid+"' style='position:relative; top: -80px'></a><div id='refdiv"+i+"' style='border:1px solid white; margin-left:2em;'";
   
   if (selected) {
     txt += " class='refdiv selref'>";
   }
   else {
     txt += " class='refdiv'>";
   }

   if (!readonly) {
	 var vis = "visibility:hidden;";
	 if (true || expanded) {
	   vis = "visibility:visible;";
	 }
	 
	 txt += "<div id='editref"+i+"' class='flright' style='float:right; "+vis+" padding-left:3em; "+sty+"'><a title='Edit reference' href='editRef.php?refid="+ref.refid+"'><img alt='edit' src=\""+rootpath+"edit-sml.png\"/></a>&nbsp;&nbsp;<a href='javascript:maybeDelete("+ref.refid+")' title='Delete reference'><img alt='delete' src=\""+rootpath+"delete-sml.png\"/></a>&nbsp;&nbsp;</div>";
   }
   
 
   if (ref.doi || ref.urllink || ref.pdflink || ref.attachment || ref.pubmed) {
   }
   else {
     if (!readonly) { 
       var sty = (editmode=='preview') ? "display:none" : "";

       txt += "<div id='addlink"+i+"' style='padding-left : 12px; float:right; "+sty+"'><a title='No full text link yet - add it now' style='color:red; text-decoration:none;' href='editRef.php?refid="+ref.refid+"#fulltext'> <img alt='clip' src=\""+rootpath+"clip-col-sml.png\"/> </a></div>";
     }
   }

   txt += refToHtml(ref.articletype, ref, expanded, user, rootpath, i);


   // Add the duplicate tags for index.
   var key = getPaperKey(ref);
   if (key && bypaperkey) {
     var ulist = bypaperkey[key];
     if (ulist) {
       if (ulist.length > 1) {
	 txt += " <span class='dup'>[";
	 var first = true;
	 for (var k=0; k<ulist.length; k++) {
	   var duser = ulist[k];
	   if (duser != user) {
	     if (!first) { txt += ", "; } else { txt += "also in "; }
	     txt += duser+"'s list";
	     first = false;
	   }
	 }
	 if (first) {
	   txt += "duplicate entry";
	 }
	 txt += "]</span> ";
       }
     }
   } 


   if (expanded && !noexport) {
     var refid = publist[i].refid;
     txt += "<div style='clear:right; float:right; padding:1em; font-size:8pt;'>";
     txt += "<a target='_blank' href='"+rootpath+"php/exportRef.php?u="+user+"&refid="+refid+"&fmt=bibtex'>bibtex</a> | ";
     txt += "<a target='_blank' href='"+rootpath+"php/exportRef.php?u="+user+"&refid="+refid+"&fmt=endnote'>endnote</a> | ";
     txt += "<a target='_blank' href='"+rootpath+"php/exportRef.php?u="+user+"&refid="+refid+"&fmt=ris'>procite (RIS)</a> | ";
     txt += "<a target='_blank' href='"+rootpath+"php/exportRef.php?u="+user+"&refid="+refid+"&fmt=isi'>ISI</a> | ";
     txt += "<a target='_blank' href='"+rootpath+"php/exportRef.php?u="+user+"&refid="+refid+"&fmt=xml'>XML</a> ";
     txt += "</div><div style='clear:right'></div>\n";
   }   


   // If _userids set, show links back to publists.
   if (expanded && publist[i]._publists) {
     var lists = publist[i]._publists;
     txt += "<div style='text-align:right; margin-bottom:3em; margin-right:4em; font-style:italic; color:#a0a0a0;'>From the publications list"; 
     if (lists.length>1) { txt += "s"; }
     txt += " of: ";
     for (var j=0; j<lists.length; j++) {
       if (j!=0) { txt += "; "; }
       txt += "<a target='_blank' href='"+rootpath+lists[j].userid+"#refid"+lists[j].refid+"'>"+lists[j].userid+"</a> ";
     }
     txt += "</div>"; // <div style='clear:right'> </div>";
   }

   txt += "</div>"; // refdiv

   return txt;
 }


/* --- other display modes not used.

 function displayOrigOrder(div) {
   for (var i=0; i<publist.length; i++) {
     var ref = publist[i];
     var el = document.createElement("div");
     el.className = "publication";
     el.id = "list"+i;
     
     txt = getRefHtml(i, ref, false);
     el.innerHTML = txt;
     div.appendChild(el);
   }   
 }

 function displayByYear(div) {
   var byyear = new Object();
   var keys = new Array();
   for (var i=0; i<publist.length; i++) {
     var ref = publist[i];
     var year = "- no year specified -";

     if (ref.year) {
       year = ref.year; // could get 1st 4 chars
     }
     else {
       //  alert("strange year "+ref.year);
     }
     
     if (!byyear[year]) {
       byyear[year] = new Array();
       keys[keys.length] = year;
       // alert("got a year "+year + " keys length "+keys.length);
     }
     byyear[year][byyear[year].length] = i;         
   }
   keys.sort();


   for (var y = keys.length-1; y>=0; y--) {
     var el = document.createElement("h2");
     el.className='yeartitle';
     div.appendChild(el);
     var year = keys[y];    
     el.innerHTML = year;
     //alert("Got year "+year);
     var subdiv = document.createElement("div");
     subdiv.className = 'yearindent';
     div.appendChild(subdiv);

     for (var i=0; i<byyear[year].length; i++) {
       var el = document.createElement("div");
       el.className = "publication";
       var pli = byyear[year][i];
       var ref = publist[ pli ];
       el.id = "list"+pli;
       txt = getRefHtml(pli, ref, false);
       el.innerHTML = txt;
       subdiv.appendChild(el);
     }
   }      
 }

*/

// Get a key for a paper.
function getPaperKey(ref) {
  var ret = "";
  ret += trim(ref.year)+"-";
   
  // Try for volume * pages match...
  if (ref.volume && ref.pages) { 
	if (ref.volume) {
	  ret += trim(ref.volume)+"-";
	}
	if (ref.number) {
	  ret += trim(ref.number)+"-";
	}
	if (ref.pages) {
	  ret += trim(ref.pages)+"-";
	}
  }
  else {
	if (ref.author) {
	  var list = authorStringToArray(ref.author.toUpperCase());
	  for (var j=0; j<list.length; j++) {
		var obj = list[j];
		var astr = normaliseAuthorObj(obj);
		if (astr) {
		  ret += astr.toLowerCase()+"-";
		}
	  }
	}

	if (ref.title) {
	  // Remove '-' characters....
	  var t2 = ref.title;
	  if (t2.indexOf("-")!=-1) {
		t2 = t2.replace("-", " ");		
	  }
	  ret += trim(t2).toLowerCase()+"-";
	}
	else if (ref.booktitle) {
	  ret += trim(ref.booktitle).toLowerCase()+"-";
	}
	if (ref.journal) {
	  ret += trim(ref.journal).toLowerCase()+"-";
	}
  }

  return ret;
}

// paper key -> list of users.
var bypaperkey = false;



// Global vars for callback.
// var worklist = false;
// var workstart = 0;
var batchsize = 10;
var workdelay = 10;

function displaycb() {
  if (worklist) {
    //  alert("Doing ref "+workstart+" to "+(workstart + batchsize));
    for (var k=workstart; k<worklist.length && k < workstart+batchsize; k++) {
      var work = worklist[k];
      var pli = work["pli"];
      var ref = work["ref"];
      var el = work["el"];
      var user = work["user"];
      var key = work["key"];
      var txt = getRefHtml(pli, ref, false, user);
    
      el.innerHTML = txt;
    }

    workstart += batchsize;
    if (workstart < worklist.length) {
      setTimeout(displaycb, workdelay);
    }
    else {
      worklist = false;
      countSelected(); // update it...
    }
  }
}

 function displayByType(div) {
   displayRangeByType(div, 0, publist.length, true);
 }

// Display a range of pubs from publist
function displayRangeByType(div, startpli, endpli, doreset) {
   var bytype = new Object();
   var keys = new Array();
   
   if (doreset || (typeof(worklist) == "undefined") || worklist === false) {
	 worklist = new Array();
	 workstart = 0;
   }
   
   // Order of sections.   
   var inits = ["book", "article", "inbook", "inproceedings"];
   for (var i=0; i<inits.length; i++) {
     var dtype = getDisplayType(inits[i]);
     keys[i] = dtype;
     bytype[dtype] = new Array();
   }
   keys[0] = getDisplayType("book");
   keys[1] = getDisplayType("article");
   keys[2] = getDisplayType("inbook");
   keys[3] = getDisplayType("inproceedings");

   for (var i=startpli; i<endpli; i++) {
     var ref = publist[i];
     var atype = "misc";

     if (ref.articletype) {
       atype = ref.articletype;
     }
     var dtype = getDisplayType(atype);
     if (atype == "misc" && ref.sectionheading) {
       dtype = ref.sectionheading;
     }
     
     if (!bytype[dtype]) {
       bytype[dtype] = new Array();
       keys[keys.length] = dtype;
     }
     bytype[dtype][bytype[dtype].length] = i;         
   }
  
   // Main table for pubs.
   var tbl = document.createElement("table");
   tbl.style.width = "95%"; // 100% no good for IE
   tbl.style.tableLayout = "fixed";
   div.appendChild(tbl);
   
   var tr = tbl.insertRow(-1);
   var td = tr.insertCell(-1);
   td.style.width='40px';
   var td = tr.insertCell(-1);

   // Start vertical label after 6 publications and continue for 4.
   var typerepeat = 6;
   var typespace  = 4; 

   for (var t = 0; t<keys.length; t++) {
     var el = document.createElement("h2");
     el.className='yeartitle';
     var dtype = keys[t];    

	 // Article type.

     if (bytype[dtype].length > 0) {
	   var tr  = tbl.insertRow(-1);
	   var td = tr.insertCell(-1);
	   td.colSpan = "2";
	   //td.style.width="auto";
       el.innerHTML = dtype;
       td.appendChild(el);

	   	   	   
	   var tr = tbl.insertRow(-1);
	   var td = tr.insertCell(-1);
       td.style.width="100px";
       var subdiv = document.createElement("div");
       subdiv.className = 'yearindent';
       td.appendChild(subdiv);
       
       var ret = sortWithinByYear(bytype[dtype]);
       
       var prevy = "";

       var typeidx = 0; // counter for vert label

       for (var i=0; i<ret.length; i++) {
		 var el = document.createElement("div");
		 el.className = "publication";
		 var pli = ret[i];
		 var ref = publist[ pli ];
		 el.id = "list"+pli;
		 var txt = "";
		 
		 typeidx ++;
		 if (typeidx == typerepeat && i < ret.length - typespace) {
		   // Add a vertical 'journal articles' label
		   var tr = tbl.insertRow(-1);
		   var td = tr.insertCell(-1);
		   var vdiv = document.createElement("div");
		   vdiv.style.position = "relative";
		   vdiv.style.height = "0px";
		   td.appendChild(vdiv);
		   var img = imagesByType[ref.articletype];
		   // alert(img);
		   vdiv.innerHTML = "<div style='position : absolute; left:-50px; z-index : 0'><img class='ja' title='"+dtype+"' src='"+rootpath+img+"'/></div>";
		   
		   typeidx = -typespace;
		 }
		

		 var tr = tbl.insertRow(-1);
		 var td = tr.insertCell(-1);

         if (ref.year != prevy) {
             var ydiv = document.createElement("div");
		     ydiv.className = "yearsep";
		     ydiv.innerHTML = ref.year;		   
		     td.appendChild(ydiv);			 
		     td.style.verticalAlign="top";
             prevy = ref.year;
         }

		 var td = tr.insertCell(-1);
		 td.appendChild(el);
		 td.id = "td-"+pli;
		 
		 var workuser = userid;
		 if (ref.userid) {
		   workuser = ref.userid;
		 }

		 worklist[worklist.length] = {"pli":pli, "ref":ref, "subdiv":subdiv, "el":el, "user":workuser};
       }
     }
   } 
     
   // Draw the refs on callback.
   displaycb();
   // setTimeout(displaycb, workdelay);
 }


 // Sort within an indexed array by fld.
 function sortWithinByYear(ary) {
   var ret = new Array();
   for (var i=0; i<ary.length; i++) {
     ret[i] = ary[i];
   }
   
   ret.sort(function(a,b) { 
	      var y1 = publist[a].year;
	      var y2 = publist[b].year;
	      if (y1 > y2) { return -1; }
	      if (y1 < y2) { return 1; }
	      return 0;
	    });
   return ret;
 }

var displayMode = "type";

function authorInfo() {
    var txt = '';
	if (mode == "publish") { return ""; } // Don't display help info
    txt += '<h2>About you</h2>';
    txt += "<p><i>The 'Author details' section lets you add your work address, home page and ";
	txt += "other biographical information."; 
    txt += '</i></p>';
    return txt;
}


// Filter a publications list by tag.
// Returns a shorter list with only the matching elements.
function filterByTag(plist, mtag) {
  var ret = new Array();
  for (var i=0; i<plist.length; i++) {
	var el = plist[i];

	// Do the tags match?
	var t = el["tags"];
	var l = splitTags(t);
	var found = false;

	for (var j=0; j<l.length && !found; j++) {
	  var tag = trim(l[j]);  
	  if (tag) {
		if (tag.toLowerCase() == mtag.toLowerCase()) {
		  found = true;
		}
	  }
	}
	if (found) {
	  ret[ret.length] = el;
	}
  }
  return ret;
}


function display() {
    var div = document.getElementById('publistdiv');
    if (div) {
      removeChildren(div);
    }

    var txt = '';
    if (!publist || publist.length==0) {
      txt = "&nbsp;";      
      if (!readonly) {

	var firstname = trim(details["firstname"]);
	var lastname = trim(details["lastname"]);
	var lookup = firstname+"_"+lastname;
    txt = '<h2>Welcome to ' + publistBrand + '</h2>';
	txt += "<div id='clickhelpid'><br/><p><i>";

	txt += "Click the '<b>Add a paper</b>' button above to enter details for your publications ";
	txt += "or import citation information from Bibtex, Endnote, Reference Manager, PubMed ";
	txt += "and other formats. The <b>Author details</b> button lets you add a bio sketch and contact details.</p><p>Whenever you're ready to make your list public, click the green <b>Publish</b> button above which will generate a public web page.</p>";
	
	txt += "<br/><br/>You can also search the author index for <a target='_blank' href='"+rootpath+"php/authors.php?a="+lookup+"'>"+firstname+" "+lastname+"</a> to check if your co-authors have already added some of your publications for you to add to your list.";

	txt += "<br/><br/><h4>PubMed users</h4><p>Biomedical researchers can <a href='pubmed.php'>lookup publications on PubMed using the integrated search page</a> and import selected papers. See also the 'pubmed' link in the top right.</p>";


	txt += "<br/><br/><h4>Importing from Web of Science</h4><p>If you have access to the web of science database through your institution, you can search it and import your publications <a target='_blank' href='http://publicationslist.org/import-web-of-science.html'>more details...</a></p>";
  if (!localInstall) {
    txt += "<br/><br/><h4>Upgrading your account</h4><p>You can edit your account settings on your <a href='order.php'>Account page</a> - this includes options for upgrading to PublicationsList professional and joining your <a target='_blank' href='../groupaccount.html'>research group's account.</a></p>";
  }


	txt += "</p></div>";
      }
	  else {
		if (!publist) {
		  txt = "<b>Publications list not available</b>";
		}
	  }
      var el = document.createElement("div");
      el.innerHTML = txt;
      div.appendChild(el);
    }
    else {
      if (displayMode=="type") {
	displayByType(div);
      }
      else {
	displayByYear(div);
      }
    }
}

 function updateControls(mode) {
   var el = document.getElementById("controlsid");
   var txt  = "";
   var div = document.createElement("div");
   txt = "Arrange by ";
   if (mode != "date") {
     txt += "<a class='control' href='javascript:setDateMode()'>date</a> |  ";
   }   
   else {
     txt += "<b>date</b> |  ";
   }

   if (mode != "type") {
     txt += "<a class='control' href='javascript:setTypeMode()'>article type</a> | ";
   }   
   else {
     txt += "<b>article type</b>  ";
   }

   if (mode != "both") {
     txt += "<a class='control' href='javascript:setBothMode()'>type and date</a> ";
   }   
   else {
     txt += "<b>type and date</b>  ";
   }

   div.innerHTML = txt;
   removeChildren(el);
   el.appendChild(div);
 }

 function setDateMode() {
   displayMode = "date";
   updateControls(displayMode);
   display();
 }

 function setBothMode() {
   displayMode = "both";
   updateControls(displayMode);
   display();
 }

 function setTypeMode() {
   displayMode = "type";
   updateControls(displayMode);
   display();
 }

function setDetailField(field) {
  if (details[field]) {
    var el = document.getElementById(field+'id');
    if (el) {
	  var txt = details[field];

	  /* Nastiness because IE innerhtml is broken */
	  txt = txt.replace(/\n/g, "<br/>"); 
	  txt = txt.replace(/\r/g, ""); 

	  el.innerHTML = txt;
    }
    else {
      alert(field+" not found");
    }
  }
}


 var editmode = "edit";

 // toggle display of edit controls.
 function toggleEdits(mode) {
   document.getElementById('editlinksid').style.display=mode;
   document.getElementById('selectid').style.display=mode;
   var clickhelp = document.getElementById('clickhelpid');
   if (clickhelp) { clickhelp.style.display=mode; }

   for (var i=0; i<publist.length; i++) {
	 // Don't hide edit controls
	 //     document.getElementById('editref'+i).style.display=mode;
     var lel = document.getElementById('addlink'+i);
     if (lel) { lel.style.display=mode; }
     var cel = document.getElementById('check'+i);
     if (cel) { cel.style.display=mode; }

     if (mode=='block') { showHighlight(i); } else { hideHighlight(i); }
   }   
 }

 function edit() {
   editmode = "edit";
   editControls();
   toggleEdits("block");
   countSelected();
 }

 function preview() {
   editmode = "preview";
   document.getElementById("selectops").style.display="none";
   editControls();
   selectedById = new Object(); // zap selections.
   toggleEdits("none");
 }

 function editControls() {
   return;
   if (ownpage) {
     var el = document.getElementById('editbuttons');
     removeChildren(el);
     var div = document.createElement("div");
     var txt = "";
     if (editmode == "edit") {
       txt = "<div class='selbutton'>Edit</div>&nbsp;&nbsp;<a class='unselbutton' href='javascript:preview()'>Preview</a>&nbsp;&nbsp;<a class='unselbutton' target='_blank' href='publist.php?u="+userid+"&m=publish'>Publish</a>";
     }
     else if (editmode == "preview") {
       txt = "<a class='unselbutton' href='javascript:edit()'>Edit</a>&nbsp;&nbsp;<div class='selbutton'>Preview</div>&nbsp;&nbsp;<a class='unselbutton'  target='_blank' href='publist.php?u="+userid+"&m=publish'>Publish</a>";
     }
     div.innerHTML = txt;
     el.appendChild(div);
   }
 }

function displayDetails() {
  if (details) {
    setDetailField("address");
    setDetailField("firstname");
    setDetailField("lastname");
    //    setDetailField("middlename");
    setDetailField("biosketch");

    if (! details.biosketch || details.biosketch.length < 2) {
        var el = document.getElementById("biosketchid");
        el.innerHTML = authorInfo();
    }


    if (details.email) {
      document.getElementById('emailid').innerHTML="<table><tr><td><img src='"+rootpath+"email-sml.png'/></td><td> "+details.email + "</td></tr></table>";
    }
    if (details.website) {
      document.getElementById('websiteid').innerHTML="<table><tr><td><img src='"+rootpath+"web-sml.png'/></td><td><a href='"+details.website+"'>Home page</a> </td></tr></table>";
    }
  }
}

 function trimWS(txt) {
     if (txt.indexOf("http://") == 0) {
         txt = txt.substr(7);
     }
     return txt;
 }



 var selectedById = new Object();


// For publish.php
function sendlink(a) {
  var ael = document.getElementById("auth"+a);
  if (ael) {
    var aname = ael.title;
   
    var ael = document.getElementById("coinvite");
    ael.style.display="block";
      
    var n1 = document.getElementById("invitename");
    var n2 = document.getElementById("invitename2");
    var ta = document.getElementById("invitetxt");
    var em = document.getElementById("inviteemail");
    //      var il = document.getElementById("invitelink");
    var ia = document.getElementById("invitea");
    spanInnerHtml(n1, aname);
    spanInnerHtml(n2, aname);


    ta.style.width = "100%";

    ta.value = "Loading your co-publications with "+aname+" ...";      
    em.value = "";      
    var fullname = details.firstname + " "+ details.lastname;
    ia.value = a;
      
    setTimeout("sendlinkcb("+a+")", 100);
  }
}

function sendlinkcb(a) {
  var ael = document.getElementById("auth"+a);
  if (ael) {
    var aname = ael.title;
   
    var txt = postURL("sendLink.php", "n="+encodeURIComponent(aname));
    
    if (txt.substring(0,3) != "ERR") {
      var ael = document.getElementById("coinvite");
      ael.style.display="block";
      
      var n1 = document.getElementById("invitename");
      var n2 = document.getElementById("invitename2");
      var ta = document.getElementById("invitetxt");
      var em = document.getElementById("inviteemail");
      //      var il = document.getElementById("invitelink");
      var ia = document.getElementById("invitea");
      spanInnerHtml(n1, aname);
      spanInnerHtml(n2, aname);
      ta.value = "";
      ta.value = txt;      
      ta.style.width = "100%";
      em.value = "";      
      var fullname = details.firstname + " "+ details.lastname;
      ia.value = a;
      
      //      il.href = "mailto:?subject=" + encodeURIComponent("[publicationslist.org] "+fullname+" has added some of your co-publications")+"&body=" + encodeURIComponent(txt);
    }
    else {
      alert(txt);
    }
  }
}

function closeinvite() {
  var bel = document.getElementById("coinvite");
  bel.style.display="none";  
}

function sendemaillink() {  
  var email = document.getElementById("inviteemail").value;
  var a = document.getElementById("invitea").value;
  var ael = document.getElementById("auth"+a);
  if (ael) {
    var aname = ael.title;
   
    //    window.prompt("Enter "+aname+"'s email address\nto send them a link to your publications list", "");
    if (email) {
      // Call a PHP to send a message.
      var ret = postURL("sendLink.php", "e="+encodeURIComponent(email)+"&n="+encodeURIComponent(aname));
      alert(ret); // "OK - Sent a link to "+email + " "+ret);
      ael.style.color = "#a0a0a0";

      closeinvite();
      
    }
  }
}
//
// Utils for group publications list
//

var recent = false;
var readonly = true;
var editmode = "index"; 
//if (userid) { editmode = "indexsel"; }

var publist = new Array();

var batchsize = 20;
var workdelay = 5;


if (typeof(target_div) == "undefined" || !target_div) {
  target_div = "publistdiv"; // by default.
}

function groupdisplaycb() {
  if (worklist) {
    for (var k=workstart; k<worklist.length && k < workstart+batchsize; k++) {
      var work = worklist[k];
      var pli = work["pli"];
      var ref = work["ref"];
      var el = work["el"];
      var user = work["user"];
      var key = work["key"];
      var txt = getRefHtml(pli, ref, false, user);    

	  //	  if (k==0) { alert(txt); }
      el.innerHTML = txt;
    }

    workstart = k; // was += batchsize;
    if (workstart < worklist.length) {
      setTimeout(groupdisplaycb, workdelay);
    }
  }
}

//
// Initialise group list - zap it.
//
function initGroupList() {
  publist = new Array();
  worklist = new Array();
  workstart = 0;
  bypaperkey = new Object(); // paper key -> array of user names.

  var ilist = document.getElementById(target_div);
  removeChildren(ilist);
}


var groupyearidx = 1;
var groupyearlist = false;

// Display a list of years in background.
function displayGroupYears(groupyears) {
  groupyears.sort();
  if (typeof(year_filter)!="undefined" && year_filter.length > 0) {
    var y2 = new Array();
    for (var i=0; i<groupyears.length; i++) {
      var found = false;
      for (var j=0; j<year_filter.length; j++) {
	if (0 + groupyears[i] == 0 + year_filter[j]) {
	  found = true;
	}
      }
      if (found) {
	y2[y2.length] = groupyears[i];
      }
    }
    groupyears = y2;
  }
  
  if (groupyears.length > 0) {
    groupyearlist = groupyears;
    groupyearidx = groupyearlist.length - 1;
    setTimeout(displayNextGroupYear, 10);
  }
  else {
    noneFound();
  }
}

// Pop the next group year off the stack
function displayNextGroupYear() {
  if (groupyearidx >= 0) {
    // fetch the js for the year.
    var scr = document.createElement("script");
    scr.src = rootpath+"data/groups/"+groupid+"/publist_"+groupyearlist[groupyearidx]+".js";
    document.body.appendChild(scr); // ... load it...
  }  
}

// Callback from group publications for a year
function yearPublistLoaded(year, publist_year) {
  displayGroupListForYear(year, publist_year);

  // After posting the display, load the next lot...
  groupyearidx --;
  if (groupyearidx >=0) {
    setTimeout(displayNextGroupYear, 100);
  }  
  else {
    // Check if we've actually displayed any...
    if (worklist.length == 0) {
      noneFound();
    }
  }
}

function noneFound() {
  var ilist = document.getElementById(target_div);
  var div = document.createElement("div");
  div.innerHTML = "<i>No publications found</i>";
  ilist.appendChild(div);
}

// Display the list for a given year
// byauthor: map of author to list for that year
function displayGroupListForYear(year, byauthor) {
  var lcfilter = tag_filter.toLowerCase();
  var ilist = document.getElementById(target_div);

  var atitle = document.createElement("div");
  if (typeof(no_year_headings) != "undefined" && no_year_headings) {} else {
  str = "";
  str += "<a name='Y"+year+"'></a>";
  var yname = ""+year;
  str += "<h2 class='layout'>"+yname.toLowerCase()+"</h2>";
  atitle.innerHTML = str;
  }
  
  // delay appending year until sure
  var doneyear = false; 
    
  for (var user in byauthor) {
    var ulist = document.createElement("div");
    ulist.className="indexpad";
    str = "";
    var utitle = document.createElement("div");
    
    
    var subdiv = document.createElement("div");
    subdiv.className = "noindexsub";
    
    var list = byauthor[user];
    
    utitle.innerHTML = str;

    var doneuser = false; // delay appending 
    ulist.appendChild(utitle);
    ulist.appendChild(subdiv);
    
    for (var i=0; i<list.length; i++) { 
      var ref = list[i];
      
      // Check for keyword filter match
      var kwmatch = true;
      if (lcfilter != "") {
	var kw = ref.tags;
	if (!kw) {
	  kwmatch = false;
	}
	else if (kw.toLowerCase().indexOf(lcfilter) == -1) {
	  kwmatch = false
	    }
      }
      
      // Check for duplicates...
      var key = getPaperKey(ref);
      var ary = bypaperkey[key];
      if (kwmatch) {
	if (!ary) {
	  if (!doneyear) {
	    ilist.appendChild(atitle);
	    doneyear = true;
	  }
	  if (!doneuser) {
	    ilist.appendChild(ulist);
	    doneuser = true;
	  }
	  
	  // First occurence of this paper
	  ary = new Array();
	  bypaperkey[key] = ary;
	  
	  var pli = publist.length;
	  publist[pli] = ref;
	  
	  var el = document.createElement("div");
	  el.id = "list"+pli;
	  el.className="indexref";
	  
	  ref.refid = user + "-" + ref.refid;
	  ref.userid = user;
	  subdiv.appendChild(el);
	  
	  // key is paper key...
	  worklist[worklist.length] = {"pli":pli, "ref":ref, "el":el, "user":user, "key":key};
	}
	else {
	  // Duplicate found... just log it.
	  ary[ary.length] = user;
	}
      }
    }
  }
  
  groupdisplaycb();
}


//
// Display the group list
//
function displayGroupList(byyear) {
  var str = "";
  publist = new Array();

  // Do painting later.
  worklist = new Array();
  workstart = 0;

  bypaperkey = new Object(); // paper key -> array of user names.

  var ilist = document.getElementById(target_div);
  removeChildren(ilist);

  var yearlist = new Array();
  for (var year in byyear) {
    yearlist[yearlist.length] = year;
  }
  yearlist.sort();
  
  var lcfilter = tag_filter.toLowerCase();

  for (var yi=yearlist.length - 1; yi >=0; yi--) {
    var year = yearlist[yi];
    var byauthor = byyear[year];

    var atitle = document.createElement("div"); 
    if (typeof(no_year_headings) != "undefined" && no_year_headings) {} else {
    str = "";
    str += "<a name='"+year+"'></a>";
    var yname = year.substring(1);
    str += "<h2 class='layout'>"+yname.toLowerCase()+"</h2>";
    atitle.innerHTML = str;
    }

    // delay appending year until sure
    var doneyear = false; 

    //   ilist.appendChild(atitle);

    for (var user in byauthor) {
      var ulist = document.createElement("div");
      ulist.className="indexpad";
      str = "";
      var utitle = document.createElement("div");

      // str += "<span class='layout'>From <a class='layout' href='/"+user+"'>"+user+"'s list</a></span>";

      var subdiv = document.createElement("div");
      subdiv.className = "noindexsub";

      var list = byauthor[user];
               
      utitle.innerHTML = str;
      // ilist.appendChild(ulist);
      var doneuser = false; // delay appending 
      ulist.appendChild(utitle);
      ulist.appendChild(subdiv);
	  
      for (var i=0; i<list.length; i++) { 
	var ref = list[i];

	// Check for keyword filter match
	var kwmatch = true;
	if (lcfilter != "") {
	  var kw = ref.tags;
	  if (!kw) {
	    kwmatch = false;
	  }
	  else if (kw.toLowerCase().indexOf(lcfilter) == -1) {
	    kwmatch = false
	  }
	}

	// Check for duplicates...
	var key = getPaperKey(ref);
	var ary = bypaperkey[key];
	if (kwmatch) {
	  if (!ary) {
	    if (!doneyear) {
	      ilist.appendChild(atitle);
	      doneyear = true;
	    }
	    if (!doneuser) {
	      ilist.appendChild(ulist);
	      doneuser = true;
	    }

	    // First occurence of this paper
	    ary = new Array();
	    bypaperkey[key] = ary;
	    
	    var pli = publist.length;
	    publist[pli] = ref;
	    
	    var el = document.createElement("div");
	    el.id = "list"+pli;
	    el.className="indexref";
	    
	    ref.refid = user + "-" + ref.refid;
	    ref.userid = user;
	    subdiv.appendChild(el);
	    
	    // key is paper key...
	    worklist[worklist.length] = {"pli":pli, "ref":ref, "el":el, "user":user, "key":key};
	  }
	  else {
	    // Duplicate found... just log it.
	    ary[ary.length] = user;
	  }
	}
      }
    }
  }

  if (worklist.length == 0) {
    var el = document.createElement("div");
    el.style.margin = "2em";
    el.innerHTML = "No references found.";
    ilist.appendChild(el);
  }

  displaycb();

}




//
// Embed a group publications list in another page.
//
// Info on: http://publicationslist.org
//
// (c) 2007 Textensor Limited, www.textensor.com
//

var readonly = '1';

//
// *** Set the root path to publicationslist.org for deploy !!! ***
//
var rootpath = "http://publicationslist.org/"; 
//var rootpath = "http://localhost/Publist2/"; 
var ownpage = '';

var mode = 'publish';

if (typeof(userid) == "undefined") {
  userid = ''; // unknown user
 }

// Find the target div to embed into.
var target_div_el = document.getElementById(target_div);
if (!target_div_el) {
  target_div_el = document.createElement("div");
  document.body.appendChild(target_div_el); 
}
 else {
   removeChildren(target_div_el);
 }


