// ==UserScript==
// @name          del.icio.us index
// @namespace	http://fg-180.katamayu.net/userscripts
// @description   Add index of your del.icio.us bookmark
// @include       http://del.icio.us/*
// ==/UserScript==

(function () {
   var ignorePaths = ['network'];

   // margin top and bottom of alphabets list(px)
   var listMargin = 20;

   //---------------------------------------------------------------------

   function firstLetter(tag) { 
     if (!tag) {
       return '';
     } else {
       var l = tag.textContent.substr(0, 1).toUpperCase();

       if (l.charCodeAt(0) < 'A'.charCodeAt(0)) return '#';
       else if (l.charCodeAt(0) > 'Z'.charCodeAt(0)) return '@';
       else return l;
     }
   }

   function getTags(xpath) {
     var result = [];
     var tags = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);
     var t;
     while(t = tags.iterateNext()) result.push(t);
     return result;
   }

   function unique(list, pred) {
     var result = [];
     for (var i = list.length - 1; i >= 0; i--) {
       if (pred(result[0]) == pred(list[i])) result[0] = list[i];
       else result.unshift(list[i]);
     }
     return result;
   }

   function forEach(list, proc) {
     for (var i = 0; i < list.length; i++) proc(list[i]);
   }

   // thanks http://diveintogreasemonkey.org/patterns/add-css.html
   function addGlobalStyle(css) {
     var head, style;
     head = document.getElementsByTagName('head')[0];
     if (!head) { return; }
     style = document.createElement('style');
     style.type = 'text/css';
     style.innerHTML = css;
     head.appendChild(style);
   }

   //---------------------------------------------------------------------

   for (var i = 0; i < ignorePaths.length; i++) {
     if (location.href.indexOf("http://del.icio.us/" + ignorePaths[i]) == 0) return;
   }

   var tags = unique(getTags("id('sidebar')/div/ul/li[3]/ul/li/a"), firstLetter);

   if (tags.length == 0) return;

   var ul = document.createElement('ul');
   ul.id = 'tag_index';

   forEach(tags, function (tag) {
     var li = document.createElement('li');
     li.appendChild(document.createTextNode(firstLetter(tag)));

     li.addEventListener('click', function () { 
       var elm = tag;
       var top = 0;
       do { 
         top += elm.offsetTop;
         elm = elm.offsetParent;
       } while (elm);

       window.scrollTo(0, top);
     }, false);

     ul.appendChild(li);
   });

   document.body.wrappedJSObject.appendChild(ul);

   ul.style.listStyleType = 'none';
   ul.style.textAlign = 'center';
   ul.style.marginTop = listMargin + 'px';
   ul.style.marginBottom = listMargin + 'px';
   ul.style.right = 0;
   ul.style.top = 0;

   var onResize = function () {
     var margin = Math.round((window.innerHeight - listMargin * 2 - ul.firstChild.offsetHeight * tags.length) / tags.length);
     if (margin < 0) {
       ul.style.position = 'absolute';
       margin = 0;
     } else {
       ul.style.position = 'fixed';
     }

     addGlobalStyle('#tag_index li { margin-bottom: ' + margin + 'px; cursor: pointer; color: #555; }');
   }

   window.addEventListener('resize', onResize, false);

   onResize();

 })();
