/*==================================================*
 $Id: mapviewobjs.js, v2.0 2009/02/13 01:24:00 Exp $
 Copyright 2009-2010 Spidy Web Design
 Last Modified 2/10/2010
 http://spidy.net/
 This is a set of objects for displaying json maps
 including a collection object with appropriate methods
 *==================================================*/

// Global Objects to hold marker and layers
var allmarkers = new Object();
var layers = new Object();
var sortedlayers = new Array();  // names of layers in sorted order
var editmode = 0;
var markersbyzoom = new Object();   // For launching the markerManager in batch
var mapkeys = null;     // for random-access editing via url

// icon construction material
var iconbase = "/Photos/imgs/mapicons/";
var iconcodes = {'pin': '-pushpin.png', 'star': '-stars.png',
                 'dot': '-dot.png', 'blank': '.png', 'sm': '-sm.png'}
var sepiacolor = 'E6D5B3';
var clt1 = ['green', 'yellow', 'white', 'ltblue', 'pink', 'purple', 'grey', 'red', 'blue', 'orange', 'sepia'];
var clt4 = ['00FF00', 'FFBB00', 'EEEEEE', '22DDFF', 'FF0088', '8800FF', '000000', 'FF0000', '0000FF', 'FF8800', sepiacolor];
var maxzoom = 21;
var gp = {
    'mtype': [['star', 'star', 'pin', 'pin'],
              ['star', 'star', 'pin', 'pin'],
              ['star', 'star', 'pin', 'pin'],
              ['blank', 'blank', 'dot', 'star'],
              ['sm', 'sm', 'blank', 'dot']
             ],
    'zooms':  [0, 0, 0, 8, 12],
    'widths': [4, 4, 5, 7]
}



// Define icon styles and 4 default icon types
var iconstyles = {
    // shadow, iconSize, shadowSize, iconAnchor, ifwAnchor
    'dot': ['z_paddle_shadow.png', 32,32, 59,32, 16,32, 16,0],
    'pin': ['z_pushpin_shadow.png', 32,32, 59,32, 16,32, 16,0],
    'star': ['z_star_shadow.png', 23,39, 45,42, 11,38, 14,5],
    'sm': ['mm_20_shadow.png', 12,20, 22,20, 6,20, 5,1],
    'cir': ['waypnt.png', 11,11, 11,11, 6,6, 6,1]
    };
iconstyles.blank = iconstyles.dot;

function setIconStyle(icon, stylecode) {
    var s = iconstyles[stylecode];
    icon.shadow = iconbase+s[0];
    icon.iconSize = new GSize(s[1],s[2]);
    icon.shadowSize = new GSize(s[3],s[4]);
    icon.iconAnchor = new GPoint(s[5],s[6]);
    icon.infoWindowAnchor = new GPoint(s[7],s[8]);
}

var padIcon = new GIcon(G_DEFAULT_ICON);    // PADDLE
setIconStyle(padIcon, 'dot');

var pinIcon = new GIcon(G_DEFAULT_ICON);    // PUSHPIN
setIconStyle(pinIcon, 'pin');

var starIcon = new GIcon(G_DEFAULT_ICON);   // STAR
setIconStyle(starIcon, 'star');

var smIcon = new GIcon(G_DEFAULT_ICON);     // SMALL
setIconStyle(smIcon, 'sm');

// --- INFOWINDOW

var sp = '&nbsp;';
var br = '<br\/>';
var tabledef = '<table class="ifwtable"><tr>';
var emptyth = '<img src="" alt="" id="ifwthumb" onclick="pic(this);" style="border:0px"\/>'
    +'<p class="acaption" id="ifwcap"><\/p>';

// ------------------------------------------------------------
//   RLayer Object (Collection)
// ------------------------------------------------------------

function RLayer(coll) {
    // Initialize a layer of markers
    // array this.markers to be populated later as markers are added

    // Variable .isVisible indicates visibility
    // Makes available methods .show() .hide()

    // Initialize Collection name and desc
    this.name = clean2(coll.name);
    this.title = clean2(coll.title);

    var collvars = ['desc', 'year', 'color', 'opacity', 'dlevel'];
    for (var j=0; j<collvars.length; j++) {
        if (collvars[j] in coll) this[collvars[j]] = coll[collvars[j]];
    }
    this.mtype = (coll.mtype)?coll.mtype:gp.mtype;
    this.zooms = (coll.zooms)?coll.zooms:gp.zooms;
    this.widths = (coll.widths)?coll.widths:gp.widths;
    if (editmode!=0) {
        var collvars = ['sitelist','dcat'];
        for (var j=0; j<collvars.length; j++) this[collvars[j]] = coll[collvars[j]];
    }

    // Initialize markerlist
    this.markers = new Array();

    // All collections visible by default
    this.isVisible = true;
    if (this.name!='Orphans') sortedlayers.push(this.name);

    // === Show and Hide, call respective methods for each marker in this.markers
    this.show = function() {

        for (var i=0;i<this.markers.length;i++) {
            var m  = allmarkers[this.markers[i]];
            m.show(this);
        }

        // == check the checkbox and set visible ==
        document.getElementById(this.name+"box").checked = true;
        this.isVisible = true;

    }

    this.hide = function() {

        // == clear the checkbox and set visibility ==
        document.getElementById(this.name+"box").checked = false;
        this.isVisible = false;

        // == close the info window, in case its open on a marker that we just hid
        map.closeInfoWindow();

        for (var i=0;i<this.markers.length;i++) {
            var m  = allmarkers[this.markers[i]];
            m.hide();
        }
    }

}

// ------------------------------------------------------------
//   RMarker Object
// ------------------------------------------------------------

function RMarker(pm) {
    // Initialize and load a given marker 'pm'
    // Defines functions .createMarker() .createPolyLine() +  others

    // Set current collection-dependent attributes
    this.set_attr = function(coll) {
        if (this.lcolors) { // line properties
            this.clcolor = this.lcolors[coll.name];
            this.hicolor = (coll.color==7)?'#00FF00':'#FF0000';
        } else {
            // calculate levels
            this.mlevel = this.level;
            if (coll.dlevel) {this.mlevel = (this.dlevel==-1)?coll.dlevel:this.dlevel;}

            // colors and shapes
            this.ccolor = coll.color;
            this.cmtype = coll.mtype[this.mlevel][this.weight];
            // Temporary correction for lack of colored pins
            if ((this.cmtype=='pin')&&(typeof(coll.color)!="number")) this.cmtype='star';
            var hcolor = (coll.color==7)?0:7;
            this.numstar = false;
            if (this.cmtype=='star') {
                if (typeof(coll.color)=="number") {this.numstar = true;}
                else {hcolor='FF0000'}
            }
            this.micon = geticonurl(this.ccolor, this.cmtype);
            this.hicon = geticonurl(hcolor, this.cmtype);
        }
    }

    // Determine first visible collection, set attributes, and show/hide
    // remove and re-add markers to mgr to fix zoom
    this.show = function(cl) {
        this.set_attr(cl);
        this.update_color();
    }
    this.hide = function() {
        var visible = markervisible(this.key);
        if (!visible[0]) { mhide(this.marker); return; }
        // show next collection
        var cl = visible[1];
        this.set_attr(cl);
        this.update_color();
    }

    // Set marker color based on attributes
    this.update_color = function(high) {
        var m = this.marker;
        if (m instanceof GPolyline) {   // Lines are easy
            var ncolor = (high)?this.hicolor:this.clcolor;
            try { m.setStrokeStyle({color: ncolor}) } catch(err) { }
            m.show();
        } else if (m instanceof GMarker)  {
            // Fix Icon style and color
            var nicon = (high)?this.hicon:this.micon;
            m.getIcon().image = nicon;  // fixes default for rezoom w/ mgr
            if (this.numstar) { setIconStyle(m.getIcon(), 'dot'); }
            else { setIconStyle(m.getIcon(), this.cmtype); }
            if (high) {try {m.setImage(nicon);} catch(err) { }}
            else {
                mgr.removeMarker(m);
                mgr.addMarker(m, this.zoom);
            }
        }
    }

    // Create a Point marker and set up the event window
    this.createMarker = function(point,def_icon) {
        var markerOptions = { icon: def_icon, title:clean2(this.name) };
        if (editmode !=0) { markerOptions["draggable"] = true; }
        //else { markerOptions["hide"] = true; }

        var m = new GMarker(point, markerOptions);

        if (editmode==0) {
            // Switch icon color on marker mouseover and mouseout
            // since only highlighting, setImage is OK
            GEvent.addListener(m, "mouseover", function() {
                try { m.setImage(allmarkers[m.key].hicon); } catch(err) { }
            });
            GEvent.addListener(m, "mouseout", function() {
                try { m.setImage(allmarkers[m.key].micon); } catch(err) { }
            });
        } else if ((editmode==1)||(editmode==2)||(editmode==4)) {
            setHighlightDragging(m);
        }
        m.parnt = this;

        return m;
    }

    // Create a polyline
    this.createPolyLine = function(clr,width,opc, ps) {
        if (editmode!=0 && this.lys[0]!="Orphans") clr = '#0000FF';
        if (ps) { var poly = new GPolyline(ps, clr, width, opc, {geodesic:true, mouseOutTolerance: 10}); }
        else {
            var poly = new GPolyline.fromEncoded({
                points: this.encoding, levels: this.zoomstr, zoomFactor: 2, numLevels: 18,
                color: clr, weight: width, opacity:opc, mouseOutTolerance: 10
                });
        }

        // Switch cursor on polyline mouseover and mouseout
        GEvent.addListener(poly, "mouseover", function() {
            map.getDragObject().setDraggableCursor("pointer");
            if (editmode==0) try { poly.setStrokeStyle({color: allmarkers[m.key].hicolor}) } catch(err) { }
        });
        GEvent.addListener(poly, "mouseout", function() {
            setcursor();
            if (editmode==0) try { poly.setStrokeStyle({color: allmarkers[m.key].clcolor}) } catch(err) { }
        });
        poly.parnt = this;

        return poly;
    }

    // Generate infowindow contents
    this.genIFW = function() {

        // What to do if no thumb supplied 
        var altthumb = Array();
        if (this.th=='') {
            if (this.pl) { var altthumb = this.pl[0]; }
            else if (this.fl) {
                for (var c=0; c<this.fl.length; c++) {
                    var altthumb = ftot(this.fl[c]);
                    if (altthumb.length > 0) break;
                }
            } else if (this.al) {
                for (var c=0; c<this.al.length; c++) {
                    var altthumb  = atot(this.al[c]);
                    if (altthumb.length > 0) break;
                }
            }
        }

        // Generate content
        var content = ''
        if (this.al) {
            var dummy = Array();
            for (var c=0; c<this.al.length; c++) dummy[c] = mkaurl(this.al[c]);
            content += '<p class="a">Albums:<br\/>'+ dummy.join('<br\/>') +'<\/p>';
        }
        if (this.fl)  {
            var dummy = Array();
            for (var c=0; c<this.fl.length; c++) dummy[c]=mkfurl(this.fl[c]);
            content += '<p class="f">Folders:<br\/>'+ dummy.join('<br\/>') +'<\/p>';
        }
        if (this.pl)  {
            var dummy = Array();
            for (var c=0; c<this.pl.length; c++) dummy[c]=mkpurl(this.pl[c]);
            content += '<p class="p">Photos:<br\/>'+ dummy.join('<br\/>') +'<\/p>';
        }

        var lnames = [];
        for (var c=0; c<this.lys.length; c++) lnames.push(layers[this.lys[c]].title);

        var ifw = '<p class="greytext">'+lnames.join(', ');
        if (this.sub) ifw += br+this.sub;
        ifw += '<\/P>';
        if (this.desc) ifw += '<p class="desc">'+this.desc+'<\/p>';

        var thurl = '';
        var ifwtable = '';
        if (content+this.th!='') { // NOT empty
            if (this.th!='') {thurl = mkthurl(this.th); }
            else if (altthumb.length > 0) {thurl = mkthurl(altthumb);}
            var hgt = Math.max(this.dims[0], this.dims[2]);
            ifwtable = (thurl=='')?tabledef:tabledef
                + '<th style="height:'+hgt+'px">' + thurl + '<\/th>';
            ifwtable += '<td style="width:'+this.dims[1]+'px;height:'+hgt+'px">'
                + content + '<\/td><\/tr><\/table>';
        }
        return [ifw, ifwtable]
    }

    // Create tabbed infowindow content based on content
    this.loadContent = function() {
        if (!this.Phtab) {
            var data = this.genIFW();
            this.Phtab = data[1];
            this.tabhead = data[0];
        }

        var tabs = new Object();
        var title = '<div class="maptitle">'+this.name+'<\/div>';

        if ((this.Phtab!='')||((!this.ISBNtab)&&(!this.linkstab))) {
            tabs['Photos'] = title+this.tabhead+this.Phtab;
        } else { title = title+this.tabhead; }
        if (this.ISBNtab) tabs['Books'] = title+this.ISBNtab;
        if (this.linkstab) tabs['Links'] = title+this.linkstab;

        ntabs = [];
        for (var i in tabs) {
            ntabs.push(new GInfoWindowTab(i, tabs[i]));
        }
        return ntabs;
    }

    // Calculate level from content
    this.calc_level = function() {
        if (this.al) {         // Have Albums
            if (this.fl) return 2; // + Folders
            if (this.pl) return 1; // + Photos
            return 0;              // Only
        }
        if (this.fl) return 3;     // Folders, no albums
        if (this.pl) return 4;     // Photos Only
        return this.dlevel;        // Nothing - empty point
    }
    //--------------------------------------------------

    // First absorb content from 'pm'
    this.name = pm.nm;
    var mvars = ['desc', 'key', 'lys', 'th', 'ISBNs', 'links'];
    if (editmode==0) mvars = mvars.concat(['sub', 'al', 'fl', 'pl', 'dims']);
    for (var j=0; j<mvars.length; j++) { if (pm[mvars[j]]) this[mvars[j]] = pm[mvars[j]]; }
    if (!this.th) this.th = '';

    // Next define collection-specific content
    if (this.lys.length==0) {
        this.lys = ['Orphans'];
        pm.lcolors = ['000000'];
    }
    // Choose first collection for initialization (except zoom)
    // Just in case an undefined layer is supplied;
    coll = (this.lys[0] in layers)?layers[this.lys[0]]:layers['Orphans'];
    if (pm.lcolors) {
        this.lcolors = new Object();
        for (var c=0; c<pm.lcolors.length; c++) this.lcolors[this.lys[c]] = '#'+pm.lcolors[c];
    }

    this.dlevel = pm.lw[0];
    this.weight = pm.lw[1];
    this.zoom   = pm.lw[2];
    if (editmode==0) {
        this.level = this.calc_level();

        // Choose zoom based minimum of (zl, z[dl/ml]_last coll)
            // Last collection is special with most wide-zoom
        var zm = maxzoom;
        lastcoll = layers[this.lys[this.lys.length-1]];
        if (lastcoll.dlevel) {
            var ml = (this.dlevel==-1)?lastcoll.dlevel:this.dlevel;
            zm = lastcoll.zooms[ml];
        }
        this.zoom = (this.zoom==-1)?zm:Math.min(this.zoom, zm);

        this.set_attr(coll);
    }

    // Finally content and infowindow
    if (editmode!=0) {
        this.afp = pm.afp;
    } else {
      if (pm.links) this.linkstab = mklink(pm.links, pm.nm);
        if (pm.ISBNs) {
            this.ISBNtab = this.ISBNs.split(',');
            for (var i=0; i<this.ISBNtab.length; i++) this.ISBNtab[i] = amazon_ad(this.ISBNtab[i]);
            this.ISBNtab = this.ISBNtab.join(' ');
        }
    }

    // Create marker and add to map
    if (('ps' in pm)&&(pm.ps.length < 40)) {   // Point

        var point = eval(pm.ps);
        if (editmode!=0) {
            var def_icon=(this.lys[0]=="Orphans")?new GIcon(bIcon):new GIcon(oIcon); }
        else { var def_icon = createIcon(this.ccolor, this.cmtype)[0]; }

        var m = this.createMarker(point, def_icon);

        if (editmode==0) {
            GEvent.addListener(m, "click", function(latlng) {
                var htmlcontent = m.parnt.loadContent();
                m.openInfoWindowTabsHtml(htmlcontent, {maxWidth:550});
            });
        } else {
            this.level = pm.lw[3];
            this.mlevel = (this.level==-1)?coll.dlevel:this.level;
            var zm = editingzooms[this.mlevel];
            this.zoom = (this.zoom==-1)?zm:this.zoom; //Math.min(this.zoom, zm);
        }

        // Finally add to markerManager
        if (!(this.zoom in markersbyzoom)) markersbyzoom[this.zoom] = [];
        markersbyzoom[this.zoom].push(m);

    } else {            // Line
        if (pm.encoding) {
            this.encoding = pm.encoding;
            this.zoomstr = pm.zoomstr;
            var points = null;
        } else {
            var points = eval(pm.ps);
        }

        var m = this.createPolyLine(this.clcolor, coll.widths[this.weight], coll.opacity, points);
        if (editmode==0) definepolywindow(m);
        map.addOverlay(m);
    }

    m.state = 0;    // for editing, later
    m.key = this.key;
    this.marker = m;

    // Add to markerlist of appropriate layers
    for (var i=0; i<this.lys.length; i++) {
        ck = this.lys[i];
        if (ck in layers) {
            cl = layers[ck];
            cl.markers.push(this.key);
        }
    }

}


// ------------------------------------------------------------
//   Helper Functions
// ------------------------------------------------------------

// loop over layers and load
function loadLayers(clist) {
    for (var i=0; i<clist.length; i++) {
        clayer = new RLayer(clist[i]);
        layers[clayer.name] = clayer;
    }
}

// loop over markers and load
function loadMarkers(mlist) {
    var dd = new Date();
    var stime = dd.getTime();

    for (var i=0; i<mlist.length; i++) {
        cmarker = new RMarker(mlist[i]);
        allmarkers[cmarker.key] = cmarker;
    }

    for (var z in markersbyzoom) mgr.addMarkers(markersbyzoom[z], z);
    mgr.refresh();

    // --- Statistics diagnostic for zoom distribution
    // GLog.write('Zoom MaxMarkers');
    // for (var z=0; z< maxzoom; z++) GLog.write(z+' '+mgr.getMarkerCount(z););

    var dd = new Date();
    window.status = dd.getTime()-stime;
}

// Isolate definition of infowindow for polyline
function definepolywindow(line) {
    // GEvent.addListener wants to have its own namespace and not be part of a loop
    GEvent.addListener(line, "click", function(latlng) {
        htmlcontent = line.parnt.loadContent();
        map.openInfoWindowTabsHtml(latlng, htmlcontent, {maxWidth:550});
    });
}

// Load sidebar data based on layers loaded from JSON file
function loadsidebar() {

    var sidebar_data = new Array();
    for (var cl=0; cl<sortedlayers.length; cl++) {
        c = layers[sortedlayers[cl]];
        if (c.markers.length > 0) {
            sidebar_data.push('<tr><td><input type="checkbox" id="'+c.name+
                'box" value="'+c.name+'" onclick="javascript:boxclick(this);" checked="checked"\/><\/td>\n            '+
                '<td><img src="'+geticonurl(c.color, 'sm')+'" alt="icon"\/><\/td>\n            <td><b>'+
                c.title+'<\/b> '+clean2(c.desc)+'<\/td><\/tr>');
        }
    }
    sidebar = sidebar_data.join('\n        ');
    document.getElementById("sidebar_data").innerHTML = '<table>'+sidebar+'<\/table>'
}

// Sorting function to sort layers by Title
function layersbyTitle(a,b) {
    if (layers[a].title > layers[b].title) {
        return 1;
    } else if (layers[a].title < layers[b].title) {
        return -1;
    } else {
        return 0;
    }
}

// Utility function to test if marker is visible in other layers
function markervisible(mk) {

    amp = allmarkers[mk];
    var visible = false;
    for (var c=0; c<amp.lys.length; c++) {
        if (layers[amp.lys[c]].isVisible) {
            visible = true;
            break;
        }
    }

    return [visible, layers[amp.lys[c]]];
}

// == handler for clicked checkbox ==
function boxclick(box) {
    clayer = layers[box.value]
    if (box.checked) {
        clayer.show();
    } else {
        clayer.hide();
    }
}

// --- ICON HANDLING

// determine icon url given color and type
function geticonurl(color, mtype) {
    if (typeof(color) != "number") {
        if (mtype=='star') {
            return 'http://chart.apis.google.com/chart?chst=d_map_xpin_letter&chld=pin_star||'+color+'|000000|00FF00'; }
        else {
            szh=(mtype=='sm')?20:32;
            szw=(mtype=='sm')?12:32;
            return 'http://chart.apis.google.com/chart?cht=mm&chs='+szw+'x'+szh+'&chco=FFFFFF,'+color+',000000&ext=.png';}
    } else {
        return iconbase+clt1[color]+iconcodes[mtype];
    }
}

// Create an icon given color and type
function createIcon(color, mtype) {
    if (typeof(color) != "number"){
        if (mtype=='star') {
            var opts = {primaryColor: '#'+color, label:'', addStar:true};
            opts.starPrimaryColor = "#00FF00";
            opts.starStrokeColor = "#000000";
            var nIcon = MapIconMaker.createLabeledMarkerIcon(opts); }
        else {
            szh=(mtype=='sm')?20:32;
            szw=(mtype=='sm')?12:32;
            var opts = {width: szw, height: szh, primaryColor: '#'+color};
            var nIcon = MapIconMaker.createMarkerIcon(opts); }
    } else {
        switch(mtype) {
          case 'sm':  var nIcon = new GIcon(smIcon);break;
          case 'pin': var nIcon = new GIcon(pinIcon);break;
          default:    var nIcon = new GIcon(padIcon);
        }
        nIcon.image = iconbase+clt1[color]+iconcodes[mtype];
    }
    return [nIcon, nIcon.image];
}

// Create links for display
function mklink(links, name) {

    var ll = links.split('\n');
    var nlinks = [];
    for (var i=0; i<ll.length; i++) {
        var nl = ll[i].split('|');
        if (nl.length==1) {nl = [name, nl[0], "Official Website"];}
        else if (nl.length==2) {nl = [nl[0], nl[1], "Official Website"];}
        if (nl[0]!='') { nlinks.push('<DT><A HREF="'+nl[1]+'" target="_blank">'+nl[0]+'<\/A><DD>'+nl[2]); }
    }
    return '<DL>'+nlinks.join('\n')+'<\/DL>'

}

// Initialize an orphan layer
function createOrphanLayer() {
    var coll = new RLayer({
        'name':'Orphans', 'desc':'Orphan Markers', 'title':'_Orphan Markers',
        'color': '000000', 'dcat':0, 'dlevel':2,
        'sitelist': [], 'opacity': 0.6, 'year': '2000',
        'zooms':gp.zooms, 'mtype':gp.mtype, 'widths':gp.widths});
    return coll;
}

// generic hide
function mhide(m) {
    if (m instanceof GMarker) { mgr.removeMarker(m); }
    else if (m instanceof GPolyline) { m.hide(); }
}

// Funtions to construct URLs out of data
function mkaurl(ii) {
    var th = atot(ii);
    var actions = (th.length<4)?'':' onmouseover="chafth([\''+th.join("','")+'\']);" onmouseout="bk();"';
    return '<a href="/Photos/'+ii[0]+'/index-'+prio+'.html"'
        +actions+' target="slideshow">'+ii[3]+'</a>, '+ii[1]+'/'+ii[2];
}
function mkfurl(ii) {
    var th = ftot(ii);
    var actions = (th.length<4)?'':' onmouseover="chafth([\''+th.join("','")+'\']);" onmouseout="bk();"';
    return '<a href="/Photos/'+ii[0]+'/'+ii[1]+'/index-'+ii[1]+'-'+prio+'.html"'
        +actions+' target="slideshow">'+ii[4]+'</a>, '+ii[2]+'/'+ii[3];
}
function mkpurl(ii) {
    // Open movies separately
    if (ii[1]=='Movies') {
        return '<a href="/Photos/'+ii[0]+'/'+ii[1]+'/'+ii[2]
            +'" target="_blank" onmouseover="chmth(this);" onmouseout="bk();">'+
            ii[3]+'</a>, '+ii[4]+'/'+ii[5];
    }
    return '<a href="/Photos/'+ii[0]+'/'+ii[1]+'/index-'+ii[1]+'-'+prio+'.html?pfname='+ii[2]
        +'" target="slideshow" onmouseover="chth(this);" onmouseout="bk();">'+
        ii[3]+'</a>, '+ii[4]+'/'+ii[5];
}
//return thumbs from album and folder
function atot(ii) {
    // Thumb info contained in ii[4:]
    if (ii.length<5) return [];
    var th = ii.slice(4,7);
    th.push(ii[3]);
    return th;
}
function ftot(ii) {
    // Thumb info contained in ii[5:]
    if (ii.length<6) return [];
    var th = ii.slice(5,8);
    th.push(ii[4]);
    return th;
}
function mkthurl(ii) {
    return '<img src="/Photos/'+ii[0]+'/'+ii[1]+'/thumbs/th_'+ii[2]+'" alt="'
        +ii[3]+'" id="ifwthumb" onclick="pic(this);"\/><p class="acaption" id="ifwcap">'
        +ii[3]+'<\/p>';
}

