String.prototype.trim = function(){ return this.replace(/^\s+|\s+$/g,'') }

var feed_url = "http://feeds.delicious.com/v2/json/"

var del_itemsData = [], del_relTagsData = {}, del_cloudTagsData = {}, g_del_help_docElement, g_del_help_navFN, g_del_helpSectionsDIV, g_del_helpCurShowing, g_del_moreCurShowing;

var del_clouds_tagcounts_hash = [], del_clouds_tagElsByTagCounts = [], del_clouds_maxTags = 0; del_clouds_tagcounts_CutOff = 0; del_rel_tagcounts_hash = [] // later may need more of these for the fontsize lookups as well; in case re-render after loading

var g_del_allTags = []

var g_del_relTagCount = 0;  // we'll use this as a hack to centralise the range of tag 'sizes' when there are a lot of related tags

function del_toggleShowMainContent(id){


    var el = document.getElementById(id)
      
    if (el.className == id + ' linksshowing'){
        el.className = id + ' linkshidden'
    }else{
        el.className = id + ' linksshowing'
    }
}


var g_haveNotShownSearchYet = 1

function toggleMoreOptions(idspecial){

    var id = idspecial ? idspecial : 'tagviewer'

    if (id != 'tagviewer'){
        alert('Sorry, the extra options for the main tag cloud are not yet implemented (July 25 2006).')
        return 0;
    }
    
    if (g_del_helpCurShowing) del_toggleShowHelp() // hide help before showing more options

    var optionsEl = getTagsByClassInObjByID(id, 'div', 'del_moreoptions', 1)
    var relatedEl = getTagsByClassInObjByID(id, 'div', 'relatedTags', 1)
    var optionsH3El = getTagsByClassInObjByID(id, 'h3', 'moreOptions_head', 1)
    var relatedH3El = getTagsByClassInObjByID(id, 'h3', 'relatedTags_head', 1)
    
    var newState = (optionsEl.style.display == 'none')
    
    g_del_moreCurShowing = newState
    
    if (optionsEl) optionsEl.style.display = newState ? 'block' : 'none' 
    if (optionsH3El) optionsH3El.style.display = newState ? 'block' : 'none' 
    
    if (relatedEl) relatedEl.style.display = newState ? 'none' : 'block'
    if (relatedH3El) relatedH3El.style.display = newState ? 'none' : 'block' 
    
    
    if ((newState) && g_haveNotShownSearchYet){
        ss_obj_1.kickstart();    // spiffySearch init
        g_haveNotShownSearchYet = 0
    }
    
}

function toggleBusyVContent(busy, id, related){

    var busyEl, contentEl

    if(related){
        busyEl = getTagsByClassInObjByID(id, 'div', 'tagsfetch_busy', 1)
         contentEl = getTagsByClassInObjByID(id, 'div', 'relatedTags', 1)
    }else{
        busyEl = getTagsByClassInObjByID(id, 'div', 'linksfetch_busy', 1)
        contentEl = getTagsByClassInObjByID(id, 'div', 'tagged_items', 1)
    }
    
    contentEl = document.getElementById(id) //////  ****** this is a hack -- need to resize something for dumb old IE
    
    if (busyEl){
        busyEl.style.display = busy ? 'block' : 'none'
        if (busy && (! related)){  // stretch to fit the current dimensions of the item viewing area
            busyEl.style.width = (contentEl.offsetWidth - 26) + 'px'
            busyEl.innerHTML = 'Fetching items for: <br /><br /><br />"<b>'
                + (gsys_del_pendingLinksFetch[id] ? gsys_del_pendingLinksFetch[id].split('+').join(' + ') : ' delicious account') + '</b>"'
        }
        
        if (busy && related){
            busyEl.innerHTML = 'Fetching related tags for: <br /><br /><br />"<b>' + gsys_del_pendingRelatedFetch[id].split('+').join(' + ') + '</b>"'      
        }
    }
    
    
//    if (contentEl) contentEl.style.display = busy ? 'none' : 'inherit'
  
    
}

function toggleSettings(setting, id){

    switch (setting){
        case 'show-notes' :
        
            gk_del_showNotes = ! gk_del_showNotes;
            
            var notesEls = getTagsByClassInObjByID(id, 'div', 'delicious-extended', 0), i, N = notesEls.length
            
            var newState = gk_del_showNotes ? 'block' : 'none'
            for (i=0; i<N; i++){
                notesEls[i].style.display = newState
            }
            
            break;
            
        case 'show-tags' :
            gk_del_showTags = ! gk_del_showTags;
            var tagsEls = getTagsByClassInObjByID(id, 'div', 'del_tags', 0), i, N = tagsEls.length
            var newState = gk_del_showTags ? 'block' : 'none'
            for (i=0; i<N; i++){
                tagsEls[i].style.display = newState
            }
            break;
            
        case 'new-windows' :
            gk_del_openItemsInNewWindow = ! gk_del_openItemsInNewWindow;
            var linkEls = getTagsByClassInObjByID(id, 'a', 'link-plain', 0), i, N = linkEls.length
            var newState = gk_del_openItemsInNewWindow ? '_blank' : '_self'
            for (i=0; i<N; i++){
                linkEls[i].target = newState
            }
    }

}

function fetchLinksForTag(tag, id, combining){      // will need to add id of the dom object to insert them into


    if (combining){
        g_del_Tag2 = tag
        tag = combining + '+' + tag
    }
    
    var path =  tag ? ((g_del_UserName ? g_del_UserName + '/' : '') + encodeURI(tag)) : g_del_UserName

    gsys_del_pendingLinksFetch[id] = tag
    
    
    toggleBusyVContent(1, id, 0)
    

    gsys_del_callbacks_LinksFetch[id] = function (data) {
        delete gsys_del_callbacks_LinksFetch[id];
        gotLinksData(id, data, (combining ? "'" + combining + "'" : ''));
    }
    
    fetchDelJSON(path, 'gsys_del_callbacks_LinksFetch["' + id + '"]')
    
}


function fetchRelatedForTag(tag, id, combining){


    if (combining){
        g_del_Tag2 = tag
        tag = combining + '+' + tag
    }

    var path = 'tags/' +  (g_del_UserName ? g_del_UserName + '/' : '') + encodeURI(tag)


    gsys_del_pendingRelatedFetch[id] = tag
    
    
    
    toggleBusyVContent(1, id, 1)
    
    

    gsys_del_callbacks_RelatedFetch[id] = function (data) {
        delete gsys_del_callbacks_RelatedFetch[id];
        gotRelTagsData(id, data, (combining ? "'" + combining + "'" : ''));
    }
    
    fetchDelJSON(path, 'gsys_del_callbacks_RelatedFetch["' + id + '"]')    

}

function cloudTagClicked(tag, id, idviewer, linkEl){

    fetchLinksForTag(tag, idviewer, 0)
    fetchRelatedForTag(tag, idviewer, 0)
}

function relatedTagClicked(tag, id, combining, linkEl){

    if (linkEl == gsys_del_callbacks_RelatedCombinedLinkObj[id]) combining = 0

    fetchLinksForTag(tag, id, combining)
    
    if (combining){
        hiliteCurrentCombinedTag(id, tag, linkEl)
    }else{
        fetchRelatedForTag(tag, id, 0)
    }
    
//////    fetchRelatedForTag(tag, id, combining)    //// nope - use the related tags for the main tag always as index into its relations
}

function itemTagClicked(tag, id){

    fetchLinksForTag(tag, id, 0)
    fetchRelatedForTag(tag, id, 0)

}


function mouseIntoItem(e, id, o){

//    window.status = 'Click to open ' + o.location

    if(e.altKey){
        var el = document.getElementById(id)
        el.showingDetail = true
        
        var notesEl = getTagsByClassInObjByID(id, 'div', 'delicious-extended', 1)
        var tagsEl = getTagsByClassInObjByID(id, 'div', 'del_tags', 1)
        if(notesEl) notesEl.style.display = 'block'
        if(tagsEl) tagsEl.style.display = 'block'        
    }

}

function mouseOutOfItem(e, id, o){

//    window.status = ''

    if(e.altKey){
        var el = document.getElementById(id)
        el.showingDetail = false
        
        var notesEl = getTagsByClassInObjByID(id, 'div', 'delicious-extended', 1)
        var tagsEl = getTagsByClassInObjByID(id, 'div', 'del_tags', 1)
        if(notesEl) notesEl.style.display = 'none'
        if(tagsEl) tagsEl.style.display = 'none'        
    }

}

function del_toggleShowHelp(){

    var id = 'tagviewer';   // ееееееееее hack temp !!!!

    if (g_del_moreCurShowing) toggleMoreOptions() // hide more options before showing help


    var helpIndexEl = getTagsByClassInObjByID(id, 'div', 'del_helpIndex', 1)
    var helpContentEl = getTagsByClassInObjByID(id, 'iframe', 'del_helpcontent', 1)
    var relatedEl = getTagsByClassInObjByID(id, 'div', 'relatedTags', 1)
    var itemsEl = getTagsByClassInObjByID(id, 'div', 'tagged_items', 1)
    var relatedH3El = getTagsByClassInObjByID(id, 'h3', 'relatedTags_head', 1)
    var helpH3El = getTagsByClassInObjByID(id, 'h3', 'helpSections_head', 1)
    
    var newState = (helpContentEl.style.display == 'none')
    
    g_del_helpCurShowing = newState
    
    if (helpContentEl) helpContentEl.style.display = newState ? 'block' : 'none' 
    if (helpIndexEl) helpIndexEl.style.display = newState ? 'block' : 'none' 
    
    if (relatedEl) relatedEl.style.display = newState ? 'none' : 'block'
    if (itemsEl) itemsEl.style.display = newState ? 'none' : 'block'
    
    if (helpH3El) helpH3El.style.display = newState ? 'block' : 'none' 
    if (relatedH3El) relatedH3El.style.display = newState ? 'none' : 'block'
    
    if (g_del_helpSectionsDIV)  {} // have already loaded the iframe
    else{
        helpContentEl.src = 'del_tagviewer_help.html'
    }
        
    
    var el = document.getElementById(id)      
    if (el.className == 'tagviewer linkshidden'){ // show the main viewing area before showing the help - help link visible in collapsed ui
        del_toggleShowMainContent(id)
    }

}


/************

                delispiffysearch

************/

var del_g_searchPagesNotSites = 0;

function generateYahooJSON_URL(){     /// based on script from from Tony Hirst


    var searchTerms = ''    //formatSearchTerms();
    var searchString;
    var tmp; var url; var searchURL='', N = del_itemsData.length;
    
//    alert(N)
    
    if (del_itemsData.length){
        searchString= ''   ;    //  escape(searchTerms)+'+(';
        
//       searchString = '+('
        for(var i = 0; i < N; i++){
 //           alert(i)
            url=parseUrlDomain(del_itemsData[i].u)
            
            tmp=searchString+'&site='+url;
            if  (searchString.search(url)==-1){
                if (tmp.length < 1400){
                    searchString+='&site='+url  //+'&'
                }else{
 //                   alert('the limit reached: ' + tmp.length)
                    break;
                }
            }
        }
//        searchURL='http://search.yahoo.com/search?p='+searchString;
//        alert(searchString[searchString.length-1])
//        searchString += ')';
//        searchString =searchString.split('&)').join(')')
//    alert(searchString)
    }
    
/////return ''
    return searchString;

}


function generateYahooURL(){     /// based on script from from Tony Hirst


    var searchTerms = formatSearchTerms();
    var searchString;
    var tmp; var url; var searchURL='', N = del_itemsData.length;
    
    if (del_itemsData.length){
        searchString=escape(searchTerms)+'+(';
        for(var i = 0; i < N; i++){
            
            url=parseUrlDomain(del_itemsData[i].u)
            
            tmp=searchString+'site:'+url;
            if  (searchString.search(url)==-1){
                if (tmp.length<1400){
                    searchString+='site:'+url+'%20OR%20'
                }
                else break;
            }
        }
        searchString+=')';
        searchURL='http://search.yahoo.com/search?p='+searchString;
    }
    
    return searchURL;

}

function generateNewURL(delicious){     /// from Tony Hirst


///////alert(delicious.length)
 var searchTerms = formatSearchTerms();
 var searchString;
 var tmp; var url; var myURL='';
 if (delicious) {
 
 ///////alert(1)
  var customtype;
//  for (var i=0;i<document.dataForm.searchType.length;i++)
//   if (document.dataForm.searchType[i].checked==true)
//    customType=document.dataForm.searchType[i].value;

  searchString=escape(searchTerms)+'+(';
  for (var i=0, post; post = delicious[i]; i++) {
  
//  alert(i)
    if (customType=='pages') {
     tmp=searchString+'url:'+post.u;
     if (tmp.length<1400) searchString+='url:'+post.u+'%20OR%20'; else break;
    } else {
    url=parseUrlDomain(post.u)
    tmp=searchString+'site:'+url;
    if  (searchString.search(url)==-1)
     if (tmp.length<1400)
        searchString+='site:'+url+'%20OR%20'; else break;
    }
  }
  searchString+=')';
  myURL='http://search.yahoo.com/search?p='+searchString;
 }

  return myURL;
}

function formatSearchTerms(){
 var searchTerms= document.getElementById('ss_q').value;
 searchTerms= searchTerms.replace ( / /g, '+' );
 return searchTerms;
}


function parseUrlDomain(data) {
    var e=/^(http:\/\/)?([^\/]+)/i;

    if (data.match(e)) {
        return RegExp.$2;
    }
    else {
        return '';
    }
}


/************

                communications with the outside world

************/

function fetchDelJSON(path, callback, N){

    var count = N ? N : gk_del_nlinks
    var el = document.createElement("script");
    el.src = feed_url + path + '?count=' + count + '&callback=' + encodeURI(callback);
    el.charset = "utf-8";
    document.body.appendChild(el);

}

function loadedFavIcon(imgEl, itemID){
    
    
    if (! g_del_isIE){
        imgEl.style.display= 'block'
        return false;
    }
    var src = imgEl.src, el = document.getElementById(itemID)

    if (el && src){
        el.style.backgroundImage ='url(' + src + ')'
        el.style.backgroundRepeat ='no-repeat'
        
    }
}


function registerHelpIframe(doc, navFNref, h2refs){

    g_del_help_docElement = doc;
    g_del_help_navFN = navFNref;
    var sns = []
    
    if (g_del_helpSectionsDIV){}
    else{g_del_helpSectionsDIV = getTagsByClassInObjByID('tagviewer', 'div', 'del_help_topics', 1)}

    if(g_del_helpSectionsDIV) {
        for (var i=0; i < h2refs.length; i++){
            var oneSn = oneHelpSectionLink_tmpl.split('*sectionID*').join(h2refs[i].id)
             sns[i] = oneSn.split('*helpTopicText*').join(h2refs[i].title)
        }
        g_del_helpSectionsDIV.innerHTML = '<ul class="del_help_sections">' + sns.join('\r') + '</ul>'
    }
}


function chooseHelpOption(helpsn){

    if ( g_del_help_navFN) g_del_help_navFN (helpsn)
}


/************

                rendering data to html

************/



function gotLinksData(id, data, combining){

    toggleBusyVContent(0, id, 0)


    del_itemsData = data;
    
    var i, N = data.length, favTMPL = (gk_del_useFavICO ? oneFAVICO_tmpl : ''), tmpl = oneLinkLI_tmpl.split('*favTMPL*').join(favTMPL), items = []
    
    for (i = 0; i < N; i++){
        var o = data[i], url = o.u, descr = o.d, favURL = url.split('/').splice(0,3).join('/')+'/favicon.ico', linktitle = '(' + (i+1) + ' / ' + N + ') '
        var hiliteClassStr = (i % 2) ? '' : 'class="del_item_odd"'
        if (descr.length > 130){    // hack - expose long descriptions like I make to css styling - extra padding etc
            hiliteClassStr= (i % 2) ? 'class="del_descr_long"' : 'class="del_item_odd del_descr_long"';
        }
        var s = tmpl.split('*url*').join(url)
        if (o.n) linktitle += o.n
        s = s.split('*descr*').join(descr)  /// in delicious, 'description' is the title and 'notes' is the description :o)
        s = s.split('*linkid*').join(i+1)
        s = s.split('*linktitle*').join(safeForLinkTitle(linktitle))
        s = s.split('*favicon*').join(favURL)
        s = s.split('*notes*').join(o.n ? o.n : '')
        s = s.split('*tags*').join(renderTagsForItem(o.t ? o.t : []))
        
        s = s.split('*hiliteclass*').join(hiliteClassStr)
        items[i] = s
    }
    
    var ulstr = '<ul>' + items.join('\r') + '</ul>'
    ulstr = ulstr.split('*cntnrID*').join(id)
    ulstr = ulstr.split('*USERNAME*').join(g_del_UserName)
    ulstr = ulstr.split('*showTags*').join(gk_del_showTags ? 'block' : 'none')
    ulstr = ulstr.split('*showNotes*').join(gk_del_showNotes ? 'block' : 'none')
    
    if (! gk_del_openItemsInNewWindow){
        ulstr = ulstr.split('target="_blank"').join('')    
    }

    var cntnrEl = getTagsByClassInObjByID(id, 'div', 'tagged_items', 1)

    if (cntnrEl){
        cntnrEl.innerHTML = ulstr
        var relTagsEl = getTagsByClassInObjByID(id, 'div', 'relatedTags', 1)
        var tallestAllowedForItems = relTagsEl ? Math.max(relTagsEl.offsetHeight, gk_del_maxHeight) : gk_del_maxHeight

        
        if (cntnrEl.offsetHeight > tallestAllowedForItems){
            cntnrEl.style.height = tallestAllowedForItems + 'px'
            if ( g_del_isIE ) cntnrEl.style.overflow = 'auto'
        }else{
            if (parseInt(cntnrEl.style.height) < tallestAllowedForItems){   // the related tags dictate max height; I may be shorter already
                cntnrEl.style.height = tallestAllowedForItems + 'px'
            }
            if ( g_del_isIE ) cntnrEl.style.overflow = 'visible'
        }
    }
    writeTagViewerTitle(id, N, combining)
}

function writeTagViewerTitle(id, N, combining){

    var newTag = gsys_del_pendingLinksFetch[id]
    
    if (newTag){
        var newTagLink = 'http://delicious.com/' + g_del_UserName + '/' + newTag
       
    var h3strPreamble = '<b><i>' + N + '</i> Resources tagged:</b> <a class="del_itemsH3a" href="'
    var h3str = h3strPreamble + newTagLink + '" title="click to view these items in the delicious site (to see who else has collected them, etc)"><span class="h3delLinks">' +  newTag + '</span></a> <i>by ' + g_del_UserName + '</i>'
    
    if (combining){
        var tagsplit = newTag.split('+'), tagsStr = h3strPreamble
        if(tagsplit.length > 1){
            tagsStr += 'http://delicious.com/' + g_del_UserName + '/' + tagsplit[0]
                + '" title="click to view items tagged \'' + tagsplit[0] + '\' in the delicious site (to see who else has collected them, etc)"><span class="h3delLinks">' +  tagsplit[0] + '</span></a> '
                
            tagsStr += '<a class="del_itemsH3a" href="' + newTagLink
                + '" title="click to view items tagged both \'' + tagsplit[0] + '\' AND \'' + tagsplit[1] + '\' in the delicious site (to see who else has collected them, etc)"><span class="h3delLinks">+</span></a> '
        
            tagsStr += '<a class="del_itemsH3a" href="http://delicious.com/' + g_del_UserName + '/' + tagsplit[1]
                + '" title="click to view items tagged \'' + tagsplit[1] + '\' in the delicious site (to see who else has collected them, etc)"><span class="h3delLinks">' +  tagsplit[1] + '</span></a> '
                
            h3str = tagsStr + ' <i> by ' + g_del_UserName + ' (both tags applied)</i>'
        }
    }
    }else{
        var newTagLink = 'http://delicious.com/' + g_del_UserName
        h3str = 'Recent items from ' + g_del_UserName + '\'s delicious  social bookmarks'
    }
    var h3El = getTagsByClassInObjByID(id, 'h3', 'tagged_items_head', 1)

    if (h3El){
        h3El.innerHTML = h3str
    }
    var delLinkEl = getTagsByClassInObjByID(id, 'a', 'del_icon', 1) ///// MAY CAUSE UGLY EXT-LINK NOTICE IN PLONE DUE TO SCANNING FOR EXTERNAL LINKS
    
    if(delLinkEl){
        delLinkEl.href = newTagLink
        delLinkEl.style.display = 'block'
    }
  
    var rssLinkEl = getTagsByClassInObjByID(id, 'a', 'rss_icon', 1)
    
    if(rssLinkEl){
        rssLinkEl.href = newTagLink.split('http://delicious.com/').join('http://feeds.delicious.com/v2/rss/')
        rssLinkEl.style.display = 'block'
    }
    


}


function safeForLinkTitle(s){
    s = s.split('<').join('&lt;')
    s = s.split('>').join('&gt;')
    return s.split('"').join('&quot;')
}

function renderTagsForItem(t){
    var i,j=0, N = t.length, tagstrs = []
    for (i=0; i<N; i++){
        var tag = t[i]
        if (! dictItemLabelInList(tag, gk_del_omitTags)) tagstrs[j++] = oneItemTag_tmpl.split('*TAG*').join(tag)
    }
    return tagstrs.join(' ')
}

function initRelTagsData(data){ //// temp
    gotRelTagsData('tagviewer', data, 0)
}


function initCloudTagsData(data){ //// temp
    
    gotCloudTagsData('tagcloud','tagviewer', data)
}



function gotCloudTagsData(id, idviewer, data){

    toggleBusyVContent(0, id, 1)
    
    del_cloudTagsData = data;
    

    
    procTagData(del_cloudTagsData)    // build the lookup array
    
    del_clouds_tagcounts_hash = tagCountToTagCountHash(del_working_tagcounts)
    
    
///    var curTag = gsys_del_pendingRelatedFetch[idviewer]
    
    var  tmpl = oneCloudTag_tmpl, items = [], i = 0, count=0, tagClass = 'cloud'
    var cloudTagsEl = getTagsByClassInObjByID(id, 'div', 'cloud_tags', 1)
    
//////    gsys_del_callbacks_RelatedCombinedLinkObj[id] = null
    
    for (o in data){
        if (! dictItemLabelInList(o, gk_del_omitTags)){

            count = data[o]
            tagClass = tagCountToTagClass_Cloud(count)
            var style='font-size:'+scaler(count)+'px; color:'+colscaler(count, 0)+';'
            
            var tagname = o, linkTitle = count + ' items.  Click to view items tagged with \'' + o + '\' in the tag-viewer below this panel'
            var tagLink = 'http://delicious.com/' + g_del_UserName + '/' + tagname
            

            s = tmpl.split('*linkTitle*').join(linkTitle + ' [ items will display in the pane at the left ]')
            s = s.split('*TAG*').join(tagname)
            s = s.split('*ID*').join(id)
            s = s.split('*ID-VIEWER*').join(idviewer)
            s = s.split('*STYLE*').join(style)
            s = s.split('*N-CLASS*').join(tagClass)
            s = s.split('*COUNT*').join(count)
            
            
            s = s.split('*URL*').join(tagLink)
            
            g_del_allTags[i] = tagname // for comparing to bundles
            
            items[i++] = s
        }
    }
    
    del_clouds_maxTags = i

  
    if (typeof g_bundles != 'undefined') processBundles()
    else window.g_bundles = false   // hack to cover legacy installs
  
    
    var tagstr =  items.join('')
    tagstr = tagstr.split('"1 items').join('"1 item')
    
    cloudTagsEl.style.display='none' /// do not display until filter for showing n tags
    cloudTagsEl.innerHTML = tagstr
    
    var delLinkEl = getTagsByClassInObjByID(id, 'a', 'del_icon', 1)
    if(delLinkEl){
        delLinkEl.href = 'http://delicious.com/' + g_del_UserName
    }
  
    var rssLinkEl = getTagsByClassInObjByID(id, 'a', 'rss_icon', 1)
    
    if(rssLinkEl){
        rssLinkEl.href = 'http://feeds.delicious.com/v2/rss/'  + g_del_UserName
    }


    
    initNumTagsSlider()

    
      
    if (typeof g_del_initialBundle != 'undefined'){
        if (g_del_initialBundle && (g_del_initialBundle != '')) showTagsInBundle(g_del_initialBundle)
    }else if(document.location.search.indexOf('bundle=') > -1){
        var bundlearg = document.location.search.split('bundle=')[1].split('&')[0]
        showTagsInBundle(bundlearg)
    }

}

function gotRelTagsData(id, data, combining){

    toggleBusyVContent(0, id, 1)
    del_relTagsData = data;
    
    procTagData(del_relTagsData)    // build the lookup array
    
    var curTag = gsys_del_pendingRelatedFetch[id] /// these will be parameters passed 2nd hand through the anon function in the array
    
    var  tmpl = oneRelTag_tmpl, items = [], i = 0, count=0, tagClass = 'rel'
    var relTagsEl = getTagsByClassInObjByID(id, 'div', 'relatedTags', 1)
    
    gsys_del_callbacks_RelatedCombinedLinkObj[id] = null
    
    for (o in data){
        if (! dictItemLabelInList(o, gk_del_omitTags)){

            count = data[o]
            tagClass = tagCountToTagClass(count)
            var style='font-size:'+scaler(count,true)+'px; color:'+colscaler(count, 1)+';'
            var tagname = o, linkTitle = count + ' items.  Click to view items tagged with \'' + o + '\'  AND \'' + curTag + '\''
            var combineWith = "'"+ curTag + "'"
            var comboTagLink = 'http://delicious.com/' + g_del_UserName + '/' + curTag + '+' + tagname
            
            if (o == curTag){
                tagClass = tagClass.split('rel ').join('currentMain ')
 //               tagname = '! ' + tagname
                linkTitle = count + ' items.  Click to view all items tagged with \''+ curTag + '\''
                combineWith = 0
                comboTagLink = 'http://delicious.com/' + g_del_UserName + '/' + curTag
            }
            s = tmpl.split('*linkTitle*').join(linkTitle + ' [ items will display in the pane at the left ]')
            s = s.split('*TAG*').join(tagname)
//            s = s.split('*TAG-HR*').join(tagname)   //  .split('/').join('/ '))
            s = s.split('*COMBINEWITH*').join(combineWith)
            s = s.split('*ID*').join(id)
            s = s.split('*STYLE*').join(style)
            s = s.split('*N-CLASS*').join(tagClass)
            s = s.split('*URL*').join(comboTagLink)
            items[i++] = s
        }
    }
    
    var tagstr =  items.join('\r')
    tagstr = tagstr.split('"1 items').join('"1 item')
    
    relTagsEl.innerHTML = tagstr
    
    
    var itemCntnrEl = getTagsByClassInObjByID(id, 'div', 'tagged_items', 1) // might add some height to the items area if I am really tall

    var tallestAllowedForItems = relTagsEl ? Math.max(relTagsEl.offsetHeight, gk_del_maxHeight) : gk_del_maxHeight

    if (itemCntnrEl){
        if (parseInt(itemCntnrEl.style.height) != tallestAllowedForItems){
            itemCntnrEl.style.height = tallestAllowedForItems + 'px'
        }
    }
    
 //   return 0; // while I figure out how t pocount the dictionary :o)
    
    var h3str = '<i>' + i + '</i> Related tags:'
    
    var h3El = getTagsByClassInObjByID(id, 'h3', 'relatedTags_head', 1)
    
    if (h3El){
        h3El.innerHTML = h3str
    }
    
}

function writeJSInterfaceLinks(id){
    var UIlinks = '<a class="options_icon" onClick="toggleMoreOptions(\'' + id + '\');return false;" title="More options: '
    + 'click to view extra options for the display" href="more-options-link"><img '
    + 'src="kndelview_bg_imgs/singlepixel.gif" width="28" height="23" '
    + 'border="0"><i>more options</i></a> <a class="toggle_icon showing" '
    + 'onClick="del_toggleShowMainContent(\'' + id + '\');return false;" href="#"><img '
    + 'src="kndelview_bg_imgs/singlepixel.gif" width="33" height="28" '
    + 'border="0"><i>show/hide details</i></a>'
    
    document.write(UIlinks)
}

function hiliteCurrentCombinedTag(id, tag, linkEl){

    if (gsys_del_callbacks_RelatedCombinedLinkObj[id]){ // does this del-view object have an already hilited related tag?
        var prevLink = gsys_del_callbacks_RelatedCombinedLinkObj[id]
        prevLink.className = prevLink.className.split('currentMain ').join('rel ')
        prevLink.title = prevLink.prevTitle 
        prevLink.href = prevLink.prevHREF
    }
    var curClass = linkEl.className
    linkEl.className = curClass.split('rel ').join('currentMain ')
    var t = linkEl.title, count = t.split(' ')[0], url = linkEl.href
    var newTitle = (count + ' \'AND ' + gsys_del_pendingRelatedFetch[id] + '\' items currently showing.  Click to view all items tagged with \'' + tag + '\'')
    var newURL = 'http://delicious.com/' + g_del_UserName + '/' + tag
    
    linkEl.prevHREF = url
    linkEl.prevTitle = t
    
    linkEl.title = newTitle
    linkEl.href = newURL
    
    gsys_del_callbacks_RelatedCombinedLinkObj[id] = linkEl  // remember this link for de-hiliting later
    
}


function numTagsSliderChanged(offset){


    var id = 'tagcloud' //// hack
    
    document.getElementById('horizWrapper').blur()
    
    var p = Math.floor((g_sliderLstart + offset)/100 * del_clouds_maxTags), cutOff = del_clouds_tagcounts_hash[p]
       
    
    del_clouds_tagcounts_CutOff = cutOff
    var cloudTagsEl = getTagsByClassInObjByID(id, 'div', 'cloud_tags', 1)
    
    cloudTagsEl.style.display='block'
    
    var tagEls = cloudTagsEl.getElementsByTagName('A'), N =tagEls.length, numShowing = 0

    for (var i = 0; i < N; i++){        /// try first the dumb way - better to only change those that must be changed and to work from an array of el refs
        var el = tagEls[i]
        var oneCt = parseInt(el.getAttribute('kndel:count'))
        if (oneCt <  cutOff ){
            el.style.display='none'
        }else{
            numShowing++
            el.style.display='inline'
        }
    }
    document.getElementById('nTagsCur').innerHTML = numShowing;
    
}


function initNumTagsSlider(){

    document.getElementById('nTagsTotal').innerHTML = '['+ del_clouds_maxTags + ']';
    
    
    var p = gk_del_nCloudTagShowing / del_clouds_maxTags
    
      
    nTagsSliderInit(p)
    
    
    
//alert(document.getElementById('horizHandleDiv').style.left)

//    numTagsSliderChanged(offsetStart)

}

function tagCountToTagCountHash(counts){

    var i, freqs = [], N = counts.length, curCount, cumFreq, c
    
    counts.sort(function(a,b){return (parseInt(b) > parseInt(a)) ? 1 : -1})

    for (i = 0, c = 0, cumFreq = 0, curCount = counts[0]; i< N; i++){
        if (counts[i] == curCount){
            cumFreq++
        }
        else{
            for (var j=c; j< i; j++){
                freqs.push(curCount)
            }
            curCount = counts[i]
            c = i
            cumFreq++
        }
    }
    return freqs
}



function tagCountToTagClass(count){     /// maybe ought to allow author to specify cut-offs??

    if (g_del_relTagCount < gk_del_ntags_cutoffAbsTagCountsToSizes) return("rel " + scaler(count))

    
    if (count == 1) return "rel one"
    if (count < 5) return "rel onetofive"
    if (count < 10) return "rel five"
    if (count < 20) return "rel ten"
    if (count < 30) return "rel twenty"
    if (count < 40) return "rel thirty"
    if (count < 50) return "rel forty"
    if (count < 60) return "rel fifty"
    
    return "rel sixty"
}

function tagCountToTagClass_Cloud(count){     /// maybe ought to allow author to specify cut-offs??
    return scaler(count)

//    if (g_del_relTagCount < gk_del_ntags_cutoffAbsTagCountsToSizes) return("rel " + lookup[count-1])

    
    if (count == 1) return "rel one"
    if (count < 5) return "rel onetofive"
    if (count < 10) return "rel five"
    if (count < 20) return "rel ten"
    if (count < 30) return "rel twenty"
    if (count < 40) return "rel thirty"
    if (count < 50) return "rel forty"
    if (count < 60) return "rel fifty"
    
    return "rel sixty"
}

/************

                globals and string templates

************/

var g_del_isIE = navigator.appName.indexOf('Microsoft') > -1

/*
var oneLinkLI_tmpl = '<li *hiliteclass* id="*cntnrID*_*linkid*">*favTMPL*<a title="*linktitle*" target="_blank" class="link-plain" href="*url*">*descr*</a><div class="delicious-extended" style="display:*showNotes*;"><b>*linkid*</b><i>*notes*</i></div><div class="del_tags" style="display:*showTags*;">*tags*</div></li>'
*/

var oneLinkLI_tmpl = '<li *hiliteclass* id="*cntnrID*_*linkid*">*favTMPL*<a title="*linktitle*" target="_blank" class="link-plain" href="*url*"  onMouseOver="mouseIntoItem(event, \'*cntnrID*_*linkid*\', this);return false;" onMouseOut="mouseOutOfItem(event, \'*cntnrID*_*linkid*\',this);return false;">*descr*</a><div class="delicious-extended" style="display:*showNotes*;"><b>*linkid*</b><i>*notes*</i></div><div class="del_tags" style="display:*showTags*;">*tags*</div></li>'

var oneFAVICO_tmpl = '<img src="*favicon*" onload="loadedFavIcon(this, \'*cntnrID*_*linkid*\');return true;" style="display: none;" height="16" width="16">'

var oneRelTag_tmpl = '<a title="*linkTitle*" style="*STYLE*" onClick="relatedTagClicked(\'*TAG*\', \'*ID*\', *COMBINEWITH*, this);return false;" class="*N-CLASS*" href="*URL*">*TAG*</a>'


var oneCloudTag_tmpl = '<a title="*linkTitle*" kndel:count="*COUNT*"   style="*STYLE*" onClick="cloudTagClicked(\'*TAG*\', \'*ID*\', \'*ID-VIEWER*\', this);return false;" class="*N-CLASS*" href="*URL*">*TAG* </a>'


var oneItemTag_tmpl = '<a class="delicious-tag" title="Click to view items with this tag" onClick="itemTagClicked(\'*TAG*\', \'*cntnrID*\');return false;" href="http://delicious.com/*USERNAME*/*TAG*">*TAG*</a>'


var oneHelpSectionLink_tmpl = '<li><a title="Click to scroll to this help section in the helkp-viewer at the left" onClick="chooseHelpOption(\'*sectionID*\');return false;" href="del_tagviewer_help.html#*sectionID*">*helpTopicText*</a></li>'


/************

                common utilities
************/


function dictItemLabelInList(o, ar){
    for (var i=0,N=ar.length; i<N; i++){
        if (o == ar[i]) return 1
    }
    return 0
}



function filterForClass(aClass, aNodeList, firstEl){
    var aClass = new String(aClass);
    aClass=aClass.toLowerCase();
    var filteredNodeList = new Array();
    if(!(aNodeList.length > 0)){return filteredNodeList}
    for(var i=0; i<aNodeList.length; i++){
        var nodeString = new String(aNodeList[i].className);
        nodeString = nodeString.toLowerCase();
        if(nodeString == aClass){
            filteredNodeList[filteredNodeList.length] = aNodeList[i];
//          filteredNodeList.push(aNodeList[i]);
        }
    }
    if (firstEl){
        if(filteredNodeList.length > 0) return filteredNodeList[0]
        else return null;
    }
    return filteredNodeList;
}


function getTagsByClassInObj(obj, tag, classname, firstEl){

    var nodes = obj.getElementsByTagName(tag)
    return filterForClass(classname, nodes, (firstEl ? firstEl : 0))

}

function getTagsByClassInObjByID(id, tag, classname, firstEl){
    var obj = document.getElementById(id)
    if(obj) return getTagsByClassInObj(obj, tag, classname, (firstEl ? firstEl : 0))
    return [];
}



/************

                GET FREQUENCY-DISTRIBUTION BALANCED LOOKUP TABLE FOR TAG COUNTS TO CLASSES
************/



//from delicious
var SvgColors = {'black':'000000', 'silver':'c0c0c0', 'maroon':'800000', 'red':'ff0000', 'navy':'000080', 'blue':'0000ff', 'purple':'800080', 'fuchsia':'ff00ff', 'green':'008000', 'lime':'00ff00', 'olive':'808000', 'yellow':'ffff00', 'teal':'008080', 'aqua':'00ffff', 'gray':'808080', 'grey':'808080', 'white':'ffffff', 'indianred':'cd5c5c', 'darksalmon':'e9967a', 'lightcoral':'f08080', 'salmon':'fa8072', 'orangered':'ff4500', 'crimson':'dc143c', 'firebrick':'b22222', 'darkred':'8b0000', 'mediumvioletred':'c71585', 'pink':'ffc0cb', 'lightpink':'ffb6c1', 'hotpink':'ff69b4', 'deeppink':'ff1493', 'palevioletred':'db7093', 'darkkhaki':'bdb76b', 'khaki':'f0e68c', 'palegoldenrod':'eee8aa', 'lightgoldenrodyellow':'fafad2', 'lightyellow':'ffffe0', 'lemonchiffon':'fffacd', 'gold':'ffd700', 'papayawhip':'ffefd5', 'moccasin':'ffe4b5', 'peachpuff':'ffdab9', 'cyan':'00ffff', 'aquamarine':'7fffd4', 'turquoise':'40e0d0', 'mediumturquoise':'48d1cc', 'darkturquoise':'00ced1', 'cadetblue':'5f9ea0', 'slategray':'708090', 'slategrey':'708090', 'lightcyan':'e0ffff', 'paleturquoise':'afeeee', 'powderblue':'b0e0e6', 'lightsteelblue':'b0c4de', 'steelblue':'4682b4', 'lightblue':'add8e6', 'skyblue':'87ceeb', 'lightskyblue':'87cefa', 'deepskyblue':'00bfff', 'cornflowerblue':'6495ed', 'royalblue':'4169e1', 'mediumslateblue':'7b68ee', 'dodgerblue':'1e90ff', 'mediumblue':'0000cd', 'darkblue':'00008b', 'midnightblue':'191970', 'lightsalmon':'ffa07a', 'orange':'ffa500', 'darkorange':'ff8c00', 'coral':'ff7f50', 'tomato':'ff6347', 'orangered':'ff4500', 'aquamarine':'7fffd4', 'mediumspringgreen':'00fa9a', 'springgreen':'00ff7f', 'palegreen':'98fb98', 'greenyellow':'adff2f', 'chartreuse':'7fff00', 'lawngreen':'7cfc00', 'lime':'00ff00', 'lightgreen':'90ee90', 'yellowgreen':'9acd32', 'limegreen':'32cd32', 'mediumseagreen':'3cb371', 'darkseagreen':'8fbc8f', 'forestgreen':'228b22', 'seagreen':'2e8b57', 'olivedrab':'6b8e23', 'darkolivegreen':'556b2f', 'darkgreen':'006400', 'mediumaquamarine':'66cdaa', 'turquoise':'40e0d0', 'lightseagreen':'20b2aa', 'darkcyan':'008b8b', 'lavender':'e6e6fa', 'thistle':'d8bfd8', 'plum':'dda0dd', 'violet':'ee82ee', 'magenta':'ff00ff', 'orchid':'da70d6', 'mediumorchid':'ba55d3', 'darkorchid':'9932cc', 'blueviolet':'8a2be2', 'darkviolet':'9400d3', 'mediumpurple':'9370db', 'slateblue':'6a5acd', 'darkmagenta':'8b008b', 'darkslateblue':'483d8b', 'indigo':'4b0082', 'honeydew':'f0fff0', 'mintcream':'f5fffa', 'azure':'f0ffff', 'aliceblue':'f0f8ff', 'ghostwhite':'f8f8ff', 'whitesmoke':'f5f5f5', 'lavenderblush':'fff0f5', 'mistyrose':'ffe4e1', 'antiquewhite':'faebd7', 'seashell':'fff5ee', 'snow':'fffafa', 'beige':'f5f5dc', 'linen':'faf0e6', 'oldlace':'fdf5e6', 'floralwhite':'fffaf0', 'ivory':'fffff0', 'gainsboro':'dcdcdc', 'lightgrey':'d3d3d3', 'lightgray':'d3d3d3', 'darkgray':'a9a9a9', 'darkgrey':'a9a9a9', 'dimgray':'696969', 'dimgrey':'696969', 'darkslategray':'2f4f4f', 'darkslategrey':'2f4f4f', 'lightslategray':'778899', 'lightslategrey':'778899', 'cornsilk':'fff8dc', 'blanchedalmond':'ffebcd', 'bisque':'ffe4c4', 'navajowhite':'ffdead', 'wheat':'f5deb3', 'sandybrown':'f4a460', 'goldenrod':'daa520', 'darkgoldenrod':'b8860b', 'peru':'cd853f', 'chocolate':'d2691e', 'saddlebrown':'8b4513', 'brown':'a52a2a', 'sienna':'a0522d', 'darkred':'8b0000', 'burlywood':'deb887', 'tan':'d2b48c', 'rosybrown':'bc8f8f' };
var del_working_tagcounts_lookup = new Array()

var del_working_tagcounts = []
/*
var del_col_min= clrFix("#334433")
var del_col_max=clrFix("#666BBB")
*/

var del_rel_col_min= clrFix("#334433")
var del_rel_col_max=clrFix("#666BBB")

var del_col_min= clrFix("#442222")
var del_col_max=clrFix("#BBBBDD")


var del_font_min = 11;
var del_font_max = 24;

var del_rel_font_min = 11;
var del_rel_font_max = 18;


var del_c_min;
var del_c_max;

function sum(d) {
    var total = 0;
    for(var i = 0; i < d.length; i++) total += d[i];
    return total;
}

function SD(d) {
    var N = d.length+0.0;
    var M=(sum(d)/N)+0.0
    SSD =0.0
    for (i=0;i<d.length;i++){
        SSD=SSD+(Math.pow(d[i]-M,2))+0.0
    }
    return [M,Math.sqrt(SSD/N)]
}


function setMinMax(d) {
    var outliers = 0;
    del_c_min = 9999999;
    del_c_max = 0;
    var data = SD(d)
    var M = data[0]
    var sd = data[1]
    for (i=0;i<d.length;i++){
        dfm = (d[i]-M)/sd
        if (dfm< 3) {
           if (d[i] < del_c_min) del_c_min=d[i]
           if (d[i] > del_c_max) del_c_max=d[i]
        }
    }
}

function procTagData(tag_data) {
    var m_max = 0;
    var c_divs = 7;
    var interval;

    var tag_count = new Array()

    d = tag_data
    d_count=0
    for (o in d){
        v= parseInt(d[o])
        if(v>m_max)m_max=v
        tag_count.push(v);
        d_count++;
    }
    
    g_del_relTagCount = d_count;    //  we'll ask later if this is large; if so we revert to absolute tag counts for the size of font
    

    setMinMax(tag_count)
    del_working_tagcounts = tag_count

}

function colscaler(i, rel) {
    clrs = []
    iMax = del_c_max-del_c_min
    for (var c = 0; c < 3; c++) {        
        min = rel ? del_rel_col_min.rgb[c] : del_col_min.rgb[c]
        max = rel ? del_rel_col_max.rgb[c] : del_col_max.rgb[c]
        if(min>max){
            var m = (min-max)/Math.log(iMax)
            var scaled = min-Math.floor(Math.log(i) * m)
        } else {
            var m = (max-min)/Math.log(iMax)
            var scaled = Math.floor(Math.log(i) * m + min)
        }
        clrs[c]=scaled
    }
    return 'rgb('+clrs[0]+','+clrs[1]+','+clrs[2]+')'
}


function scaler(i,rel) {
    if(rel){
        min=del_rel_font_min
        max=del_rel_font_max
    }else{
        min=del_font_min
        max=del_font_max
    }
    iMax = del_c_max-del_c_min
    if(min>max){
        var m = (min-max)/Math.log(iMax)
        var scaled = min-Math.floor(Math.log(i) * m)
    } else {
        var m = (max-min)/Math.log(iMax)
        var scaled = Math.floor(Math.log(i) * m + min)
    }  
    return scaled
}





// returns almost any kind of raw color value in hex and rgb forms
// todo: make less dumb

function clrFix(raw) {
    c = raw.trim().toLowerCase().replace(/ /g, '')
    var clr = '000000'
    var hex = c.match(/^#?([a-f0-9]{6})$/)
    var hexSm = c.match(/^#?([a-f0-9]{3})$/)
    if(hex) clr = hex[1]
    else if(hexSm) clr = hexSm[1].charAt(0) + hexSm[1].charAt(0) + hexSm[1].charAt(1) + hexSm[1].charAt(1) + hexSm[1].charAt(2) + hexSm[1].charAt(2)
    else if(SvgColors[c]) clr = SvgColors[c]

    var rgb = [parseInt(clr.substr(0,2),16), parseInt(clr.substr(2,2),16), parseInt(clr.substr(4,2),16)]
    
    return {'hex':clr, 'rgb':rgb, 'raw':raw}
}



/********** BELOW IS FOR THE BUNDLES - ADDED JAN 07 **********/



var g_bundles_byName = [], g_bundlesObjs_byName = [], g_bundlesStrs_byName = [], g_curShowingBundle = 'taball_showalltags'
var g_totalNTags, g_curShowingTagsListTxt = '', g_curShowingTagsArray = [], g_allBundledTags = '', g_unblundledTags = []

var g_intendedNTagsLastBundle = 50;

function processBundles(){

  
//    g_bundles.sort(function(a,b){return (a.name > b.name) ? 1 : -1})


    var i, N = g_bundles.length, s = gk_bundlesTabstmpl[0].split('**del_clouds_maxTags**').join(del_clouds_maxTags)
    var oneBundleName, oneBundleTab
    for (i=0; i<N; i++){
        oneBundleName = g_bundles[i].name
        if (gk_showUnbundled){
            g_allBundledTags +=  ' ' + g_bundles[i].tags + ' '
        }
        if(arrayContains(gk_del_omitBundles, oneBundleName)) continue
        g_bundles_byName[oneBundleName] = g_bundles[i].tags.split(' ')
        g_bundlesStrs_byName[oneBundleName] = ' ' + g_bundles[i].tags + ' '
        g_bundlesObjs_byName[oneBundleName] = {}
        oneBundleTab = gk_onebundleTabtmpl.split('**oneBundleName**').join(oneBundleName)
        oneBundleTab = oneBundleTab.split('**oneBundleNumTags**').join(g_bundles_byName[oneBundleName].length)
        s += oneBundleTab

    }
    
    if (gk_showUnbundled) {
        var NU = computeUnbundledArray()
        
        if (NU) s += gk_bundlesTabstmpl[1].split('**unbundledNumTags**').join(NU)
    }
    s += '</ul>'
    
    if (document.getElementById('tagbundles')){
        document.getElementById('tagbundles').innerHTML = s
    }
    
    g_totalNTags = del_clouds_maxTags
    g_curShowingTagsArray = g_del_allTags
    
    g_intendedNTagsLastBundle = gk_del_nCloudTagShowing /// later will compare again to gk_del_nCloudTagShowing when changing bundles, and increase it if that is bigger...

}

function bundleChanged(newTab){
 
    /*** update the tabs ***/
    
    if(newTab != g_curShowingBundle){
    
        if (g_intendedNTagsLastBundle < gk_del_nCloudTagShowing) g_intendedNTagsLastBundle = gk_del_nCloudTagShowing // do not let it ratchet down to smaller values
        else if (g_intendedNTagsLastBundle < del_clouds_maxTags) g_intendedNTagsLastBundle = gk_del_nCloudTagShowing // unless there had been a choice to make it bigger
        
        document.getElementById(g_curShowingBundle).className = ''
        document.getElementById(newTab).className = 'currentTab'
        g_curShowingBundle = newTab
        document.getElementById(newTab).blur()        
        
    }
    /*** update the cloud ***/
    del_clouds_maxTags = g_curShowingTagsArray.length
    updateCloudForBundleChoice()        ///// RECOMPUTES AND RESETS THE HSH FOR FREQUENCY -- NB SHOULD ONLY DO EACH ONE ONCE!!!!
    
}


function procTagDataForFrequencyWBundles(tag_data) {
    var m_max = 0;
    var c_divs = 7;
    var interval;

    var tag_count = new Array()

    d = tag_data
    d_count=0
    for (o in d){
        if (g_curShowingBundle != 'taball_showalltags'){
            if (g_curShowingTagsListTxt.indexOf(o) == -1) continue
        }
        v= parseInt(d[o])
        if(v>m_max)m_max=v
        tag_count.push(v);
        d_count++;
    }
    
    g_del_relTagCount = d_count;    //  we'll ask later if this is large; if so we revert to absolute tag counts for the size of font
    

    setMinMax(tag_count)
    del_working_tagcounts = tag_count
    
    
    del_clouds_tagcounts_hash = tagCountToTagCountHash(del_working_tagcounts)

}

function computeUnbundledArray(){

    var i, d1 = new Date(), N = g_del_allTags.length
    for(i = 0; i < N; i++){
        oneTag = g_del_allTags[i]
        if(g_allBundledTags.indexOf(oneTag) == -1){
            g_unblundledTags.push(oneTag)
        }
    }

    return g_unblundledTags.length
}

function calc_showThisTag(el, cutOff){

    if (g_bundles){
        if (g_curShowingBundle != 'taball_showalltags'){
            var tag = el.innerHTML
            if (g_curShowingTagsListTxt.indexOf(' ' + tag) == -1) return 0  // NB there is already one space after the tag in markup
        }
    }

    var oneCt = parseInt(el.getAttribute('kndel:count'))
    
    return oneCt >= cutOff ? 1 : 0

}

function updateCloudForBundleChoice(){

    
    procTagDataForFrequencyWBundles(del_cloudTagsData)
    initNumTagsSliderBundleChanged()

}

function numTagsSliderChanged(offset){

    var id = 'tagcloud' //// hack
    
    document.getElementById('horizWrapper').blur()
    
    var p = Math.floor((g_sliderLstart + offset)/80 * del_clouds_maxTags), cutOff = del_clouds_tagcounts_hash[p]  ////////// it had been 100 iso 80

  
    if(typeof cutOff == 'undefined') cutOff = 1
    

    del_clouds_tagcounts_CutOff = cutOff
    var cloudTagsEl = getTagsByClassInObjByID(id, 'div', 'cloud_tags', 1)
    
    cloudTagsEl.style.display='block'
    
    var tagEls = cloudTagsEl.getElementsByTagName('A'), N =tagEls.length, numShowing = 0

    for (var i = 0; i < N; i++){        /// try first the dumb way - better to only change those that must be changed and to work from an array of el refs
        var el = tagEls[i]
        if (! calc_showThisTag(el, cutOff) ){
            el.style.display='none'
        }else{
            numShowing++
            el.style.display='inline'
        }
    }
    
    document.getElementById('nTagsCur').innerHTML = numShowing;
    gk_del_nCloudTagShowing = numShowing
    
    
}

function initNumTagsSliderBundleChanged(){   ////////////// remove this - it is in the orig js

    document.getElementById('nTagsTotal').innerHTML = '['+ del_clouds_maxTags + ']';
    
    
    var p = Math.min(1, g_intendedNTagsLastBundle / del_clouds_maxTags)

    nTagsSliderInit(p)

}


function arrayContains(a, e){
    
    var N = a.length;
    for(var i=0; i<N; i++){
        if(a[i] == e) return 1
    }

    return 0
}


function showAllTags(){
    
    var newTab = 'taball_showalltags'
    
    if(newTab != g_curShowingBundle){
        g_curShowingTagsArray = g_del_allTags
        g_curShowingTagsListTxt = ' '
        bundleChanged(newTab)
        updateCloudTitleForBundle('All ' + del_clouds_maxTags + ' tags')
    }
}

function showTagsInBundle(bid){
    
    var newTab = 'tab_' + bid
    
    if(newTab != g_curShowingBundle){
        g_curShowingTagsArray = g_bundles_byName[bid]
        g_curShowingTagsListTxt = g_bundlesStrs_byName[bid]
        bundleChanged(newTab)
        updateCloudTitleForBundle( del_clouds_maxTags + ' tags in bundle "<b>' + bid + '</b>"')
        
    }
}


function showNotBundledTags(){
    var newTab = 'taball_showunbundledtags'
    
    if(newTab != g_curShowingBundle){
        g_curShowingTagsArray = g_unblundledTags
        g_curShowingTagsListTxt = ' ' + g_unblundledTags.join(' ') + ' '
        bundleChanged(newTab)
        updateCloudTitleForBundle(del_clouds_maxTags + ' unbundled tags')
    }
    
}

function updateCloudTitleForBundle(str){
    
    var id ='tagcloud' /// hack!
    
    str += ' <i>- click tags to view tagged items in the viewer below)</i>'

    var h3El = getTagsByClassInObjByID(id, 'h3', 'tagged_items_head', 1)

    if (h3El){
        h3El.innerHTML = str
    }

}

var gk_bundlesTabstmpl = ['<ul><li id="taball_showalltags" class="currentTab"><a href="javascript:void(showAllTags())"'
    + ' title="Click to show all **del_clouds_maxTags** tags in the main tag cloud area, regardless of bundles"'
    + '>All **del_clouds_maxTags**  tags</a></li>'
    ,
    '<li id="taball_showunbundledtags"><a href="javascript:void(showNotBundledTags())" title="Click to show unbundled tags (**unbundledNumTags** tags that are not in any of the bundles)'
    + ' in the main tag cloud area"'
    + '>Unbundled tags (**unbundledNumTags**)</a></li>'
    ]

var gk_onebundleTabtmpl = '<li id="tab_**oneBundleName**"><a href="javascript:void(showTagsInBundle(\'**oneBundleName**\'))" '
    + ' title="Click to show (**oneBundleNumTags**) tags from the bundle \'**oneBundleName**\' in the main tag cloud area">**oneBundleName**</a></li>'

