
function encodeQueryData(data){
   var ret = [];
   for (var d in data){
	   ret.push(encodeURIComponent(d) + "=" + encodeURIComponent(data[d]));
   }
   return ret.join("&");
}
var $id = function(id){
    return document.getElementById(id);
};

var $create = function(name){
    return document.createElement(name);
};

$hasClass = function(ele,cls) {
    try{
		 var has = (ele.className) ? ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)','g')) : false;
		 return has;
    }
    catch(e){
        throw "element has no class attribute";
    }
};

$toggleClass = function(ele,cls) {
    if($hasClass(ele,cls)){
        $removeClass(ele,cls);
    }
    else{
        $appendClass(ele,cls);
    }
};

$appendClass = function(ele,cls) {
	if (!$hasClass(ele,cls)) {
		ele.className += ((!ele.className.length) ? '':" ")+cls;
	}
};

$removeClass = function(ele,cls) {
    if ($hasClass(ele,cls)) {
        var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)','g');
        ele.className = ele.className.replace(reg,' ');
    }
};

function insertAfter(node, referenceNode) {
  referenceNode.parentNode.insertBefore(node, referenceNode.nextSibling);
}

function deepObjCopy(dupeObj) {
    var retObj = {};
    if (typeof(dupeObj) == 'object') {
        if (typeof(dupeObj.length) != 'undefined'){
            retObj = [];
        }
        for (var objInd in dupeObj) {   
            if (typeof(dupeObj[objInd]) == 'object') {
                retObj[objInd] = deepObjCopy(dupeObj[objInd]);
            } else if (typeof(dupeObj[objInd]) == 'string') {
                retObj[objInd] = dupeObj[objInd];
            } else if (typeof(dupeObj[objInd]) == 'number') {
                retObj[objInd] = dupeObj[objInd];
            } else if (typeof(dupeObj[objInd]) == 'boolean') {
                ((dupeObj[objInd] === true) ? retObj[objInd] = true : retObj[objInd] = false);
            }
        }
    }
    return retObj;
}

function f_clientWidth() {
	return f_filterResults (
		window.innerWidth ? window.innerWidth : 0,
		document.documentElement ? document.documentElement.clientWidth : 0,
		document.body ? document.body.clientWidth : 0
	);
}
function f_clientHeight() {
	return f_filterResults (
		window.innerHeight ? window.innerHeight : 0,
		document.documentElement ? document.documentElement.clientHeight : 0,
		document.body ? document.body.clientHeight : 0
	);
}
function f_scrollLeft() {
	return f_filterResults (
		window.pageXOffset ? window.pageXOffset : 0,
		document.documentElement ? document.documentElement.scrollLeft : 0,
		document.body ? document.body.scrollLeft : 0
	);
}
function f_scrollTop() {
	return f_filterResults (
		window.pageYOffset ? window.pageYOffset : 0,
		document.documentElement ? document.documentElement.scrollTop : 0,
		document.body ? document.body.scrollTop : 0
	);
}
function f_filterResults(n_win, n_docel, n_body) {
	var n_result = n_win ? n_win : 0;
	if (n_docel && (!n_result || (n_result > n_docel))){
		n_result = n_docel;
	}
	return n_body && (!n_result || (n_result > n_body)) ? n_body : n_result;
}

/* some date constants */

var DEFAULT_DISTANCE = 75;
var now = new Date();
var now_date = now.getDate();

var yesterdate = new Date();
    yesterdate.setDate(now.getDate()-1); 

var tomorrow = new Date();
    tomorrow.setDate(tomorrow.getDate()+1);

var future = new Date();
    future.setDate(future.getDate()+35);
    
var max_default = new Date();
    max_default.setDate(max_default.getDate()+25);
		
var thisweek = new Date();
    thisweek.setDate(thisweek.getDate()+7);
		
var ldom = new Date();
    ldom.setMonth(ldom.getMonth() +1);
    ldom.setDate(0);
		
var thissun = new Date();
    thissun.setDate( thissun.getDate() + (7-thissun.getDay())%7 );
    
var thismon = new Date();
    thismon.setDate( thismon.getDate() + (7+1-thismon.getDay())%7 );
		
var thisfri = new Date();
    thisfri.setDate( thisfri.getDate() + (5-thisfri.getDay())%7 );

var nextweekstart = new Date();
    nextweekstart.setDate(nextweekstart.getDate() + (7+1-nextweekstart.getDay())%7 );
    nextweekstart.setDate(nextweekstart.getDate()  + 7 );

var nextweekend = new Date();
    nextweekend.setDate(nextweekstart.getDate() +6);
    
var fdonm = new Date();
    fdonm.setMonth(fdonm.getMonth()+1);
    fdonm.setDate(1);

var ldonm = new Date();
    ldonm.setMonth(ldonm.getMonth()+2);
    ldonm.setDate(1);
    ldonm.setDate(ldonm.getDate()-1);

var startdate = now;

/* if(now.getHours() < 6){
    startdate = yesterdate;
} */

var currentNodeRefId = 'category:0';
function treeclick(e, update){
	targ = e.target || e.srcElement;

	//console.log(targ)

	if(targ.tagName == 'A'){
		
		// clear the class for the last link
		var par = document.getElementById(currentNodeRefId);
				par.className = '';
		
		// set the class on this link to selected
		targ.className = 'selected';
		currentNodeRefId = targ.id;
		
		// the selected is a link in level 2
		if(targ.parentNode.parentNode.parentNode.className == 'parent selected'){
			// abort here so we dont hide parent trees
			select_category_onchange(update);
			return false;
		}
		
		// the last was a link in level 2
		if(par.parentNode.parentNode.parentNode.className == 'parent selected'){
			par.parentNode.parentNode.parentNode.className = 'parent';
			// hide level 2
		}
		// the last was a link in level 1
		else {
			par.parentNode.className = 'parent';
			// hide level 1
		}
		
		// the selected is a link in level 2
		if(targ.parentNode.parentNode.parentNode.className == 'parent'){
			targ.parentNode.parentNode.parentNode.className = 'parent selected';
			// stick level 2
			select_category_onchange(update);
			return false;
		}
		// the selected is a link in level 2
		else {
			// stick level 1
			targ.parentNode.className = 'parent selected';
		}
		
		
		select_category_onchange(update);
		return false;
		/* e.stopPropagation();
		e.preventDefault();
		return false; */
		//document.getElementById(currentNodeRefId).className = ''
	}
	
}


var current_page = 1;
var tries = 0;
var filters = {
    start:null,
    end:null,
    category:'0',
    city:'all',
    distance:DEFAULT_DISTANCE,
    dindex:0,
    page:1,
    
    update_set:function(addHistoryEvent){
    	//console.log('Updating set')
    	EventsBrowser.updateSet(addHistoryEvent);
    },
    
    set_category:function(category_id, category_name){
        // update only if required
        if(this.category == category_id){ 
            return;
        }
        
        this.category = category_id;
        this.reset_page();
        
        _gaq.push(['_trackEvent', 'Events', 'Select category', category_name]);
    },
    
    set_city:function(city_id, city_name, forced){
    	forced = forced || false;
        // update only if required
        if(this.city == city_id){ 
            return;
        }
        
        this.city = city_id;
        this.reset_page();
        
        _gaq.push(['Events', 'Select city', city_name + ' - ' + this.distance]);
    },
    
    set_distance:function(distance){
        // update only if required
        if(this.distance == distance){
            return;
        }
        
        this.distance = distance;
        this.reset_page();
        
        _gaq.push(['Events', 'Select distance', filters.distance]);
    },
    
    set_date:function(start, end){
        // update only if required
        if(this.start && this.end && this.start == start && this.end == end){
            return;
        }
        
        this.start = start.strftime('%Y-%m-%d');
        this.end = end.strftime('%Y-%m-%d');
        this.reset_page();
        
        _gaq.push(['Events', 'Select date', filters.start+' - '+filters.end]);
    },
    
    set_page:function(page){
    	//console.log('Setting page to: ', page)
        this.page = page;
        current_page = page;
    },
    
    set_dindex:function(v){
        this.dindex = v;
    },
    
    unserialize:function(d, forced){
    	var s = null;
    	var e = null;
        if(d.start.length === 0 || d.end.length === 0){
            //console.log('Dates',d.start.length, d.end.length);
            s = now;
            e = future;
            this.start = s.strftime('%Y-%m-%d');
            this.end = e.strftime('%Y-%m-%d');
        }
        else {
            try{
                s = parse_iso_date(d.start);
                e = parse_iso_date(d.end);
            }
            catch(ex){
            }
            // if start is less than now, make start now, and end in same proportion
            if(s < reset_time(now)){
                var delta = days_between(s, e);
                
                this.start = now.strftime('%Y-%m-%d');
                this.end = new Date();
                this.end.setDate(this.end.getDate() + delta);
                this.end = this.end.strftime('%Y-%m-%d');
                
            }
            else {
                this.start = d.start;
                this.end = d.end;
            }
        }
        
        this.category = d.category;
        this.city = d.city;
        this.distance = d.distance;
        this.page = d.page;
        this.dindex = d.dindex;
        
    },
    
    serialize:function(){
        return {
            'start':this.start,
            'end':this.end,
            'category':this.category,
            'city':this.city,
            'distance':this.distance,
            'page':this.page,
            'dindex':this.dindex
        };
    },
    
    reset_page:function(){
        this.page = 1;
        current_page = 1;
    }
    
};

function reset_time(d){
    d.setHours(0);
    d.setMinutes(0);
    d.setSeconds(0);
    return d;
}

/* Event handlers */

function select_city_onchange(){
    var select_city = $id('select-city');
    var city = select_city.options[select_city.selectedIndex];
    
    var city_id = city.value;
    var city_name = city.text;
    
    if(city_id == 'all'){
        EventsBrowser.hide_select_distance();
    }
    else {
        EventsBrowser.show_select_distance();
    }
    
    filters.set_city(city_id, city_name);
    filters.update_set(true);
    
    if(city_id != 'all'){
        regeo(text);
    }
}

function select_distance_onchange(update){
    var select = document.getElementById('select-distance');
    
    filters.set_distance(select.options[select.selectedIndex].value);
    filters.update_set(true);
}

function select_category_onchange(update){
    
    var catnode = document.getElementById(currentNodeRefId);
    
    if(!catnode){
        return false;
    }
    
    if(update){
		var name = catnode.innerHTML;
		filters.set_category(currentNodeRefId.split(':')[1], name);
		filters.update_set(true);
    }
}


// NOTE: this is called first if there is any document fragment
function navCallback(e) {
	var token = (e.token === null) ? 'null' : '\u201C' + e.token + '\u201D';
	//goog.dom.setTextContent(output, token);
	try{
		newLocation = e.token;
		yourListener(newLocation, null);
	}catch(err){
		//console.error(err);
	}
}

var EventsBrowser = {};

EventsBrowser.history = new goog.History();
goog.events.listen(EventsBrowser.history, goog.History.EventType.NAVIGATE, navCallback);

EventsBrowser.show_select_distance = function(){
	$id('box-select-distance').style.display = 'block';
};
EventsBrowser.hide_select_distance = function(){
	$id('box-select-distance').style.display = 'none';
};
EventsBrowser.xlat_date_range = function(v){
    switch(v){
        case 'today':        
            return [new Date(), new Date(), true];
        case 'tomorrow':       
            return [tomorrow, tomorrow, true];
        case 'this weekend':   
            return [thisfri, thissun, true];
        case 'this week':      
            return [new Date(), thissun, true];
        case 'next week':      
            return [nextweekstart, nextweekend, true];
        case 'this month':     
            return [new Date(), ldom, true];
        case 'next month':     
            return [fdonm, ldonm, true];
        default:
            return [startdate, future, true];
    }
};
EventsBrowser.page_move = function(event){
	var pageNode = (window.event) ? window.event.srcElement : event.target;
    var page = parseInt(pageNode.innerHTML, 10);
    
    filters.set_page(page);
    filters.update_set(true);
    _gaq.push(['Events', 'Browse event: Select page', page]);
};

EventsBrowser.page_next = function(){
    filters.set_page(current_page+1);
    filters.update_set(true);
    _gaq.push(['Events', 'Browse event: Click next page']);
}; 

EventsBrowser.page_previous = function(){
    filters.set_page(current_page-1);
    filters.update_set(true);
    _gaq.push(['Events', 'Browse event: Click previous page']);
};



FORCED = false;
EventsBrowser.updateSet = function(ADDHISTORYEVENT){
    try {
    	window.FORCED = ADDHISTORYEVENT;
        document.getElementById('throbber').style.display = 'block';
        var serfilters = filters.serialize();
        var iop = new goog.net.XhrIo();
		
		goog.events.listen(iop, goog.net.EventType.COMPLETE, function(e) {
			 var xhr = e.target;
				try{
					var obj = goog.json.unsafeParse(iop.getResponseText());
					//console.log('Updating results...');
					if(ADDHISTORYEVENT){
						EventsBrowser.add_search_history();
					}
					
					goog.dom.$("throbber").style.display = 'none';
					updateList(obj);
					
					//var pos = Position.cumulativeOffset($id('table-event-finder'));
					//if(f_scrollTop() > pos[1]-80){
					//	window.scroll(0, pos[1]-80);
					//}
					
					var rect = goog.style.getPageOffset(goog.dom.getElement("table-event-finder"));
					if(f_scrollTop() > rect.y-80){
						window.scroll(0, rect.y-80);
					}
					
					//console.log(f_scrollTop(), pos[0], pos[1])
					
			
					tries =0;
				}catch(err){
					//console.error(err);
				}
		});
		
		goog.events.listen(iop, goog.net.EventType.ERROR, function(e) {
				//console.log('Retrying');
		  var xhr = e.target;
		  if(tries < 1){
				tries++;
				EventsBrowser.updateSet();
				return;
			}
			document.getElementById('throbber').style.display = 'none';
			alert(_('There was a problem. Please try to reselect the filters'));
			
			
			tries = 0;
		});
		
		iop.send('/events/api/getevents?'+encodeQueryData(serfilters));
    }catch(e){
    	//console.log(e);
    }
};

EventsBrowser.add_search_history = function(){
	//historyStorage.put("filters", filters.serialize());
	//console.log('Setting search history to:', filters);
    EventsBrowser.addHistoryEvent([filters.start,filters.end,filters.category,filters.city,filters.distance,filters.page,filters.dindex].join(','));
};

EventsBrowser.addHistoryEvent = function(name, value) {
	/* Our event handler to add history change events */
	EventsBrowser.history.setToken(name);
	//dhtmlHistory.add(name, value);
};

EventsBrowser.update_ui = function(filters, update){
	var select_city = $id('select-city');
    var select_distance = document.getElementById('select-distance');
    var select_date = $id('select-date');
    
    for(var i=0; i<select_city.options.length; i++){
    if(select_city.options[i].value == filters.city){
            select_city.selectedIndex = i;
    }
    }
        
    if(filters.city != 'all'){
        EventsBrowser.show_select_distance();
    }
    else {
        EventsBrowser.hide_select_distance();
    }
    
    for(i=0; i<select_distance.options.length; i++){
        if(select_distance.options[i].value == filters.distance){
            select_distance.selectedIndex = i;
        }
    }
        
    select_date.selectedIndex = filters.dindex;
    
    var treenode = $id('category:'+filters.category);
    if(treenode){
		var e = {'target':treenode};
		treeclick(e, update);
    }
};

function select_date_range_onchange(){
    var select_city = $id('select-date');
    
    var v = select_city.options[select_city.selectedIndex];
    var d = EventsBrowser.xlat_date_range(v.value);
    
    filters.set_dindex(select_city.selectedIndex);
    filters.set_date(d[0], d[1]);
    filters.update_set(true);
}

/* Controller */

function updatePoints(points){
    var minLat = Number.MAX_VALUE;
    var maxLat = Number.MIN_VALUE;
    var minLon = Number.MAX_VALUE;
    var maxLon = Number.MIN_VALUE;
    
    //console.log(points)
    if(!points){
    	return;
    }
    if(points.length < 2){
    	return;
    }
    //var polylinePoints = [];
    //1.
    //for(var i=0; i<points.length;i++)
    
    var x =0;
    for(var i in points){
        
        mapObject = points[i][0];
        //var currentLatLon = new LatLng(mapObject.latitude, mapObject.longitude);
        //polylinePoints.push(currentLatLon);
    
        if(mapObject.lat() > maxLat){
            maxLat = mapObject.lat();
        }
        if(mapObject.lat() < minLat){
            minLat = mapObject.lat();
        }
        if(mapObject.lng() > maxLon){
            maxLon = mapObject.lng();
        }
        if(mapObject.lng() < minLon){
            minLon = mapObject.lng();
        }
        x++;
    }
    
    if(x === 0){
    	return;
    }
    if(!maxLat || !minLat || !maxLon || !minLon){
    	return;
    }
    //2.
    var centerPointLat = minLat + (maxLat - minLat)/2;
    var centerPointLon = minLon + (maxLon - minLon)/2;
    var centerPoint = new GLatLng(centerPointLat,centerPointLon);
    
    //3.
    var bounds = new GLatLngBounds(
    new GLatLng(minLon, minLat),
    new GLatLng(maxLon, maxLat)
    );
    
    //4.
    map.setZoom(map.getBoundsZoomLevel(bounds)-1);
    //5.
    map.setCenter(centerPoint);

}

function updateList(items){
    
    var list = document.getElementById('box-list-events');
    try {
        if(items && (items[0].count === 0 || items.length <= 1) || !items){
            document.getElementById('search-results-info').innerHTML = '&nbsp;';
            var str = [];
            str.push('<div class="notification-light">');
            str.push('<p>'+_('No events found. Please try to change your selection.')+'</p>');
            str.push('<h2>' + _('Do you have something to add?') + '</h2>');
            str.push('<p>'+_('Sign in and create and an event.')+'</p>');
            str.push('</div>');
            
            list.innerHTML = str.join(''); 
            return false;
        }
        
        mgr.clearMarkers();
        
        // use item zero as the page info
        var df = document.createDocumentFragment();
        
        half = Math.round(items / 2 );
        
        var table = goog.dom.createDom('table',{'class':'table-events'});
        var tbody = goog.dom.createDom('tbody');
        
        // keep lat/lngs for ids
        var points = {};
        
        for(var i=1; i < items.length; i++){
            var ic = 0;
            if(items[i].lat !== 0 && items[i].lng !== 0){
                ic = getRandomIcon();
                points[items[i].id] = [new GLatLng(items[i].lat,items[i].lng),items[i],ic];
            }
            
            var is_grey = i % 2 === 0;
            tbody.appendChild(listItem(items[i], ic, is_grey));
        }
        
        table.appendChild(tbody);
        df.appendChild(table);
        
        for(i in points){
            if(typeof points[i][0] == 'object'){
                var marker = new GMarker(points[i][0], { icon:iconcache[points[i][2]], draggable:true });
                marker.bindInfoWindowHtml('<a href="/events/'+points[i][1].id+'"><img style="margin-right:6px;float:left;height:58px" src="'+points[i][1].image+'"/></a><a href="/events/'+points[i][1].id+'">'+points[i][1].name+'</a><div>'+points[i][1].date+'</div>');
                mgr.addMarker(marker, 3);
            }
        }
        mgr.refresh();
        updatePoints(points);    
    } 
    catch(e){
        //alert('Error! '+e.message)
        //console.error(e.message)
    }
    document.getElementById('search-results-info').innerHTML = '<div>'+items[0].info[0]+'</div><div>'+items[0].info[1]+'</div>';
    list.innerHTML = '';
    list.appendChild(df);
    list.appendChild(get_page_list(items));
}

/* Builders */

function listItem(data, ic, ig){
    var row = null;
    var cell = null;
    var link = null;
    var header = null;
    var box = null;
    var label = null;
    var span = null;
    
    var i = new Image();
        i.src = data.image;
    
    // *****************
    // event listing row
    row = goog.dom.createDom('tr', {'class':'event' + (data.is_today == 1 ? ' today' : '')}, '');
    if(ig){
        row.className+= ' odd';
    }
    
    // *****************
    // image cell
    cell = goog.dom.createDom('td', {'class':'cell-event-image'});
    
    if(data.image){
    	var imgr = goog.dom.createDom('img', {'src':data.image},'');
    	var imglink = goog.dom.createDom('a', {'href':'/events/'+data.id}, imgr);
    	var imgbox = goog.dom.createDom('div', {'class':'flyer'}, imglink);
        cell.appendChild(imgbox);
    }
    else {
        cell.innerHTML = '&nbsp;';
    }
    
    row.appendChild(cell);
    
    // info cell 
    
    cell = goog.dom.createDom('td', {'class':'cell-event-flag'});
    // flag
    if(ic>=0){
        try {
        var a = $create('a');
        a.innerHTML = '';
        a.onclick =   function (e){
            try{
                var pos = Position.cumulativeOffset(document.getElementById('cell-events-map'));
                window.scroll(0,pos[1]-30);
                map.setCenter(new GLatLng(data.lat,data.lng), 14);
            }catch(ex){
                //alert(e)
            }
	        
        }; 
        var flag = document.createElement('img');
        flag.className = 'flag';
        flag.src = iconcache[ic].image;
        
        //GEvent.addListener(a, "click", onflagclick);
        a.appendChild(flag);

        } catch(e){
            //alert(e)
        // console.error(e);
        }
    }
    
    cell.appendChild(a);
    row.appendChild(cell);
    
    
    // ***************
    // title/venue main cell
    cell = goog.dom.createDom('td', {'class':'cell-event-main'});
    
    // title link
    link = goog.dom.createDom('a', {'href':'/events/'+data.id}, data.name);
    // title header
    header = goog.dom.createDom('h3', null, link);
    
    cell.appendChild(header);
    
    var dtbox = goog.dom.createDom('div',null,'');
    if(data.is_today == 1){        dtbox.appendChild(goog.dom.createDom('span', {'class':'is-today'}, goog.dom.createDom('label', null, _('Today!'), ' ')));    }
    if(data.recur){    	dtbox.appendChild(goog.dom.createDom('span', {'class':'recurrence'}, data.recur));    }
    
    dtbox.appendChild(goog.dom.createDom('span', {'class':'date-start'}, data.date));
    
    if(data.date_end){
    	dtbox.appendChild(goog.dom.createDom('span', {'class':'date-separator'}, ' - '));
    	dtbox.appendChild(goog.dom.createDom('span', {'class':'date-end'}, data.date_end));
    }
    
    cell.appendChild(dtbox);
    cell.appendChild(goog.dom.createDom('div',{'class':'category'}, data.category_name));
    
    
    var venuelink = goog.dom.createDom('span', {'class':'venue-name'}, goog.dom.createDom('a', {'href':'/venues/'+data.venue_id}, data.venue_name));
    var locbox = goog.dom.createDom('div',{'class':'location-line'}, venuelink);
    
    if(data.city_name){
    	var citystr = '(' + data.city_name + ')';
    	locbox.appendChild(goog.dom.createDom('span',{'class':'city-name'}, citystr));
    }
    
    cell.appendChild(locbox);
    
    if(data.price && data.price.length >0 && data.price != ' '){
        // price label
        label = goog.dom.createDom('label', {'class':'label-price'}, _('Price'));
        // price value
        span = goog.dom.createDom('span', null, data.price);
        box = goog.dom.createDom('div', null, label, span);
        // price box
        cell.appendChild(box);
    }
    
     // user box
     link = goog.dom.createDom('a', {'href':'/users/'+data.user_id}, data.user_alias);
    // user box    
     box = goog.dom.createDom('div', {'class':'posted-by'}, link);
    /* box.innerHTML = '<label>'+_('Posted by')+'</label>'; */
    cell.appendChild(box); 
    
    // body
    body = goog.dom.createDom('div',null, data.body);
    cell.appendChild(body);
    
    row.appendChild(cell);
    
    // **************
    // date/time cell
    //cell = $create('td');
    //cell.className = 'cell-event-date';
    return row;
    /* 
    if(data.flags & 1 === 1){
        desc.innerHTML = _('You have marked this event as interesting');
    }
    else {
         var a = document.createElement('a');
            a.className = 'button-interest';
            div.appendChild(a) 
    }
    */
}

function get_page_list(items){
    // items:0 has pages (total), page(current on server), count(count of all)
    
    var df = document.createDocumentFragment();
    
    page_count = items[0].pages;
    current_page = items[0].page;
    total = items[0].count;
    filters.page = current_page;

    if(page_count == 1 || page_count === 0){
        return df;
    }
    
    var span = null;
    
    var leftnodes = [];
    var centernodes = [];
    var rightnodes = [];
    
    if(current_page != 1){
    	span = goog.dom.createDom('a', null, _('Previous'));
    	goog.events.listen(span, goog.events.EventType.CLICK, EventsBrowser.page_previous, false, this);

        leftnodes.push(span);
    }
    
    for(var i=1; i <= page_count; i++){
        span = $create('a');
        
        if(filters.page == i){
        	span = goog.dom.createDom('a', {'class':'ui-page-navigation-current-page'}, i.toString());
        }
        else {
        	span = goog.dom.createDom('a', {'class':'ui-page-navigation-page'}, i.toString());
        }
        
        if(filters.page != i){
        	goog.events.listen(span, goog.events.EventType.CLICK, EventsBrowser.page_move, false, span);
        }
        centernodes.push(span);
    }
    
    if(current_page < page_count){
        span = goog.dom.createDom('a', null, _('Next'));
        goog.events.listen(span, goog.events.EventType.CLICK, EventsBrowser.page_next, false, this);
        rightnodes.push(span);
    }
    
    var left = goog.dom.createDom('td', { 'class': 'ui-page-navigation-previous' }, leftnodes);
    var center = goog.dom.createDom('td', { 'class': 'ui-page-navigation-pages' }, centernodes);
    var right = goog.dom.createDom('td', { 'class': 'ui-page-navigation-next' }, rightnodes);
    
    var tbody = goog.dom.createDom('tbody', null, goog.dom.createDom('tr', null, left, center, right));
    var table = goog.dom.createDom('table', {'class':'ui-page-navigation'}, tbody);
    
    var div = goog.dom.createDom('div', {'class':'ui-page-navigation-box'}, table); 
    
    df.appendChild(div);
    return df;

}

var iconmarkers = [
    '/styles/maps/mm_20_red.png'
,   '/styles/maps/mm_20_green.png'
,   '/styles/maps/mm_20_blue.png'
,   '/styles/maps/mm_20_yellow.png'
,   '/styles/maps/mm_20_orange.png'
,   '/styles/maps/mm_20_purple.png'
//,   '/styles/maps/mm_20_brown.png'
//,   '/styles/maps/mm_20_black.png'
,   '/styles/maps/mm_20_white.png'
,   '/styles/maps/mm_20_gray.png'
];
var iconcache = [];
var iconlasti = -1;

function createIconCache(){
    for(var i=0; i<iconmarkers.length; i++){
        var tinyIcon = new GIcon();
        tinyIcon.image = iconmarkers[i];
        tinyIcon.shadow = "/styles/maps/mm_20_shadow.png";
        tinyIcon.iconSize = new GSize(12, 20);
        tinyIcon.shadowSize = new GSize(22, 20);
        tinyIcon.iconAnchor = new GPoint(6, 20);
        tinyIcon.infoWindowAnchor = new GPoint(5, 1);
        iconcache.push(tinyIcon);
    }
}

/* function createIconCache(){
    colors = 'b g r'.split(' ')
    for(var j=0; j<colors.length;j++){
        for(var i=1; i<50; i++){
            var tinyIcon = new GIcon();
            tinyIcon.image = "/styles/events/flags/icon"+colors[j]+i+".png";
            tinyIcon.shadow = "/styles/events/flags/shadow50.png";
            tinyIcon.iconSize = new GSize(12, 20);
            tinyIcon.shadowSize = new GSize(22, 20);
            tinyIcon.iconAnchor = new GPoint(6, 20);
            tinyIcon.infoWindowAnchor = new GPoint(5, 1);
            iconcache.push(tinyIcon)
        }
    }
} */

function getRandomIcon(){
    var newi = Math.floor(Math.random()*(iconcache.length));
    
    // dont repeat right away
    if(newi == iconlasti){
        newi = Math.floor(Math.random()*(iconcache.length));
    }
    
    iconlasti = newi;
    return newi;
}
    
    
/* dhtmlHistory.create({
    toJSON: function(o) {
            return Object.toJSON(o);
    }
    , fromJSON: function(s) {
            return s.evalJSON();
    }
}); */

function yourListener(newLocation, historyData) {
    //console.log($id('select-date').options[0])
    
    if(newLocation && newLocation.toString().length){
    	//console.log('Loaded from history',newLocation);
        var splt = newLocation.split(',');
        
        if(splt.length == 7){
        	var dd = {
                start:splt[0],
                end:splt[1],
                category:splt[2],
                city:splt[3],
                distance:splt[4],
                page:splt[5],
                dindex:splt[6]
            };
            
            if(typeof dd.start == 'undefined' || typeof dd.end == 'undefined'){
            	filters.set_date(startdate, future);
            }
            filters.unserialize(dd);
            filters.update_set(false);
            var s = filters.start;
            var e = filters.end;
            
            if(s == e){
                $id('select-date').options[0].innerHTML = s;
            }
            else {
                
                $id('select-date').options[0].innerHTML = s + ' - ' + e;
            }
            
            EventsBrowser.update_ui(filters, false);
        }
	}
	else {
		if(CURRENT_LOCATION && filters.city == 'all'){
	    	//console.log(CURRENT_LOCATION);
	    	filters.set_city(CURRENT_LOCATION[0], CURRENT_LOCATION[1], true);
	    }
	    
	    filters.set_date(startdate, future);
	    EventsBrowser.update_ui(filters, false);
	    // update the set without adding a history entry
	    EventsBrowser.updateSet(false);
	}
}



goog.events.listen(window, goog.events.EventType.LOAD, function(){
    createIconCache();
    initialize_map();
    try {
    	if(CURRENT_LOCATION && filters.city == 'all'){
	    	//console.log(CURRENT_LOCATION);
	    	filters.set_city(CURRENT_LOCATION[0], CURRENT_LOCATION[1], true);
	    }
	    
	    EventsBrowser.history.setEnabled(true);
	    
	    var location = EventsBrowser.history.getToken();
	    if(location && location.length > 0){
			//console.log('initialize complete. loaded from history');
			return;
	    }
	    
	    filters.set_date(startdate, future);
	    
	    
	    EventsBrowser.update_ui(filters, false);
	    // update the set without adding a history entry
	    EventsBrowser.updateSet(false);
	    
    }
    catch (err){
    alert(err.message);
    }
});

