// vim: sw=4:ts=4:nu:nospell

/**
 * HyperCities collectionList Object
 *
 * @author    Chen-Kuei Lee
 * @copyright (c) 2008, by HyperCities Tech Team
 * @date      2008-12-22
 * @version   $Id$
 *
 */

HyperCities.collectionList = function() {
    // do NOT access javascript generated DOM from here; elements don't exist yet

    // Private variable goes here
    var _id        = "[HyperCities.collectionList] ",

    // Map Related Variables
    _mapBounds  = null,
    _mapZoom    = null,
    _HMarker    = null,
    _oldBaseMap = null,

    // Time Related Variables
    _timespan  = null,

    // intelliList Related Variables
    _initialized   = false,
    _doRender      = true,
	_originalMode  = HyperCities.config.MODE_DEFAULT,
    _opened        = [],  // Folders that are opened
    _checked       = [],  // Checkers that are checked
    _objects       = [],  // All Objects that in current bounding box
    _citations     = [],  // Citations for objects
    _updated       = [],  // Object or Collection that has been updated
    _skipList      = [],  // Root Level Collection Id, don't update
    _progressCount = 0,
    _queuedOperations = [], // Queued actions to take after an update of the collectionList is complete.
                            // This is used by snapshots and permalinks.

	// CSS classes constant used by treeview
	CLASSES = {
		main: "HCTreeview",
		folder: "folder",
		folderLink: "folderLink",
		marker: "marker",
		markerLink: "markerLink",
		collection: "collection",
		narrative: "narrative",
		editItem: "editItem",
		item: "item",
		noItem: "noItem",
		checkBox: "folderChecker",
		noCheckBox: "noChecker",
		external: "external",
		checked: "checked",
		enabled: "enabled",
		loading: "loading",
		expandable: "expandable",
		expandableHitarea: "expandable-hitarea",
		lastExpandable: "lastExpandable",
		lastExpandableHitarea: "lastExpandable-hitarea",
		collapsable: "collapsable",
		collapsableHitarea: "collapsable-hitarea",
		lastCollapsable: "lastCollapsable",
		lastCollapsableHitarea: "lastCollapsable-hitarea",
		last: "last",
		hitarea: "hitarea",
		myCollection: "myCollection"
	};

    /*
	var _cluster   = [];
    var _folders   = [];

    var _subTree   = [];

    var _getCluster    = 0;
    var _objCount      = 0;
    var _clusterCount  = 0;
    var _infoWindowId  = 0;
    var _prevWindowId  = -1;
    var _currentCollectionId = -1;
    var _previousItem = {}
    var _nextItem     = {};
    //jay
    var _syncMap      = false;
    var _maximizeInfoWindow = false;
	var _hasInfoWindowOpen  = false;
    var _oldKmlOverlay = [];
	var _addByNarrative = [];
	var _externalKml = [];	//save the external collection overlay
	
	// David
	var _permalinkedItems = [];
	var _permalinkHideArrows = false;
*/
    // Private method goes here

    var _initMarker = function() {

        var markerOptions, icon = new GIcon(G_DEFAULT_ICON, "images/markerHighlight.png");

        icon.iconSize   = new GSize(78, 76);
        icon.imageMap   = [0, 0, 76, 0, 76, 76, 0, 76];
        icon.iconAnchor = new GPoint(39, 38);

        markerOptions = {
            icon : icon,
            clickable : false,
            hide: true
        };

        _HMarker = new GMarker(new GLatLng(0, 0), markerOptions);
        _HMarker.importance = 10;

        HyperCities.mainMap.addOverlay(_HMarker);
    };

    /**
	 * Given object id, find the index of object in _objects array
	 * @param integer $id
	 * @return integer The index of $linkId in _objects array, or -1 if not found
	 */
    var _getObjectIndexById = function($id) {
        var index;

        index = _objects.length;
        while ( index-- > 0 ) {
//           HyperCities.debug (_id + "Object with id " + _objects[index].id +" at index " +index);
            if ( _objects[index].id === $id )
                return index;
        }

        return -1;
    };

    /**
	 * Setup the Dom Node of Collection Tree
	 * @return jQuery $("#treeviewWrapper") 
	 */
    var _initCollectionList = function () {

        var treeWrapper = $(document.createElement("div")),
			treeRoot    = $(document.createElement("ul"));

        treeRoot.attr("id", "treeviewWrapper")
			.addClass(CLASSES.main)
			.bind('HCUpdateFinish', _adjustLayout)   // Bind Adjust jScrollPane Event
			.bind('click', _listClickHandler);       // Bind Collection List Click Event

        treeWrapper.append(treeRoot);

        // Setup Highlight Marker
        _initMarker();

        // Reset intelliList and append Collection Tree Dom
        HyperCities.intelliList.reset();
        $("#intelliList").append(treeWrapper);

        return treeRoot;
    };

    var _resetCollectionList = function () {

        if ( _HMarker instanceof GMarker ) {
            HyperCities.mainMap.removeOverlay(_HMarker);
        }

        // Clean up variables
        _mapBounds = null;
        _mapZoom   = null;
        _HMarker   = null;
        _timespan  = null;
        _initialized = false;
        _doRender  = true;
        _opened    = [];
        _checked   = [];
        _objects   = [];
        _updated   = [];
        _skipList  = [];
        _progressCount = 0;

    };

    /**
	 * Adjust Layout for jScrollPane
	 */
    var _adjustLayout = function () {
        // TODO: Only adjust layout and remove loading message
        // after all Ajax call is done
        //		HyperCities.debug(_id + "[A2] Progress Count (Adjust Layout) " + _progressCount);

        if ( _progressCount == 0 ) {
            setTimeout( function() {
                $('#intelliList').jScrollPane();
            }, 100);
            $("#loadingMessage").fadeOut("slow");
            for (var i in _queuedOperations) {
                var operation = _queuedOperations.pop();
                _queuedOperations[i].op(_queuedOperations[i].data);
            }
            _queuedOperations = [];
        } // end if ( _progressCount == 0 )

		setTimeout(function(){
			if ($("#loadingMessage"))
	            $("#loadingMessage").fadeOut("slow", function(){HyperCities.debug("Loading message is stuck. Remove it manually.")});
		}, 5000);
    };

    /**
	 * Apply corresponding last class to given Dom Node
	 * @param jQuery $lastNodeDom
	 */
    var _applyLastClass = function ($lastNodeDom) {

        var lastNodeId  = $lastNodeDom.data("id"),
        isItem      = $lastNodeDom.hasClass(CLASSES.item),
		isNoItem    = $lastNodeDom.hasClass(CLASSES.noItem),
        isExternal  = $lastNodeDom.hasClass(CLASSES.external),
        isOpened    = ($.inArray(lastNodeId, _opened) !== -1);

        if ( isItem || isNoItem || isExternal ) {
            $lastNodeDom.addClass(CLASSES.last);
        }
        // Not an Item, it's Collapsable or Expandable
        else if ( isOpened ) {
            $lastNodeDom.addClass(CLASSES.lastCollapsable)
            .find(">div." + CLASSES.hitarea)
            .addClass(CLASSES.lastCollapsableHitarea);
        }
        else {
            $lastNodeDom.addClass(CLASSES.lastExpandable)
            .find(">div." + CLASSES.hitarea)
            .addClass(CLASSES.lastExpandableHitarea);
        }
    };

    /**
	 * Event Delegation Handler to process all click event on collection tree
	 * @param Event $event
	 * @return boolean always return false to prevent event propagation
	 */
    var _listClickHandler = function ($event) {

        var target = $($event.target);

        if ( target.hasClass(CLASSES.hitarea) ) { // user click on Open/Close Folder
            _toggleFolder($event);
        }
        else if ( target.hasClass(CLASSES.checkBox) ) { // user click on CheckBox
            _toggleCheckBox($event);
        }
        else if ( target.hasClass(CLASSES.folderLink) ) { // user click on Folder Link
            _zoomToCollection($event);
        }
        else if ( target.hasClass(CLASSES.markerLink) ) { // user click on Marker Link
            _openItemInfoWindow($event);
        }
        else if ( target.hasClass(CLASSES.editItem) ) { // user click on edit link
            _openItemEditWindow($event);
        }
        else if ( target.hasClass(CLASSES.narrative) ) { // user click on Narrative Link
            _openNarrativePanel($event);
        }
        else {
            //HyperCities.debug(_id + "[A2] Click Collection Tree");
            HyperCities.debug(target);
        }

        return false;
    };

    /**
	 * Check all checkBox that has id equals to $checkerId
	 * @param integer $checkerId
	 */
    var _checkItem = function ($checkerId) {

        var index = 0, totalChildren = 0, showLoading = false,
        folderDom, folderId, folderIndex, isCollection = true, isExternal = false,
        targetDom, children,
        targetArray = $("#treeviewWrapper ." + CLASSES.checkBox + $checkerId);

        index = targetArray.length;
        while ( index-- > 0 ) {
            targetDom = $(targetArray[index]);
			
            targetDom.addClass(CLASSES.checked);

            // Get Folder Information
            folderDom    = targetDom.parent();
            folderId     = $checkerId;
            folderIndex  = $.inArray($checkerId, _opened);
            isCollection = folderDom.hasClass(CLASSES.collection);
            isExternal = folderDom.hasClass(CLASSES.external);

            // If the folder is closed, open the folder
            // Note: External collection can be check but cannot be opened
            if ( isCollection && !isExternal && folderIndex < 0 && typeof(folderId) !== 'undefined' ) {
                _setFolderStatus(folderId, true);
            }

            // Get Children Information
            children = $.map(folderDom.find(">ul>li"), function($node){
                return $($node).data("id");
            });
            totalChildren = children.length;

            // Check each child by yielding processes
            if ( totalChildren > 0 ) {
                // Initialize Progressbar
                if ( !showLoading ) {
                    showLoading = true;
                    //					HyperCities.debug(folderId + " Init " + totalChildren);
                    HyperCities.mainMap.addProgressbarPending(totalChildren);
                }

                setTimeout(function() {
                    var childId = children.shift();

                    _setCheckBoxStatus(childId, true);

                    if ( children.length > 0 ) {
                        setTimeout(arguments.callee, 10);
                    }

                    // Update Progressbar
                    //						HyperCities.debug($checkerId + "(" +folderId + ") Step 1");
                    setTimeout(HyperCities.mainMap.addProgressbarFinished, 10, 1);

                }, 10);
            }

            // Enable the Link, edit Icon and bind hover event for Item
            if ( !isCollection ) {
                $("."+CLASSES.markerLink, targetDom.next())
                .addClass(CLASSES.enabled)
                .hover( function () {
                    HyperCities.collectionList.highlightItem(folderId);
                },
                function () {
                    HyperCities.collectionList.unHighlightItem(folderId);
                })

				$("."+CLASSES.editItem, targetDom.next()).show();
            }


            // Show Loading Icon for External Collection
            if ( isExternal ) {
                folderDom.find("img." + CLASSES.loading).show();
            }

        //TODO:: implement Default Check Logic
        }

        // Overlay the Item and add Google Analytics Event Tracker
        if ( isExternal ) {
            HyperCities.util.eventTracker(HyperCities.config.EVENT_VIEW_COLLECTION, $checkerId);
            // Overlay external KML on Map
            _showKmlOverlay($checkerId);
			$("."+CLASSES.editItem, targetDom.next()).show();
        }
        else if ( isCollection ) {
            HyperCities.util.eventTracker(HyperCities.config.EVENT_VIEW_COLLECTION, $checkerId);
        }
        else {
            HyperCities.util.eventTracker(HyperCities.config.EVENT_VIEW_OBJECT, $checkerId);
            // Overlay Marker on Map for Item
            _showItemOverlay(folderId);

        }

        if ( $.inArray($checkerId, _checked) < 0 ) {
            _checked.push($checkerId);
        }
    };

    // unCheck all checkBox with the same id
    var _uncheckItem = function ($checkerId) {

        var index = 0, totalChildren = 0, checkerIndex,
        folderDom, children, isCollection = true, isExternal = false,
        targetDom,
        targetArray = $("#treeviewWrapper ." + CLASSES.checkBox + $checkerId);

        index = targetArray.length;
        while ( index-- > 0 ) {
            targetDom = $(targetArray[index]);

            targetDom.removeClass(CLASSES.checked);

            // Get Folder Information
            folderDom = targetDom.parent();
            isCollection = folderDom.hasClass(CLASSES.collection);
            isExternal = folderDom.hasClass(CLASSES.external);

            // Get Children Information
            children = $.map(folderDom.find(">ul>li"), function($node){
                return $($node).data("id");
            });
            totalChildren = children.length;

            // uncheck each child by yielding processes
            if ( totalChildren > 0 ) {
                setTimeout(function() {
                    var childId = children.shift();

                    _setCheckBoxStatus(childId, false);

                    if ( children.length > 0 ) {
                        setTimeout(arguments.callee, 10);
                    }
                }, 10);
            }

            // Disable the Link for Item
            if ( !isCollection ) {
                $("."+CLASSES.markerLink, targetDom.next())
                .removeClass(CLASSES.enabled)
                .unbind('mouseenter mouseleave');

				$("."+CLASSES.editItem, targetDom.next()).hide();
            }

        //TODO:: remove parent's check if it's not default check
        }

        // remove Overlay of the Item
        if ( isExternal ) {
            _hideKmlOverlay($checkerId);
			$("."+CLASSES.editItem, targetDom.next()).hide();
        }
        else if ( !isCollection ){
            _hideItemOverlay($checkerId);
        }

        // If necessary, close infoWindow
        if ( $checkerId === HyperCities.session.get("infoWin") ) {
            HyperCities.mainMap.closeInfoWindow();
        }

        checkerIndex = $.inArray($checkerId, _checked);
        if ( checkerIndex >= 0 )
            _checked.splice(checkerIndex, 1);

    /*
		//remove base map, if there is one
		HyperCities.session.set("baseMap", null);
		
*/
    };

    // Overlay Marker on Map for Item
    var _addItemOverlay = function($item) {
        //		HyperCities.debug(_id + "[A2] Add Item Overlay " + $item.id);

        if ( $item.overlay instanceof GOverlay ) {
            HyperCities.mainMap.addOverlay($item.overlay)
            $item.added = true;
        }
    };

    var _showItemOverlay = function($itemId) {
        //		HyperCities.debug(_id + "[A2] Show Item Overlay " + $itemId);

        var itemIndex = _getObjectIndexById($itemId),
        item;

        if ( itemIndex >= 0 ) {
            item = _objects[itemIndex];

            // If we have the information of object, Overlay the Placemark
            if ( typeof(item) !== 'undefined' ) {
                // item.overlay doesn't exist, parse external kml and create overlay
                if ( !item.added ) {
                    _addItemOverlay(item);
                }
                // item.overlay already exist and is Correct
                if ( item.overlay instanceof GOverlay ){
                    item.overlay.show();
                    item.hidden = false;
                }
            }
        }
    };

    var _hideItemOverlay = function($itemId) {
        //		HyperCities.debug(_id + "[A2] Hide Item Overlay " + $itemId);

        var itemIndex = _getObjectIndexById($itemId),
        item;
		
        if ( itemIndex >= 0 ) {
            item = _objects[itemIndex];

            // If we have the information of object's overlay, hide the overlay
            if ( typeof(item) !== 'undefined' && item.overlay instanceof GOverlay ) {
                item.overlay.hide();
                item.hidden = true;
            }
        }
    };

    var _removeItemOverlay = function($item) {
        //		HyperCities.debug(_id + "[A2] Remove Item Overlay " + $item.id);

        if ( $item.overlay instanceof GOverlay ) {
            HyperCities.mainMap.removeOverlay($item.overlay);
            $item.added = false;
        }
    };

    var _addKmlOverlay = function($collection) {
        //		HyperCities.debug(_id + "[A2] Create KML Overlay " + $collection.id);

        var tempListener;
        if ( typeof($collection.url) === 'string' ) {
            $collection.overlay = new GGeoXml($collection.url);
            HyperCities.mainMap.addOverlay($collection.overlay);
            $collection.added = true;
            tempListener = GEvent.addListener($collection.overlay, "load", function() {
                // Hide Loading Icon
                $("#treeviewWrapper ." + CLASSES.collection + $collection.id)
                .find("img." + CLASSES.loading).hide();
				
                GEvent.removeListener(tempListener);
            });
        }
    };

    var _showKmlOverlay = function($collectionId) {
        //		HyperCities.debug(_id + "[A2] Show KML Overlay " + $collectionId);

        var objectIndex = _getObjectIndexById($collectionId),
        collection;
		
        if ( objectIndex >= 0 ) {
            collection = _objects[objectIndex];

            // If we have the information of object, Overlay the Placemark
            if ( typeof(collection) !== 'undefined' ) {
                // item.overlay doesn't exist, parse external kml and create overlay
                if ( !collection.added ) {
                    _addKmlOverlay(collection);
                }
                // item.overlay already exist and is Correct
                if ( collection.overlay instanceof GOverlay ){
                    collection.overlay.show();
                    $("#treeviewWrapper ." + CLASSES.collection + $collectionId)
                    .find("img." + CLASSES.loading).hide();
                }
            }
        }
    };

    var _hideKmlOverlay = function($collectionId) {
        //		HyperCities.debug(_id + "[A2] Hide KML Overlay " + $collectionId);

        var objectIndex = _getObjectIndexById($collectionId),
        collection;
		
        if ( objectIndex >= 0 ) {
            collection = _objects[objectIndex];

            // If we have the information of object's overlay, hide the overlay
            if ( typeof(collection) !== 'undefined' && collection.overlay instanceof GOverlay ) {
                collection.overlay.hide();
            }
        }
    };

    var _removeKmlOverlay = function($collection) {
        //		HyperCities.debug(_id + "[A2] Remove KML Overlay " + $collection.id);

        if ( $collection.overlay instanceof GOverlay ) {
            HyperCities.mainMap.removeOverlay($collection.overlay);
            $collection.added = false;
        }
    };

    var _openNarrativePanel = function ($event) {

        var folderDom    = $($event.target).parent().prev(),
        itemId       = folderDom.data("id"),
        collectionId = folderDom.parent().parent().parent().data("id");

        $($event.target).blur();

        //HyperCities.debug(_id + "[A2] Open Narrative of item " + itemId + " under collection " + collectionId);

        // Google Analytics Event Tracker
        HyperCities.util.eventTracker(HyperCities.config.EVENT_DETAIL_COLLECTION, itemId);
        HyperCities.narrativePanel.load(collectionId, itemId, {
            zoom: true
        });

        return false;
    };

    var _openItemInfoWindow = function ($event) {

        var folderDom    = $($event.target).parent().prev(),
        itemId       = folderDom.data("id"),
        collectionId = folderDom.parent().parent().parent().data("id"),
        objectIndex  = -1;

        $($event.target).blur();

        // If item URL is not enabled, do nothing
        if ( $($event.target).hasClass(CLASSES.enabled) ) {
            objectIndex = _getObjectIndexById(itemId);

            if ( objectIndex >= 0 ) {
                // If we have the information of object, open InfoWindow
                if ( typeof(_objects[objectIndex]) !== 'undefined' ) {
                    //HyperCities.debug(_id + "[A2] Open Item " + itemId + " in " + collectionId);

                    // Google Analytics Event Tracker
                    HyperCities.util.eventTracker(HyperCities.config.EVENT_DETAIL_OBJECT, itemId);
                    HyperCities.collectionList.showInfoWindow(itemId, collectionId);
                }
                else {
                    //HyperCities.debug(_id + "[A2] Open Item " + itemId + "Failed");
                }
            }
        }

        return false;
    };

    var _openItemEditWindow = function ($event) {

        var folderDom    = $($event.target).parent().prev(),
        itemId       = folderDom.data("id"),
        collectionId = folderDom.parent().parent().parent().data("id"),
        isExternal   = folderDom.hasClass(CLASSES.external),
        params       = {
            object_id: itemId,
            parent_id: collectionId
        };

        $($event.target).blur();

        if ( HyperCities.user.isLogin() === true ) {
            if ( isExternal ) {
                //HyperCities.debug(_id + "[A2] Edit External Collection " + itemId + " in " + collectionId);
                // Jay:: Call Edit External Collection function
                HyperCities.mainMap.getAddMediaControl().showUpdateWindow(itemId, collectionId);
            }
            else {
                //HyperCities.debug(_id + "[A2] Edit Item " + itemId + " in " + collectionId);
                HyperCities.mainMap.getAddMediaControl().showUpdateWindow(itemId, collectionId);
            }
        }

        return false;
    };

    var _zoomToCollection = function ($event) {

        var folderDom    = $($event.target).parent().prev(),
        collectionId = folderDom.data("id"),
        objectIndex  = _getObjectIndexById(collectionId),
        bBox, newBound, newZoom,
        temp1, temp2, offsetX, offsetY;

        $($event.target).blur();

        if ( typeof(_objects[objectIndex]) !== 'undefined' ) {
            //HyperCities.debug(_id + "[A2] Zoom to collections " + collectionId);

            bBox = _objects[objectIndex].bBox;
            /*
			// Apply the offset to get actual bound in View (Extend the Bound)
			temp1 = HyperCities.mainMap.fromContainerPixelToLatLng(new GPoint(100,100));
			temp2 = HyperCities.mainMap.fromContainerPixelToLatLng(new GPoint(140,180));

			offsetX = Math.abs(temp1.x - temp2.x);
			offsetY = Math.abs(temp1.y - temp2.y);
			bBox.north = bBox.north + ( offsetX );
			bBox.east  = bBox.east + ( offsetY / 4 );
			bBox.south = bBox.south - ( offsetX * 1.5);
			bBox.west  = bBox.west - ( offsetY );
*/
            // Calculate the actual bound
            //newBound = new GLatLngBounds(new GLatLng(bBox.south, bBox.west), new GLatLng(bBox.north, bBox.east));

            //HyperCities.debug(newBound);
            // Get max zoomlevel that fit bound, and recenter the map
            newZoom = HyperCities.mainMap.getBoundsZoomLevel(bBox);
            if ( newZoom > 0 ) {
                newZoom--;
            }
            HyperCities.mainMap.setCenter(bBox.getCenter(), newZoom);
        }
        else {
            //HyperCities.debug(_id + "[A2] Zoom to collections " + collectionId + "Error");
        }

        return false;
    };

    var _parseBoundingBox = function ($bBoxString) {

        var pattern = /^BBox=\[(-?\d+(?:\.\d*)?)\],\[(-?\d+(?:\.\d*)?)\],\[(-?\d+(?:\.\d*)?)\],\[(-?\d+(?:\.\d*)?)\]/i,
        bBoxArray = pattern.exec($bBoxString),
        bBox = {},
		bounds = {};

        if ( bBoxArray === null) {
            return null;
        }
        else {
            bBox.west  = parseFloat(bBoxArray[1]);
            bBox.south = parseFloat(bBoxArray[2]);
            bBox.east  = parseFloat(bBoxArray[3]);
            bBox.north = parseFloat(bBoxArray[4]);
        }

		bounds = new GLatLngBounds(new GLatLng(bBox.south, bBox.west), new GLatLng(bBox.north, bBox.east));

		return bounds;
    };

	/**
	 * Update Dom Node of single Placemark based on $data, if the dom not exist, 
	 * call _createPlacemark to create the new dom, and append it to $parentNode.
	 * returns the marker dom element.
	 */
	var _updatePlacemark = function ($parentNode, $data, $outList, $checkList) {
//		HyperCities.debug(_id + "[A2] Update Placemark");

		var markerName    = $("name:first", $data).text(),
			markerUrl     = decodeURI($("link:first > href", $data).text()),
			markerId      = $($data).attr("id"),
			ownerId       = parseInt($("ExtendedData:last > [nodeName=hc:ownerId]", $data).text()),
			stateId       = parseInt($("ExtendedData:last > [nodeName=hc:stateId]", $data).text()),
			viewFormat    = $("ExtendedData:last > [nodeName=hc:viewFormat]", $data).text(),
			bBox          = _parseBoundingBox(viewFormat),
			isInView      = HyperCities.mainMap.isInView(bBox),
			isChecked     = ($.inArray(markerId, _checked) !== -1),
			parentChecked = ($.inArray($parentNode.parent().data("id"), _checked) !== -1),
			markerDom     = null,
			markerIndex   = null,
			isEditable    = HyperCities.user.hasUpdatePrivilege(markerId, ownerId, stateId),
			domHtml       = ['<a href="', markerUrl, '" class="', CLASSES.markerLink, '">', markerName, '</a>'],
			editDomHtml   = ['<img src="./images/editIcon.gif" alt="Edit" title="Edit ', markerName, '" class="', CLASSES.editItem, '"/>'];

		// If item is not in view, don't event try to update it
		if ( !isInView ) {
			return false;
		}

		// update checker status
		if ( isChecked || parentChecked ) {
			markerIndex = $.inArray(markerId, $checkList.item);
			// Item not checked, check it (add it to $checkList.item)
			if ( markerIndex < 0 ) {
				$checkList.item.push(markerId);
			}
			isChecked = true;
		}

		// try to get marker dom
		markerDom = $("li." + CLASSES.item + markerId, $parentNode);

		// if marker dom does not exist, create dom
		if ( markerDom.length <= 0 ) { 
//			HyperCities.debug(_id + "[A2] Create Placemark " + markerId);
			markerDom = _createPlacemark(markerId, markerName, markerUrl, $data, ownerId);
		}

		// we are safe to update markerDom now
//		HyperCities.debug(_id + "[A2] Update Placemark " + markerId);

		// Since item still be shown in collection tree, remove it from $outList.item
		markerIndex = $.inArray(markerId, $outList.item);
		if ( markerIndex >= 0 ) {
			$outList.item.splice(markerIndex, 1);
		}

		// Update Link Name
		markerDom.find("> div." + CLASSES.marker).html(domHtml.join (''));

		// Update CheckBox Style
		if ( isChecked ) {
			markerDom.find("." + CLASSES.checkBox).addClass(CLASSES.checked);
		} 
		else {
			markerDom.find("." + CLASSES.checkBox).removeClass(CLASSES.checked);
		}

		// Update Edit Button, item only editable when it was checked
		if ( !isEditable ) {
			markerDom.find("." + CLASSES.editItem).remove();
		} 
		else {
			markerDom.find("." + CLASSES.markerLink).before(editDomHtml.join (''));
		}

		return markerDom;
	};

	/**
	 * Update Dom Node of single NetworkLink based on $data, if the dom not exist,
	 * call _createNetworkLink to create the new dom, and append it to $parentNode.
	 * returns the link dom element.
	 */
	var _updateNetworkLink = function ($parentNode, $data, $outList, $checkList) {
//		HyperCities.debug(_id + "[A2] Update NetworkLink");

		var linkName      = $("name:first", $data).text(),
			linkUrl       = decodeURI($("link:first > href", $data).text()),
			linkId        = $($data).attr("id"),
			totalChildren = parseInt($("ExtendedData:last > [nodeName=hc:totalChildren]", $data).text()),
			boundChildren = parseInt($("ExtendedData:last > [nodeName=hc:boundChildren]", $data).text()),
			isExternal    = parseInt($("ExtendedData:last > [nodeName=hc:external]", $data).text()),
			ownerId       = parseInt($("ExtendedData:last > [nodeName=hc:ownerId]", $data).text()),
			stateId       = parseInt($("ExtendedData:last > [nodeName=hc:stateId]", $data).text()),
			viewFormat    = $("ExtendedData:last > [nodeName=hc:viewFormat]", $data).text(),
			bBox          = _parseBoundingBox(viewFormat),
			isInView      = HyperCities.mainMap.isInView(bBox),
			isOpened      = ($.inArray(linkId, _opened) !== -1),
			isChecked     = ($.inArray(linkId, _checked) !== -1),
			parentChecked = ($.inArray($parentNode.parent().data("id"), _checked) !== -1),
			checkerDom    = null,
			linkDom       = null,
			linkIndex     = null,
			isEditable    = HyperCities.user.hasUpdatePrivilege(linkId, ownerId, stateId),
			updateFolder  = false,
			domHtml       = ['<img src="./images/navIcon.gif" alt="Narrative Mode" title="Open ', linkName, 
							 ' in Narrative Mode" class="', CLASSES.narrative, '"/>',
							 '<a href="', linkUrl, '" title="Zoom to ', linkName, '" class="', CLASSES.folderLink, '">',
							 linkName, '</a>', ' (', boundChildren, '/', totalChildren, ')',
							 '<img src="./images/loading.gif" alt="Loading..." class="', CLASSES.loading, '"/>'],
			editDomHtml   = ['<img src="./images/editIcon.gif" alt="Edit" title="Edit ', linkName, '" class="', CLASSES.editItem, '"/>'];

		// If item is not in view, don't event try to update it
		if ( !isInView ) {
			return false;
		}

        // update checker status
        if ( isChecked || parentChecked ) {
            linkIndex = $.inArray(linkId, $checkList.item);
            // Item not checked, check it (add it to $checkList.item)
            if ( linkIndex < 0 ) {
                $checkList.item.push(linkId);
            }
            isChecked = true;
        }

        // Try to get link dom
        linkDom = $("li." + CLASSES.collection + linkId, $parentNode);

		// If link dom doesn't exist, create a new one
        if ( linkDom.length <= 0 ) { 
            linkDom = _createNetworkLink(linkId, linkName, linkUrl, isExternal, bBox, ownerId);

			// Setup Open State
			// if link is external then it can only be checked, 
			// and cannot be opened (so remove div.CLASSES.hitarea)
			if ( isExternal ) {
				linkDom.addClass(CLASSES.external)
					.find(">div." + CLASSES.hitarea)
					.remove().end()
					.find(">div." + CLASSES.checkBox)
					.addClass(CLASSES.external).end()
					.find(">div." + CLASSES.folder)
					.addClass(CLASSES.external);
			}
			// It's not external, and thus can be opend
			else {
				// set folder collapsable if it's opened
				if ( isOpened ) {
					linkDom.addClass(CLASSES.collapsable)
						.find(">div." + CLASSES.hitarea)
						.addClass(CLASSES.collapsableHitarea).end()
						.find(">ul").show();
				}
				// set folder expandable if it's closed
				else {
					linkDom.addClass(CLASSES.expandable)
						.find(">div." + CLASSES.hitarea)
						.addClass(CLASSES.expandableHitarea).end()
						.find(">ul").hide();
				}
			}

        }

		// we are safe to update linkDom now 
//		HyperCities.debug(_id + "[A2] Update NetworkLink " + linkId);

		// Since item still be shown in collection tree, remove it from $outList.item
		linkIndex = $.inArray(linkId, $outList.item);
		if ( linkIndex >= 0 ) {
			$outList.item.splice(linkIndex, 1);
		}

		// If there's no total children number, just display folder name, (in this case, also remove narrative Icon)
		// If there's no bound children number, just display total children number
		boundChildren = parseInt(linkDom.data("boundChildren"));
		if ( isExternal || isNaN(totalChildren) ) {
			domHtml.splice(14,5); // Remove folder children counter
			domHtml.splice(0,5);  // Remove Narrative Icon
		}
		else if ( isNaN(boundChildren) || !isOpened ) {
			domHtml.splice(15,2); // Remove folder boundChildren counter
		}
		else {
			domHtml[15] = boundChildren;
		}

		// Update Link Name
		linkDom.data("totalChildren", totalChildren)
			.data("boundChildren", boundChildren)
			.data("name", linkName)
			.data("uri", linkUrl)
			.find(">div." + CLASSES.folder)
			.html(domHtml.join (''))
			.find("img." + CLASSES.loading).hide();

        // Update CheckBox Style
        if ( isChecked ) {
            linkDom.find("." + CLASSES.checkBox).addClass(CLASSES.checked);
        }
        else {
            linkDom.find("." + CLASSES.checkBox).removeClass(CLASSES.checked);
        }

        // Update Edit Button, item only editable when it was checked
        if ( !isEditable ) {
            linkDom.find("." + CLASSES.editItem).remove();
        }
        else {
            linkDom.find("." + CLASSES.folderLink).before(editDomHtml.join (''));
        }

		// Update Link Children if it's open or checked, and not been updated
		if ( isOpened || isChecked ) {
			_getCollection(linkId, isExternal);
		}

		return linkDom;
    };

    var _removeItem = function ($parentNode, $itemId) {

        var childNode   = $("li." + CLASSES.collection + $itemId + ">ul", $parentNode),
        objectIndex = _getObjectIndexById($itemId),
        item, children, totalChildren;

        if ( objectIndex >= 0 ) {
            item = _objects[objectIndex];

            // Get Children Information and recursivly remove all children
            children = $.map(childNode.find(">li"), function($node){
                return $($node).data("id");
            });
            totalChildren = children.length;
            _progressCount+= totalChildren;

            //			HyperCities.debug(_id + "[A2] Progress Count (RemoveItem " + $itemId + " Add children)" + _progressCount);
            while ( totalChildren-- > 0 ) {
                _removeItem(childNode, children[totalChildren]);
            }

            // If we have the information of Item, we can remove it
            if ( typeof(item) !== 'undefined' ) {
                if ( item.type === CLASSES.collection || item.type === CLASSES.folder ) {
                    // Remove Dom Element
                    _removeNetworkLink($parentNode, $itemId);
                    // Remove Overlay
                    if ( item.overlay instanceof GOverlay ) {
                        _removeKmlOverlay(item);
                    }
                }
                else if ( item.type === CLASSES.item ) {
                    // Remove Dom Element
                    _removePlacemark($parentNode, $itemId);
                    // Remove Overlay
                    if ( item.overlay instanceof GOverlay ) {
                        _removeItemOverlay(item);
                    }
                }

                // If necessary, close infoWindow
                if ( $itemId === HyperCities.session.get("infoWin") ) {
                    // This function close infoWindow only, not panTo original center
                    HyperCities.mainMap.closeHCInfoWindow(false);
                }
            }
			
            // Remove item from _object
            //			HyperCities.debug(_id + "[A2] Remove Object " + $itemId);
            _objects.splice(objectIndex, 1);
        }
    };

    var _removeNetworkLink = function ($parentNode, $linkId) {
        //		HyperCities.debug(_id + "[A2] Remove NetworkLink " + $linkId);

        var targetArray = $("li." + CLASSES.collection + $linkId, $parentNode),
        isLastNode, index, targetDom;

        // Remove Dom
        index = targetArray.length;
        while ( index-- > 0 ) {
            targetDom = $(targetArray[index]);
            isLastNode = ( targetDom.hasClass(CLASSES.lastCollapsable) || targetDom.hasClass(CLASSES.lastExpandable) || targetDom.hasClass(CLASSES.last) );

            // if is last element, apply last class to previous element
            if ( isLastNode ) {
                _applyLastClass(targetDom.prev("li"));
            }

            targetDom.slideUp().remove();
        }

        _progressCount--;

       // 		HyperCities.debug(_id + "[A2] Progress Count (Remove NetworkLink " + $linkId + ")" + _progressCount);
        $("#treeviewWrapper").trigger('HCUpdateFinish');
    };

    var _removePlacemark = function ($parentNode, $markerId) {
        //		HyperCities.debug(_id + "[A2] Remove Placemark " + $markerId);

        var targetArray = $("li." + CLASSES.item + $markerId, $parentNode),
        isLastNode, index, targetDom;

        // Remove Dom
        index = targetArray.length;
        while ( index-- > 0 ) {
            targetDom = $(targetArray[index]);
            isLastNode = targetDom.hasClass(CLASSES.last);

            // if is last element, apply last class to previous element
            if ( isLastNode ) {
                _applyLastClass(targetDom.prev("li"));
            }

            targetDom.slideUp().remove();
        }

        _progressCount--;
        //		HyperCities.debug(_id + "[A2] Progress Count (Remove Placemark " + $markerId + ")" + _progressCount);
        $("#treeviewWrapper").trigger('HCUpdateFinish');
    };

    // update folder dom according to $data
    var _updateFolder = function ($folderDom, $data) {
        //HyperCities.debug ("_updateFolder with data")
        //HyperCities.debug ($data);
        //		HyperCities.debug(_id + "[A2] Update Folder");

		var index     = 0,
			isOpened  = false,
			outList   = {}, // Only Object can passing by reference, list to be removed
			checkList = {}, // Only Object can passing by reference, list to be checked
			folderId  = $folderDom.parent().data("id"),
			childrenList, totalChild, totalUpdated = 0,
			childDom, domHtml, tempDom, newDom = $(document.createElement("ul"));

        outList.item = $.map($folderDom.find(">li"), function($node){
            return $($node).data("id");
        });
        checkList.item = [];

        childrenList = $($data).children();
        totalChild = childrenList.length;
        while ( index < totalChild ) {
				
            childDom = childrenList[index++];

            // Append dom nodes for NetworkLink (Collection)
            if ( childDom.nodeName == "NetworkLink" ) {
                tempDom = _updateNetworkLink($folderDom, childDom, outList, checkList);
            }
            // Append dom nodes for Placemark (Object)
            else if ( childDom.nodeName == "Placemark" ) {
                tempDom = _updatePlacemark($folderDom, childDom, outList, checkList);
            } else if ( childDom.nodeName == "Folder") {
                _updateFolder ($folderDom, childDom);
            }
            else {
                    tempDom = false;
            }

            if ( tempDom != false ) {
				totalUpdated++;
                newDom.append(tempDom);
				tempDom = null;
            }
        }
        $folderDom.append(newDom.find(">li"));
		newDom = null;

        // Remove Last class for not-last elements
        $folderDom.find(">li:not(:last-child)")
        .removeClass(CLASSES.last)
        .removeClass(CLASSES.lastCollapsable)
        .removeClass(CLASSES.lastExpandable).end()
        .find(">li>div." + CLASSES.hitarea + ":not(:last-child)")
        .removeClass(CLASSES.lastCollapsableHitarea)
        .removeClass(CLASSES.lastExpandableHitarea);

        // Remove objects still in outList After update all Item
        if ( (outList.item).length > 0 ) {
            _progressCount+= (outList.item).length;
            //			HyperCities.debug(_id + "[A2] Progress Count (Call RemoveItem in Update " + folderId +")" + _progressCount);
            setTimeout( function() {
                var itemId = (outList.item).shift();

                _removeItem($folderDom, itemId);

                if ( (outList.item).length ) {
                    setTimeout(arguments.callee, 10);
                }
            }, 10);
        }

        // We are safe to check all objects that in checkList now, because all new dom were append
        if ( (checkList.item).length > 0 ) {
            setTimeout( function() {
                var itemId = (checkList.item).shift();

                _checkItem(itemId);

                if ( (checkList.item).length ) {
                    setTimeout(arguments.callee, 10);
                }
            }, 10);
        }

        // Update Last Dom Element Class
        _applyLastClass($folderDom.find(">li:last"));

		// Update bounded children and prepare new counter of folder 
		tempDom = $folderDom.parent();
		tempDom.data("boundChildren", totalUpdated);
		domHtml = [ '<img src="./images/navIcon.gif" alt="Narrative Mode" title="Open ', tempDom.data("name"), 
					' in Narrative Mode" class="', CLASSES.narrative, '"/>',
					'<a href="', tempDom.data("uri"), '" title="Zoom to ', tempDom.data("name"), '" class="', CLASSES.folderLink, '">',
					tempDom.data("name"), '</a>', ' (', totalUpdated, '/', tempDom.data("totalChildren"), ')',
					'<img src="./images/loading.gif" alt="Loading..." class="', CLASSES.loading, '"/>' ];

		// Root Folder, remove Narrative Icon and Zoom in link
		if ( tempDom.find(">div." + CLASSES.folder).hasClass(CLASSES.noCheckBox) ) {
			domHtml.splice(0,12);
			domHtml.splice(1,1);
		}

		// External Link, remove Narrative Icon 
		if ( tempDom.find(">div." + CLASSES.folder).hasClass(CLASSES.external) ) {
			domHtml.splice(0,5);
		}

        // Update folder Name and remove loading icon 
		tempDom.find(">div." + CLASSES.folder)
			.html(domHtml.join(''))
			.find("img." + CLASSES.loading).hide();

		// Show message if no item in view
		if ( totalUpdated > 0 ) {
			$folderDom.find(">li." + CLASSES.noItem).hide();
		} else {
			$folderDom.find(">li." + CLASSES.noItem).show();
		}

        _progressCount--;
		//HyperCities.debug(_id + "[A2] Progress Count (Finish Update " + folderId +")" + _progressCount);

        $("#treeviewWrapper").trigger('HCUpdateFinish');
    };

    // Toggle folder event handler
    var _toggleFolder = function ($event) {

        var folderDom   = $($event.target).parent(),
        folderId    = folderDom.data("id"),
        folderIndex = $.inArray(folderId, _opened);

        if ( typeof(folderId) !== 'undefined' ) {
            if ( folderIndex >= 0 ) {             // collapse Collection
                _setFolderStatus(folderId, false);
            }
            else {                                // expand Collection
                _setFolderStatus(folderId, true);
            }
        }

        $("#treeviewWrapper").trigger('HCUpdateFinish');
    };

	var _setFolderStatus = function ($folderId, $opened, $doUpdate) {

		var folderIndex = $.inArray($folderId, _opened),
			folderDom   = $("#treeviewWrapper li." + CLASSES.collection + $folderId),
			isExternal  = folderDom.hasClass(CLASSES.external),
			domHtml     = [ '<img src="./images/navIcon.gif" alt="Narrative Mode" title="Open ', folderDom.data("name"), 
							' in Narrative Mode" class="', CLASSES.narrative, '"/>',
							'<a href="', folderDom.data("uri"), '" title="Zoom to ', folderDom.data("name"), '" class="', CLASSES.folderLink, '">',
							folderDom.data("name"), '</a>', ' (', folderDom.data("boundChildren"), '/', folderDom.data("totalChildren"), ')',
							'<img src="./images/loading.gif" alt="Loading..." class="', CLASSES.loading, '"/>' ];

		// Folder closed, remove bound Children count
		if ( !$opened || isNaN(folderDom.data("boundChildren")) ) {
			domHtml.splice(15,2);
		}

		// Root Folder, remove Narrative Icon and Zoom in link
		if ( folderDom.find(">div." + CLASSES.folder).hasClass(CLASSES.noCheckBox) ) {
                    HyperCities.util.debug (_id + "Root folder found and opened")
			domHtml.splice(0,12);
			domHtml.splice(1,1);
		}

		// External Link, remove Narrative Icon 
		if ( folderDom.find(">div." + CLASSES.folder).hasClass(CLASSES.external) ) {
			domHtml.splice(0,5);
		}

		if ( $opened && (folderIndex < 0) ) { // Should Be Opened and Not Opened
//			HyperCities.debug(_id + "Folder " + $folderId + " Opened");

			_opened.push($folderId);

			// Google Analytics Event Tracker
			HyperCities.util.eventTracker(HyperCities.config.EVENT_LIST_COLLECTION, $folderId);

			if ( !isExternal ) { // Show Children only if it's not external collection
				folderDom.removeClass(CLASSES.expandable)
					.addClass(CLASSES.collapsable)
					.filter("." + CLASSES.lastExpandable)
					.removeClass(CLASSES.lastExpandable)
					.addClass(CLASSES.lastCollapsable).end()
					.find(">div." + CLASSES.hitarea)
					.removeClass(CLASSES.expandableHitarea)
					.addClass(CLASSES.collapsableHitarea)
					.filter("." + CLASSES.lastExpandableHitarea)
					.removeClass(CLASSES.lastExpandableHitarea)
					.addClass(CLASSES.lastCollapsableHitarea).end().end()
					.find(">ul").show().end()
					.find(">div." + CLASSES.folder)
					.html(domHtml.join(''));
			}

                        if (typeof ($doUpdate) == 'undefined' || $doUpdate == true) {
                            _getCollection($folderId, isExternal);
                        }
		}
		else if ( !$opened && (folderIndex >= 0) ) { // Should Be closed and still opened
//			HyperCities.debug(_id + "Folder " + $folderId + " Closed");

			_opened.splice(folderIndex, 1);

			if ( !isExternal ) { // Hide Children only if it's not external collection
				folderDom.removeClass(CLASSES.collapsable)
					.addClass(CLASSES.expandable)
					.filter("." + CLASSES.lastCollapsable)
					.removeClass(CLASSES.lastCollapsable)
					.addClass(CLASSES.lastExpandable).end()
					.find(">div." + CLASSES.hitarea)
					.removeClass(CLASSES.collapsableHitarea)
					.addClass(CLASSES.expandableHitarea)
					.filter("." + CLASSES.lastCollapsableHitarea)
					.removeClass(CLASSES.lastCollapsableHitarea)
					.addClass(CLASSES.lastExpandableHitarea).end().end()
					.find(">ul").hide().end()
					.find(">div." + CLASSES.folder)
					.html(domHtml.join(''))
					.find("img." + CLASSES.loading).hide();
			}
        }
    };

    // Toggle CheckBox event handler
    var _toggleCheckBox = function ($event) {

        var checkerDom   = $($event.target),
        checkerId    = checkerDom.data("id"),
        checkerIndex = $.inArray(checkerId, _checked);

        if ( typeof(checkerId) !== 'undefined' ) {
            if ( checkerIndex >= 0 ) { // Already Checked, so uncheck it
                _setCheckBoxStatus(checkerId, false);
            }
            else { // Not Checked, so check it
                _setCheckBoxStatus(checkerId, true);
            }
        }

    //		HyperCities.debug(_checked);
    };

    var _setCheckBoxStatus = function ($checkerId, $checked) {

        var checkerIndex = $.inArray($checkerId, _checked);

        if ( $checked && (checkerIndex < 0) ) { // Should Be Checked and Not Checked
            //			HyperCities.debug(_id + "Folder " + $checkerId + " checked");
            _checkItem($checkerId);
        }
        else if ( !$checked && (checkerIndex >= 0) ) { // Should Be unchecked and still Checked
            //			HyperCities.debug(_id + "Folder " + $checkerId + " unchecked");
            _uncheckItem($checkerId);
        }
    };

	/**
	 * Create dom element of folder
	 */ 
	var _createFolder = function ($folderId, $folderName) {

		var folderDom = $(document.createElement("li")),
			childDom  = $(document.createElement("ul")),
			domHtml   = ['<div class="', CLASSES.hitarea, '"></div>',
						 '<div class="', CLASSES.folder, ' ', CLASSES.noCheckBox, '"></div>'],
			msgHtml   = ['<li class="', CLASSES.noItem, '">No item available in current view</li>'],
			folderObject = null;

        // Don't put folderId in element's id, it's not unique in dom tree.
        folderDom.data("id", $folderId)
			.addClass(CLASSES.collection)
			.addClass(CLASSES.collection + $folderId)
			.html(domHtml.join(''))
			.append(childDom.html(msgHtml.join('')));

        // Add Item to _objects Array
        folderObject = {
            type : CLASSES.folder,
            id   : $folderId,
            name : $folderName,
            overlay : null,
            added : false
        };

        if ( _getObjectIndexById($folderId) < 0 ) {
            _objects.push(folderObject);
        }
        return folderDom;
    };

	/**
	 * Create dom element NetworkLink
	 * TODO:// move create linkObject to HyperCities.objects Class.
	 */
    var _createNetworkLink = function ($linkId, $linkName, $linkUrl, $isExternal, $bBox, $ownerId) {

		var linkDom    = $(document.createElement("li")),
			childDom   = $(document.createElement("ul")),
			linkObject = null,
			domHtml    = ['<div class="', CLASSES.hitarea, '"></div>',
						  '<div class="', CLASSES.checkBox, '"></div>',
						  '<div class="', CLASSES.folder, '"></div>'],
			msgHtml    = ['<li class="', CLASSES.noItem, '">No item available in current view</li>'];
	/*
        '<img src="./images/navIcon.gif" alt="Narrative Mode" title="Open ', $linkName, ' in Narrative Mode" class="', CLASSES.narrative, '"/>',
        '<a href="', $linkUrl, '" title="Zoom to ', $linkName, '" class="', CLASSES.folderLink, '">', $linkName, '</a> (',
        $boundChildren, '/', $totalChildren, ') ',
        '<img src="./images/loading.gif" alt="Loading..." class="', CLASSES.loading, '"/></div>'];

        // Don't show Children Count if there's no value
        if ( isNaN($totalChildren) || isNaN($boundChildren) ) {
            domHtml    = ['<div class="', CLASSES.hitarea, '"></div>',
            '<div class="', CLASSES.checkBox, '"></div>',
            '<div class="', CLASSES.folder, '">',
            '<img src="./images/navIcon.gif" alt="Narrative Mode" title="Open ', $linkName, ' in Narrative Mode" class="', CLASSES.narrative, '"/>',
            '<a href="', $linkUrl, '" title="Zoom to ', $linkName, '" class="', CLASSES.folderLink, '">', $linkName, '</a>',
            '<img src="./images/loading.gif" alt="Loading..." class="', CLASSES.loading, '"/></div>'];
        }

*/
		// Don't put folderId in element's id, it's not unique in dom tree.
		linkDom.data("id", $linkId)
			.addClass(CLASSES.collection)
			.addClass(CLASSES.collection + $linkId)
			.html(domHtml.join (''))
			.append(childDom.html(msgHtml.join('')));

		// Setup CheckBox
		checkerDom = $("." + CLASSES.checkBox, linkDom);
		checkerDom.data("id", $linkId)
			.addClass(CLASSES.checkBox + $linkId);

		// Add Item to _objects Array
		linkObject = {
			type : CLASSES.collection,
			id   : $linkId,
			name : $linkName,
			url  : $linkUrl,
			isExternal: $isExternal,
			ownerId : $ownerId,
			bBox : $bBox,
			overlay : null,
			added : false
		};

        if ( _getObjectIndexById($linkId) < 0 ) {
            _objects.push(linkObject);
        }

        return linkDom;
    };

	/**
	 * Create dom element of placemark
	 * TODO:// move create markerObject to HyperCities.objects Class.
	 */
	var _createPlacemark = function ($markerId, $markerName, $markerUrl, $markerKml, $ownerId) {

		var markerDom     = $(document.createElement("li")),
			checkerDom    = null,
			markerObject  = null,
			markerOverlay = null,
			domHtml       = ['<div class="', CLASSES.checkBox, '"></div>', '<div class="', CLASSES.marker, '"></div>'];

		// Don't put folderId in element's id, it's not unique in dom tree.
		markerDom.data("id", $markerId)
			.addClass(CLASSES.item)
			.addClass(CLASSES.item + $markerId)
			.html(domHtml.join (''));

		// Set CheckBox Style
		checkerDom = $("." + CLASSES.checkBox, markerDom);
		checkerDom.data("id", $markerId)
			.addClass(CLASSES.checkBox + $markerId);

		// Create Overlay for the Item
		markerOverlay = new GHCMarker(HyperCities.mainMap.getMapInstance(), $markerKml);
//		HyperCities.mainMap.addOverlay(markerOverlay);

		// Add Item to _objects Array
		markerObject = {
			type : CLASSES.item,
			id   : $markerId,
			name : $markerName,
			url  : $markerUrl,
			kml  : $markerKml,
			ownerId : $ownerId,
			overlay : markerOverlay,
			added   : false,
			hidden  : true
		};

		// TODO: Seperate all _objects into HyperCities.objects Class.
		if ( _getObjectIndexById($markerId) < 0 ) {
			_objects.push(markerObject);
		}

		return markerDom;
	};

    // $data is a <Folder> XML
    // Parse the data and append it to $parentNode
    // David, 09-29-09 @return node at which the folder was created
    var _parseFolder = function ($parentNode, $data) {
//		HyperCities.debug(_id + "[A2] Parse Folder");

        var folderName    = $("name:first", $data).text(),
			folderId      = $($data).attr("id"),
			totalChildren = parseInt($("ExtendedData:first > [nodeName=hc:totalChildren]", $data).text()),
			hasCheckBox   = parseInt($("ExtendedData:first > [nodeName=hc:checkBox]", $data).text()),
			isOpened      = ($.inArray(folderId, _opened) !== -1),
			folderDom     = null,
			boundChildren = null,
			domHtml       = [folderName, ' (', '', '/', totalChildren, ')',
							'<img src="./images/loading.gif" alt="Loading..." class="', CLASSES.loading, '"/>'];

//		HyperCities.debug(_id + folderId + " (" + boundChildren + "/" + totalChildren + ")");

        // Try to get folder dom
        folderDom = $("li." + CLASSES.collection + folderId, $parentNode);

        // Skip the root level object
        // _skipList.push(folderId);

		// If folder dom doesn't exist, create a new one
        if ( folderDom.length <= 0 ) {
            folderDom = _createFolder(folderId, folderName);

			if ( isOpened ) {
				folderDom.addClass(CLASSES.collapsable)
					.addClass(CLASSES.lastCollapsable)
					.find(">div." + CLASSES.hitarea)
					.addClass(CLASSES.collapsableHitarea)
					.addClass(CLASSES.lastCollapsableHitarea).end()
					.find(">ul").show();
			} 
			else {
				folderDom.addClass(CLASSES.expandable)
					.addClass(CLASSES.lastExpandable)
					.find(">div." + CLASSES.hitarea)
					.addClass(CLASSES.expandableHitarea)
					.addClass(CLASSES.lastExpandableHitarea).end()
					.find(">ul").hide();
			}

			// User's My Collection always show as first item
			if ( folderName === HyperCities.config.HC_COLLECTIONS.USER.name ) {
				HyperCities.config.HC_COLLECTIONS.USER.id = folderId;

				folderDom.addClass(CLASSES.myCollection)
					.removeClass(CLASSES.lastCollapsable)
					.removeClass(CLASSES.lastExpandable)
					.find(">.hitarea")
					.removeClass(CLASSES.lastCollapsableHitarea)
					.removeClass(CLASSES.lastExpandableHitarea).end()
					.prependTo($parentNode);
			} 
			else { // Other Folder appended as processing order
				$parentNode.find(">li:last")
					.removeClass(CLASSES.last)
					.removeClass(CLASSES.lastCollapsable)
					.removeClass(CLASSES.lastExpandable)
					.find(">.hitarea")
					.removeClass(CLASSES.lastCollapsableHitarea)
					.removeClass(CLASSES.lastExpandableHitarea).end().end()
					.append(folderDom);
			}
        }

        _progressCount+= folderDom.length;
    	//HyperCities.debug(_id + "[A2] Progress Count (Begin Update " + folderId +")" + _progressCount);

		// If there's no total children number, just display folder name
		// If there's no bound children number, just display total children number
		boundChildren = parseInt(folderDom.data("boundChildren"));
		if ( isNaN(totalChildren) ) {
			domHtml.splice(1,5);
		} 
		else if ( isNaN(boundChildren) || !isOpened ) {
			domHtml.splice(2,2);
		} 
		else {
			domHtml[2] = boundChildren;
		}

        folderDom.each( function() {
			_progressCount--;
            // Update title of Folder
            $(this).data("totalChildren", totalChildren)
				.data("boundChildren", boundChildren)
				.data("name", folderName)
				.data("uri", null)
				.find(">div." + CLASSES.folder)
				.html(domHtml.join (''))
				.find("img." + CLASSES.loading).hide();

			// Update Tree Status
			if ( totalChildren <= 0 ) {
				$(this).removeClass(CLASSES.expandable)
					.find(">div." + CLASSES.folder)
					.prev().removeClass(CLASSES.hitarea);
			} else {
				$(this).addClass(CLASSES.expandable)
					.find(">div." + CLASSES.folder)
					.prev().addClass(CLASSES.hitarea);
			}

			// Load Update content of folder if it's opened
            if ( isOpened ) {
                _getCollection(folderId, false);
			}
        });

        if (folderDom.length > 1)
            return folderDom[0];
    };

    var _parseCollectionList = function ($data) {
        //		HyperCities.debug(_id + "[A2] Parse CollectionList");

        var treeRoot, treeChildren = [];

        // Create or Get collection tree root
        treeRoot = $("#treeviewWrapper");
        if ( treeRoot.length <= 0 ) {
            treeRoot = _initCollectionList();
        }

        // Reset Update Status
        _updated  = [];
        _skipList = [];
        _progressCount = 0;

        // Append folders to collection tree
        $("Document > Folder", $data).each( function() {
            var self = this;
            treeChildren.push(_parseFolder(treeRoot, self));
        });

		// Remove My Collection if user not login
		if ( HyperCities.user.getUserId() === null ) {
			// Remove My Collection
			_removeItem(treeRoot, treeRoot.find(">." + CLASSES.myCollection).data("id"));
			HyperCities.config.HC_COLLECTIONS.USER.id = null;
		}
        $("#treeviewWrapper").trigger('HCUpdateFinish');
        return treeChildren;
    };

	var _parseCollection = function ($data) {

		var folderXml, folderDom, folderId, index;

		if ($("Document", $data).length > 0) {
			folderXml = $("Document", $data);
		} else if ($("Folder", $data).length > 0) {
			folderXml = $("Folder", $data);
		} else if ($($data).is("Folder")) {
                    folderXml = $($data);
                }

		folderId  = folderXml.attr("id");
		folderDom = $("#treeviewWrapper li." + CLASSES.collection + folderId);

//		HyperCities.debug(_id + "[A2] Parse Collection " + folderId);

		_progressCount+= folderDom.length;
		//HyperCities.debug(_id + "[A2] Progress Count (Begin Update " + folderId +")" + _progressCount);

		index = folderDom.length;
		while ( index-- > 0 ) {
			_updateFolder($(">ul", folderDom[index]), folderXml);
		}
	};

    /*
    var _appendKmlLinks = function(parentNode, $data) {

        parentNode.find(".folderCheck").unbind().remove();
        parentNode.empty();

        HyperCities.debug(_id + "Append " + $data.length + " KML Collections");
        $data.each( function() {

                var childFolder = $(document.createElement("li"));
                var folderName  = $("title", this).text();
                var kmlLink     = $("kml", this).text();
                var proxyLink   = "./kmlProxy.php?url=" + encodeURIComponent(kmlLink);
                var folderCheck = $(document.createElement("div"));
                var folderId    = "collection_" + $("id", this).text();
                var checkerId   = "folderCheck_"+$("id", this).text();
                var hasChild    = 0; // Assign after parse KML
                var boundChild  = 0; // Assign after parse KML
                var isOpened    = ($.inArray(folderId, _opened) >= 0 );
                var isChecked   = ($.inArray(checkerId, _checked) >= 0 );

                // Set the class of folderCheck Box
                if ( isChecked )
                {
                    folderCheck.attr("class", "folderCheck overlay");
                }
                else
                    folderCheck.attr("class", "folderCheck");

                folderCheck.data("id", checkerId);
                childFolder.data("id", folderId);
                childFolder.data("kmlLink", proxyLink);
                childFolder.data("folderName", folderName);

				childFolder.addClass("collection kml last");
				if ( !isOpened )  {
					childFolder.addClass("closed");
				}
				childFolder.html('<div class="folder"><a href="#">' + folderName + '</a></div>');
				childFolder.prepend(folderCheck);
				
				parentNode.append(childFolder);
				childFolder.prev().removeClass("last");
				$('#intelliList').jScrollPane();
				
				if (typeof(_externalKml[folderId]) === 'undefined' ||
					_externalKml[folderId] === null)
				{
					var kml = new GGeoXml(kmlLink);
					_externalKml[folderId] = kml;
				}
				else
					kml = _externalKml[folderId];
					
				$(".folder", childFolder).click(function(){
					kml.gotoDefaultViewport(HyperCities.mainMap.getMapInstance());
            	});
		        
 				folderCheck.click( function(){
		            $(this).toggleClass("overlay");
		            
	                if ( $(this).hasClass("overlay") )
	                {
	                	if (! ($.inArray(checkerId, _checked) >= 0))
	                	{
	                		HyperCities.debug("add checked");
	                		_checked.push(checkerId);
	                	}
						HyperCities.mainMap.addOverlay(kml);
	                }
	                else
	                {
	                    if ( ($.inArray(checkerId, _checked) >= 0) )
	                    {
	                    	HyperCities.debug("remove checked");
							_checked.splice($.inArray(checkerId, _checked), 1);
	                    }
						HyperCities.mainMap.removeOverlay(kml);
	                }
 				});

//                if ( !isOpened )  {
//                    childFolder.addClass("closed");
//                    parentNode.append(childFolder);
////                    if ( isChecked ) // Update If it's check
////                        _getCollection(folderId);
//                } else {
//                    HyperCities.debug(_id + "Update Data of " + folderId);
//                    parentNode.append(childFolder);
//                    _parseKML(proxyLink, {name: folderName, context: childFolder, parentId: folderId, checker: folderCheck});
////                    _getCollection(folderId);
//                }

//                HyperCities.debug("Parse KML");
//                HyperCities.debug(proxyLink);
//                HyperCities.debug(folderName);
//                HyperCities.debug(childFolder);
//                HyperCities.debug(folderId);
//                HyperCities.debug(folderCheck);
//                HyperCities.debug("--------------------");
//                _parseKML( proxyLink, { name: folderName,
//                                        context: childFolder,
//                                        parentId: folderId,
//                                        checker: folderCheck});
//
            });
    };

    //jay
    var _append3DLinks = function(parentNode, $data) {

        parentNode.find(".folderCheck").unbind().remove();
        parentNode.empty();

        HyperCities.debug(_id + "Append " + $data.length + " KML Collections");
        $data.each( function() {

            var childFolder = $(document.createElement("li"));
            var folderName  = $("title", this).text();
            var kmlLink     = $("kml", this).text();
            var folderCheck = $(document.createElement("div"));
            var folderId    = "collection_" + $("id", this).text();
            var checkerId   = "folderCheck_"+$("id", this).text();
            var hasChild    = 0; // Assign after parse KML
            var boundChild  = 0; // Assign after parse KML
            var isOpened    = ($.inArray(folderId, _opened) >= 0 );
            var isChecked   = ($.inArray(checkerId, _checked) >= 0 );
            var earth       = HyperCities.earth.getEarth();

			google.earth.fetchKml(earth, kmlLink, function($kmlObject){
				if ($kmlObject)
				{
					//if (HyperCities.earth.inView(earth, $kmlObject))
					{
						// Set the class of folderCheck Box
			            if ( isChecked )
			            {
			                folderCheck.attr("class", "folderCheck overlay");
	                		HyperCities.earth.appendKmlObject({id:folderId, obj:$kmlObject});
			            }
			            else
			                folderCheck.attr("class", "folderCheck");

			            folderCheck.data("id", checkerId);

			            childFolder.data("id", folderId);
			            childFolder.data("kmlLink", kmlLink);
			            childFolder.data("folderName", folderName);

			            childFolder.addClass("collection kml last");
			            if ( !isOpened )  {
			                childFolder.addClass("closed");
			            }
			            childFolder.html('<div class="folder"><a href="#">' + folderName + '</a></div>');
			            childFolder.prepend(folderCheck);

						parentNode.append(childFolder);
			            childFolder.prev().removeClass("last");
			            //$("#intelliList").children(":last").css("margin", "0");
				        $('#intelliList').jScrollPane();


						//_parse3DKML(kmlLink, {name: folderName, context: childFolder, parentId: folderId, checker: folderCheck});
						$(".folder", childFolder).click(function(){
							if (HyperCities.mainMap.getCurrentMapType() === G_SATELLITE_3D_MAP)
								HyperCities.earth.zoomToFeature(earth, $kmlObject);
							else
								alert("Please switch to earth mode.");
		            	});

			            folderCheck.click( function()
			            {
			            	if (HyperCities.mainMap.getCurrentMapType() === G_SATELLITE_3D_MAP)
			            	{
			            		//jay
				                HyperCities.debug("folderId="+folderId);
				                HyperCities.debug("checkerId="+checkerId);
	
				                $(this).toggleClass("overlay");
	
				                if ( $(this).hasClass("overlay") )
				                {
				                	if (! ($.inArray(checkerId, _checked) >= 0))
				                	{
				                		//HyperCities.debug("add checked");
				                		_checked.push(checkerId);
				                	}
			                    	HyperCities.earth.appendKmlObject({id: folderId, obj:$kmlObject});
				                }
				                else
				                {
				                    if ( ($.inArray(checkerId, _checked) >= 0) )
				                    {
				                    	//HyperCities.debug("remove checked");
										_checked.splice($.inArray(checkerId, _checked), 1);
				                    }
	
				                    HyperCities.earth.removeKmlObject({id: folderId, obj:$kmlObject});
				                }
				                return false;
			            	}
			                else
			                	alert("Please switch to earth mode.");
			            });
					}
				}
			});
        });
    };

    var _parse3DKML = function ($url, $opt) {

		HyperCities.debug(_id + "parse 3D KML");
        //HyperCities.debug("$url="+$url);
        if ( typeof($opt) !== 'object' ) return ;

        var option = $opt;
        var folderName = option.name;
        var folderDiv  = option.context;
        var folderId   = option.parentId;
        var checker    = option.checker;

        // Show Loading Icon
        $("#treeviewWrapper .collection").filter( function (){ return $(this).data("id") == folderId })
                                         .find("> .folder")
                                         .append('<img src="./images/loading.gif" alt="Loading..." />');

		HyperCities.debug(folderId + " : " + $(".folder", folderDiv).html());

		if (HyperCities.mainMap.getCurrentMapType() === G_SATELLITE_3D_MAP)
		{
			var hasChild = 0;
		    var boundChild = 0;
		    //var kmlObjects = HyperCities.earth.getCollections();
		    var earth = HyperCities.earth.getEarth();
		    var url = $url;

			google.earth.fetchKml(earth, url, function($kmlObject){
				if ($kmlObject)
				{
					// Reset Collection Title
		            $(".folder", folderDiv).html( '<a href=#>' + folderName + '</a> (' + boundChild + '/' +  hasChild + ')' );
		            $(".folder", folderDiv).click(function(){
		            	HyperCities.earth.zoomToFeature(earth, $kmlObject);
		            });

		            checker.click( function()
		            {
		                var folderId  = $(this).parent().data("id");
		                var checkerId = "folderCheck_"+folderId.split('_')[1];
		                var isOpened  = ($.inArray(folderId, _opened) >= 0 );
		                var isChecked = ($.inArray(checkerId, _checked) >= 0 );

		                //jay
		                HyperCities.debug("folderId="+folderId);
		                HyperCities.debug("checkerId="+checkerId);

		                if ( !isOpened && !$(this).hasClass("overlay") ) {
		                    $(this).parent().find(".hitarea").trigger("click");
		                }

		                $(this).toggleClass("overlay");

		                if ( $(this).hasClass("overlay") ) { // Select all children
		                    _checked.push(checkerId);

		                    HyperCities.earth.appendKmlObject({id: folderId, obj:$kmlObject});

		                    $(this).parent().find("ul .folderCheck").each( function() {
		                        if ( !$(this).hasClass("overlay") )
		                            $(this).toggleClass("overlay");
		                            //$(this).trigger("click");
		                        });
		                } else { // unselect all children
		                    if ( isChecked )
		                        _checked.splice($.inArray(checkerId, _checked), 1);

		                    HyperCities.earth.removeKmlObject({id: folderId, obj:$kmlObject});

		                    $(this).parent().find("ul .folderCheck").each( function() {
		                         if ( $(this).hasClass("overlay") )
		                            $(this).toggleClass("overlay");
		                            //$(this).trigger("click");
		                         });
		                }
		                return false;
		            });

		            //_addKmlNode(children, folderDiv, folderId);
				}
			});
			//$("#treeviewWrapper .collection").find("> .folder").find(" img").remove();
		}
    };

    var _removeOldKml = function($objectId) {
		for (var i=0; i<_oldKmlOverlay.length; i++)
		{
			var oldKmlOverlay = _oldKmlOverlay[i];

			if (oldKmlOverlay.objectId == $objectId)
			{
                if ( oldKmlOverlay.overlay !== null )
    				HyperCities.mainMap.removeOverlay(oldKmlOverlay.overlay);
				_oldKmlOverlay.splice(i, 1);
			}
		}
	};

    //jay
    var _showOldKml = function($data) {
    	var content = $($data).find("object > content").text();
    	content = content.replace(/&amp;amp;/g, "&").replace(/&amp;/g, "&").replace(/&apos;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">");
    	//HyperCities.debug("content="+content);

    	//match .kml or .kmz first, if no match, then match maps.google.com
    	var kmlUrl = content.match(/http:\/\/[\W\w]+(.kml|.kmz)+/g);
    	if (kmlUrl == null)
    	{
    		kmlUrl = content.match(/http:\/\/maps.google.com\S+\s*" /g);
    		//delete the last characters " and blank
    		if (kmlUrl != null)
    		{
    			kmlUrl = kmlUrl.toString();
    			//HyperCities.debug("kmlUrl="+kmlUrl);
    			//HyperCities.debug("kmlUrl.length="+kmlUrl.length);
    			kmlUrl = kmlUrl.substring(0, kmlUrl.length-2);
    		}
    	}

    	if (kmlUrl != null)
    	{
    		HyperCities.debug(_id + "Fetch old kml at "+kmlUrl);
    		kmlUrl = kmlUrl.toString();
	    	var geoXml = new GGeoXml(kmlUrl);
			HyperCities.mainMap.addOverlay(geoXml);

			for (var i=0; i<_oldKmlOverlay.length; i++)
			{
				var overlay = _oldKmlOverlay[i];

				if (overlay.overlay == null)
					overlay.overlay = geoXml;
			}
		}
    };

    var _renderContent = function($data) {

        var title     = $($data).find("object > title").text();
        var creator   = $($data).find("object > creator").text();
        var copyright = $($data).find("object > copyright").text();
        var content   = $($data).find("object > content").text();
        var mapYear   = Date.today().toString("yyyy");
        var startTime = Date.parse($($data).find("object > startTime").text());
        var endTime   = Date.parse($($data).find("object > endTime").text());
        var timespan  = "Not specify";
        var htmlMin   = "";
        var htmlFull  = "";
        var maxTitle  = "";
        var maxTitleLen  = 60;
        var parentItem   = $($data).find("parent:first");
        var totalParents = $($data).find("parent").length;
        var parentId  = null;
        var hasPrev   = false;
        var hasNext   = false;
        var params    = {};
		var objectId  = $($data).find("object > id").text();
        
        if ( startTime !== null && endTime !== null )
        {
            //timespan = startTime.toString("yyyy") + " - " + endTime.toString("yyyy") ;	
            timespan = startTime.getFullYear() + " ~ " + endTime.getFullYear() ;	
        }
        else if ( startTime !== null )
        {
            //timespan = startTime.toString("yyyy") + " - " ;
            timespan = startTime.getFullYear().toString() + " ~ " ;
        }
        else if ( endTime !== null && endTime.toString("yyyy") !== "9999" )
        {
        	//timespan = " - " + endTime.toString("yyyy") ;
        	timespan = " ~ " + endTime.getFullYear().toString() ;
        }
            

		//check startTime and endTime if they are null
        if ( _syncMap && (startTime != null) && (endTime != null))
        {
            HyperCities.timebar.setTime(null, startTime.getFullYear().toString(), endTime.getFullYear().toString(), null);
            HyperCities.mainMap.setTimespan({min: startTime, max: endTime}, false);
            
            latLonBox = HyperCities.mainMap.getBounds();
            zoom      = HyperCities.mainMap.getZoom();
           	HyperCities.mapList.update(latLonBox, zoom, false, false);            

            //mapYear   = HyperCities.mapList.overlayBaseMap(startTime.toString("yyyy"), true);
			//HyperCities.mapList.overlayBaseMap(startTime.toString("yyyy"), true);
			HyperCities.mapList.overlayBaseMap(startTime.getFullYear().toString(), true);
            $("#loadingMessage").fadeOut("slow");
        }

        if ( parentItem.length == 1 ) {
            parentId = parentItem.find("id").text();
			HyperCities.debug("Parent ID" + parentId);
            hasPrev  = (parentItem.find("previous_id").length == 1 && !(_permalinkHideArrows));
            hasNext  = (parentItem.find("next_id").length == 1 && !(_permalinkHideArrows));
        	
            if ( hasPrev ) {
                _previousItem = { parentId: parentId,
                                  id: parentItem.find("previous_id").text(),
                                  title: parentItem.find("previous_title").text(),
                                  center: new GLatLng(parseFloat(parentItem.find("previous_lat").text()),
                                                      parseFloat(parentItem.find("previous_lng").text())),
                                  kml: parentItem.find("previous_kml").text(),
                                  startTime: Date.parse(parentItem.find("previous_startTime").text()),
                                  endTime: Date.parse(parentItem.find("previous_endTime").text())
                                };

                if ( typeof(_objects[_previousItem.id]) == 'undefined' )
                    _addObject(_previousItem.id, _previousItem.kml);

            }
            if ( hasNext ) {
                _nextItem = { parentId: parentId,
                              id: parentItem.find("next_id").text(),
                              title: parentItem.find("next_title").text(),
                              center: new GLatLng(parseFloat(parentItem.find("next_lat").text()),
                                                  parseFloat(parentItem.find("next_lng").text())),
                              kml: parentItem.find("next_kml").text(),
                              startTime: Date.parse(parentItem.find("next_startTime").text()),
                              endTime: Date.parse(parentItem.find("next_endTime").text())
                            };

                if ( typeof(_objects[_nextItem.id]) == 'undefined' )
                    _addObject(_nextItem.id, _nextItem.kml);

            }
//            HyperCities.debug(_previousItem);
//            HyperCities.debug(_nextItem);
        }

        if ( totalParents > 1 )
            parentId = null;

        content = content.replace(/&amp;/g, "&").replace(/&apos;/g, "'").replace(/&lt;/g, "<").replace (/&gt;/g, ">");

        title = title.replace(/"/g, "&quot;");

        // TODO: Rewrite string concatnate using array join
        htmlMin = '<div class="HCContent">';
        htmlFull = '<div class="HCContent">';

        if ( hasPrev ) {
            htmlMin += '<div class="HCContentPrev" onClick="HyperCities.collectionList.flyTo(\'prev\', false)"></div>';
            maxTitle += '<div class="HCContentMaxPrev" onClick="HyperCities.collectionList.flyTo(\'prev\', true)">Previous</div>';
        }

        // Truncate Max Title
        var tempTitle = title;
        while (maxTitleLen < title.length) {
            c = title.charAt(maxTitleLen);
            if (c.match(/\s/)) {
                tempTitle = '<div class="HCContentMaxTitle" title="'+title+'">'
                          + title.substring(0,maxTitleLen) + "...</span>";
                break;
            }
            maxTitleLen--;
        }
        maxTitle += tempTitle;

        if ( hasNext ) {
            htmlMin += '<div class="HCContentNext" onClick="HyperCities.collectionList.flyTo(\'next\', false)"></div>';
            maxTitle += '<div class="HCContentMaxNext" onClick="HyperCities.collectionList.flyTo(\'next\', true)">Next</div>';
        }

        htmlMin += '<img src="./images/HC_banner.jpg" alt="HyperCities" />'
                 + '<div class="HCContentTitle">' + title + '</div>'
                 + '<div class="HCContentMeta">Creator: ' + creator + '</div>'
                 //+ '<div class="HCContentMeta">Copyright: ' + copyright + '</div>'
                 + '<div class="HCContentMeta">Time: ' + timespan + '</div>'
                 //+ '<div class="HCContentMeta">Map Time: ' + mapYear + '</div>'
                 + '<a href="javascript:void(0);" onClick="HyperCities.mainMap.maximizeInfoWindow()">more info »</a>'  
                 + '</div>';


        htmlFull += '<img src="./images/HC_banner.jpg" alt="HyperCities" />'
                  + '<div class="HCContentTitle">' + title + '</div>'
                  + '<div class="HCContentMeta">Creator: ' + creator + '</div>'
                  //+ '<div class="HCContentMeta">Copyright: ' + copyright + '</div>'
                  + '<div class="HCContentMeta">Time: ' + timespan + '</div>'
                  //+ '<div class="HCContentMeta">Map Time: ' + mapYear + '</div>'
                  + '<a href="javascript:void(0);" onClick="HyperCities.collectionList.showUpdateWindow(' + _infoWindowId+','+parentId+')">Update</a> '
                  + '<a href="javascript:void(0);" onClick="HyperCities.collectionList.deleteItem('+ _infoWindowId+','+parentId+')">Delete</a>'+ '<br />'
				  + 'Link to this object: <a href="http://linuxdev.ats.ucla.edu/?item_type=object&item_id='+ objectId 
				  + '">http://linuxdev.ats.ucla.edu/?item_type=object&item_id=' + objectId + "</a>" 
                  + '<div class="HCContentText" id="'+_infoWindowId+'">' + content + '</div>'
                  + '</div>';

        params = {maxTitle: maxTitle, maxContent: htmlFull};

	        if ( typeof(_objects[_infoWindowId]) == 'undefined' )
    	        HyperCities.debug("Error : Object " + _infoWindowId + " does not exist!");
	        else if ( _objects[_infoWindowId].overlay.gmarkers.length > 0 ) {
				
				if (HyperCities.mainMap.getCurrentMapType() === G_SATELLITE_3D_MAP)
				{
					var lookAt = HyperCities.earth.getLookAt();
					var latLng = _objects[_infoWindowId].overlay.gmarkers[0].getLatLng();
					lookAt.setLatitude(latLng.lat());
					lookAt.setLongitude(latLng.lng());
					_objects[_infoWindowId].overlay.gmarkers[0].openInfoWindowHtml(htmlMin, params);
					HyperCities.earth.setView("KmlLookAt", lookAt);
				}
				else
    	        	_objects[_infoWindowId].overlay.gmarkers[0].openInfoWindowHtml(htmlMin, params);
	        } else if ( _objects[_infoWindowId].overlay.gpolygons.length > 0 ) {
    	        HyperCities.mainMap.getMapInstance().openInfoWindowHtml(_objects[_infoWindowId].overlay.gpolygons[0].getBounds().getCenter(), htmlMin, params);
	        } else if ( _objects[_infoWindowId].overlay.gpolylines.length > 0 ) {
    	        HyperCities.mainMap.getMapInstance().openInfoWindowHtml(_objects[_infoWindowId].overlay.gpolylines[0].getBounds().getCenter(), htmlMin, params);
	        }

        // If necessary, Maximize InfoWindow
        // Use setTimeout to queue the maximize Event till InfoWindow is ready
        if ( _maximizeInfoWindow )
            setTimeout("HyperCities.mainMap.maximizeInfoWindow();",500);

        // Reset the CurrentCollectionId
        _currentCollectionId = -1;
		// Now, the next window shown will have arrows if it is part of a narrative
		_permalinkHideArrows = false;
    };

*/
    var _getCollection = function ($collectionId, $isExternal) {
        //		HyperCities.debug(_id + "[A2] Get Collection");

        // Skip Update First Level Folder
        if ( $.inArray($collectionId, _skipList) >= 0 ) {
            //			HyperCities.debug(_id + "[A2] Skip update Collection " + $collectionId);
            return;
        }

        var isUpdated = ($.inArray($collectionId, _updated) >= 0 ),
        params = {
            func : "collectionList.getCollection",
            cid : $collectionId
        },
        yearFrom,
        yearTo;


        // we don't need to update multiple times in Single Round
        if ( isUpdated ) {
			// Hide Loading Icon
			$("#treeviewWrapper ." + CLASSES.collection + $collectionId)
				.find("img." + CLASSES.loading + ":first").hide();
            return;
        }
        else {
            _updated.push($collectionId);
        }

        // David, 10-19-09: Moved to after update test, for search engine, because
        // at this point, _mapBounds is undefined
        // Setup query mapBounds and mapZoom
        params.neLat = _mapBounds.getNorthEast().lat();
        params.neLng = _mapBounds.getNorthEast().lng();
        params.swLat = _mapBounds.getSouthWest().lat();
        params.swLng = _mapBounds.getSouthWest().lng();
        params.zoom  = _mapZoom;


        // Show Loading Icon
        $("#treeviewWrapper ." + CLASSES.collection + $collectionId)
        .find("img." + CLASSES.loading + ":first").show();

        // Only update collection for non external collection
        if ( !$isExternal ) {
            // Setup query timespan
            if ((typeof(_timespan) !== 'undefined') &&
                (_timespan.min instanceof Date) && (_timespan.max instanceof Date)) {

                params.dateFromIsBC = 0;
                params.dateToIsBC = 0;

                yearFrom = _timespan.min.getFullYear();
                yearTo   = _timespan.max.getFullYear();

                // Change negative year to positive and assign BC flag
                if ( yearFrom < 0 ) {
                    params.dateFromIsBC = 1;
                    yearFrom = -1 * yearFrom;
                }

                if ( yearTo < 0 ) {
                    params.dateToIsBC = 1;
                    yearTo = -1 * yearTo;
                }

                params.dateFrom = yearFrom + _timespan.min.toString("-MM-dd");
                params.dateTo   = yearTo + _timespan.max.toString("-MM-dd");

                // Pad leading zero to make it four digits
                while (params.dateFrom.length < 10) {
                    params.dateFrom = "0" + params.dateFrom;
                }

                while (params.dateTo.length < 10) {
                    params.dateTo = "0" + params.dateTo;
                }
            } // end if, end of timespan params process

            $.post("./getCollection.php", params, _parseCollection, "xml");
        }
    };

    //jay: update collection
    var _updateCollection = function($data) {

        var collectionId = parseInt($data.id),
			title        = $data.title,
			creator      = $data.author,
			//copyright    = $data.copyright,
			description  = $data.description,
			userId       = (HyperCities.user.getUserId() === null) ? HyperCities.config.HC_USER_ADMIN : HyperCities.user.getUserId();
			state        = parseInt($data.stateId),
			oldAddTo     = [];		// the original parent collections of this collection


        HyperCities.debug(_id + "Update collection " + collectionId);

		//tab1 "content"
        var tab1 = $('<div class="HCUpdateColDiv">'
            +'<div class="form-item"><label> Title:  </label> <input type="text" id="title"></div>'
            +'<div class="form-item"><label> Author: </label><input type="text" id="creator"></div>'
            //+'<div class="form-item"><label> Copyright: </label><input type="text" id="copyright"></div>'
            +'<div class="form-item"><label> Description: </label><textarea rows="5" cols="30" id="description"></textarea></div>'
            +'<div class="form-item"><div style="width:100px;height:80px;float:left"><label> State: </label></div>'
            +'<div id="publicDiv"><input type="radio" name="state" value="1" id="public">Public</div>'
            +'<div id="protectedDiv"><input type="radio" name="state" value="2" id="protected">Protected</div>'
            +'<div id="hiddenDiv"><input type="radio" name="state" value="3" id="hidden">Hidden</div>'
            //+'<input type="radio" name="state" value="4">Inappropriate'
            //+'<input type="radio" name="state" value="5">Delete'
            +'</div><br/>  <div class="HCBottomBar"><input type="button" id="next" value="Next"></div>');
        $("#title", tab1).val(title);
        $("#description", tab1).val(description);
        $("#creator", tab1).val(creator);
        //$("#copyright", tab1).val(copyright);

		//select state
		$("input:radio:eq("+(state-1)+")", tab1).attr("checked", true);

		//show password if state = protected
		if (state === HyperCities.config.HC_OBJECT_PRIVATE)
		{
			if ($("#protectedDiv div").length < 1)
			{
				var password = $("<div style='position:relative;left:20px'>"
								+ "keycode:<input type='password' id='password'></div>");
				$("#protectedDiv", tab1).append(password);
			}
		}
		//show options for private state
		$("#protected", tab1).click(function() {

			if ($("#protectedDiv div").length < 1)
			{
				var password = $("<div style='position:relative;left:20px'>"
								+ "password:<input type='password' id='password'></div>");
				$("#protectedDiv", tab1).append(password);
			}
		});

        $("#next", tab1).click( function() {
            HyperCities.mainMap.getInfoWindow().selectTab(1);
        });

		//tab2 "add to"
		var tab2 = $("<div><b><span id='addOwnCTitle'>Add it to other collections:</span></b>"
					+ "<div id='treePanel' style='height:300px; overflow:auto'>"
					+ "<ul id='tree'></ul>"
					+ "</div>"
					+ "<div class='HCBottomBar'><input type='button' id='next' value='next'></div></div>");

		/*
        var tab2 = $("<div><div><b><span id='addOwnCTitle'>Add it to my collections:</span></b>"
            + "<div id='own_collections'></div></div>"
            + "<div><b><span id='addOtherCTitle'>Add it to other collections:</span></b>"
            + "<div id='other_collections'></div></div>"
			+ "<div class='HCBottomBar'><input type='button' id='next' value='Next'></div></div>");
        HyperCities.util.loadCollectionList(tab2, null, collectionId);
		*/

        $("#next", tab2).click( function() {
            HyperCities.mainMap.getInfoWindow().selectTab(2);
        });

		//tab3 "share"
		var tab3 = $("<div><div><b><span class='infoWinTitle'>Share this collection with your friends:</span></b></div>"
					+"<div id='addUser'><div><span class='infoWinTitle'>Please enter your friend's last name:</span></div>"
					+"<div style='width:400px;height:30px'><input id='username' type='text'/><input type='button' id='addUserBtn' value='add'></div></div>"
					+"<div class='collectionPanel' style='width:400px;height:280px'></div>"
		            +"<div class='HCBottomBar'></div></div>");
		HyperCities.util.loadUserList($(".collectionPanel", tab3), collectionId);

		$("#addUserBtn", tab3).click(function(){
			
			var username = $("#username", tab3).val();
			var params = {command: "queryUser", username: username};

			$.post("./user.php", params, function($data){
                var error = $($data).find("Error > Message").text();

                if ( error.length > 0 ) {
                    alert(error);
                }
                else
                {
					$($data).find("Users > user").each( function() {

						var userId     = parseInt($("userId", this).text());
						var username   = $("username", this).text();
						var accessId   = HyperCities.config.HC_ACCESS_VIEW;
						var userItem   = $("<div id="+userId+"></div>");
						var checkbox   = $("<div style='float: left'><input type='checkbox'/></div>");
						var username   = $("<div style='width:120px; float:left'><span>"+username+"</span></div>");
						var accessItem = HyperCities.util.loadAccessId(userId, accessId);

						userItem.append(checkbox).append(username).append(accessItem);
						$(".collectionPanel").append(userItem);	
					});
				}
            }, "xml");
		});

		var updateBtn = $("<input type='button' id='updateBtn' value='Update'>");
        updateBtn.click( function(){

            var title              = $.trim($("#title").val());
            var objectStateId      = $("input[name=state]:checked").val();
            var description        = $.trim($("#description").val());
            var creator            = $.trim($("#creator").val());
            var copyright          = $.trim($("#copyright").val());
			var password           = $("#password").val();
            var addTo              = new Array();
			var userIdArray        = new Array();
			var accessRightIdArray = new Array();
		

			$(".checkboxChecked").next().each(function(){
				addTo.push($(this).attr("id"));	
			});

			/*
            $("input[name=otherOption]:checked").each(function() {
                addTo.push($(this).data("collectionId"));
            });
            $("input[name=ownOption]:checked").each(function() {
                addTo.push($(this).data("collectionId"));
            });
			*/

            if (addTo.length === 0)
            {
                alert("Please check at least one collection!");
                return;
            }

			$("select").each(function(){
				userIdArray.push($(this).data("userId"));		
				accessRightIdArray.push($("option[selected]", this).val());
			});

            var params = {
                collectionId: collectionId,
                title: title,
                objectStateId: objectStateId,
				password: password,
                description: description,
                creator: creator,
                //copyright: copyright,
                addTo: addTo.toString(),
				oldAddTo: oldAddTo.toString(),
				userIdArray: userIdArray.toString(),
				accessRightIdArray: accessRightIdArray.toString()
			};
           
			$.post("./updateCollection.php", params, function($response){
            
                var success = $($response).find("Success > Message").text();
                var error   = $($response).find("Error > Message").text();

                if ( error.length > 0 ) {
                    alert(error);
                }
                else
                {
                    alert(success);
                }
                
                HyperCities.mainMap.closeInfoWindow();
            }, "xml");
        });


        //tabInfoWindow variables
        var label1 = "1. Content";
        var label2 = "2. Add to";
		var label3 = "3. Share";
        var updateWindow;
		
		if (HyperCities.user.isAdmin())
		{
			tab3.find("#addUser").remove();
			tab3.find(".collectionPanel").css("height", "330px");
		}

		tab3.find("div:last").append(updateBtn);
		updateWindow = [ new GInfoWindowTab(label1, tab1.get(0)),
						 new GInfoWindowTab(label2, tab2.get(0)),
						 new GInfoWindowTab(label3, tab3.get(0))];
		//}
		//else
		//{
		//	tab2.find("div:last").empty().append(updateBtn);
		//	updateWindow = [ new GInfoWindowTab(label1, tab1.get(0)),
		//					 new GInfoWindowTab(label2, tab2.get(0))];
		//}
		var map = HyperCities.mainMap.getMapInstance();
		var infoWinOpenHandle = GEvent.addListener(map, "infowindowopen", function(){
			//load collection list after info window is opened
			var tree = HyperCities.util.loadCollectionTree($("#tree", tab2), oldAddTo, collectionId, true);
		});

		var infoWinCloseHandle = GEvent.addListener(map, "infowindowclose", function(){
			GEvent.removeListener(infoWinOpenHandle);
		});

        HyperCities.mainMap.openInfoWindow("tabsHtml", HyperCities.mainMap.getCenter(),
											updateWindow, {maxWidth: 400, noCloseOnClick:true});
    };

    return {

        // Update the Collection list
        update: function($mapBounds, $mapZoom, $doRender) {
			//HyperCities.debug(_id + "[A2] Update Collection List");

            var params = {
                func : "collectionList.getCollectionList"
            },
            yearFrom,
            yearTo;

            $("#loadingMessage").fadeIn("fast");

			_doRender = false;
            if ( typeof($doRender) === "boolean" ) {
                _doRender = $doRender;
            } 

            // Setup System Mode
            _originalMode = HyperCities.session.get("mode");
            if ( _doRender ) {
                HyperCities.session.set("mode", HyperCities.config.MODE_COLLECTION_LIST);
				HyperCities.mapList.removeMapsProxy();
			}


            // Setup query mapBounds, input should be a GLatLngBounds Object
            if ( $mapBounds instanceof GLatLngBounds ) {
                _mapBounds = $mapBounds;
            } else {
                _mapBounds = HyperCities.mainMap.getBounds();
            }

            // Setup query mapZoom, input should be a number and must be integer
            if ( typeof($mapZoom) === "number" ) {
                _mapZoom = parseInt($mapZoom);
            } else {
                _mapZoom = HyperCities.mainMap.getZoom();
            }

            params.neLat = _mapBounds.getNorthEast().lat();
            params.neLng = _mapBounds.getNorthEast().lng();
            params.swLat = _mapBounds.getSouthWest().lat();
            params.swLng = _mapBounds.getSouthWest().lng();
            params.zoom  = _mapZoom;

            // Setup query timespan
            _timespan = HyperCities.mainMap.getTimespan();
            if ((typeof(_timespan) !== 'undefined') &&
                (_timespan.min instanceof Date) && (_timespan.max instanceof Date)) {

                params.dateFromIsBC = 0;
                params.dateToIsBC = 0;

                yearFrom = _timespan.min.getFullYear();
                yearTo   = _timespan.max.getFullYear();

                // Change negative year to positive and assign BC flag
                if ( yearFrom < 0 ) {
                    params.dateFromIsBC = 1;
                    yearFrom = -1 * yearFrom;
                }

                if ( yearTo < 0 ) {
                    params.dateToIsBC = 1;
                    yearTo = -1 * yearTo;
                }

                params.dateFrom = yearFrom + _timespan.min.toString("-MM-dd");
                params.dateTo   = yearTo + _timespan.max.toString("-MM-dd");

                // Pad leading zero to make it four digits
                while (params.dateFrom.length < 10) {
                    params.dateFrom = "0" + params.dateFrom;
                }

                while (params.dateTo.length < 10) {
                    params.dateTo = "0" + params.dateTo;
                }
            } // end if, end of timespan params process

            //jay: disable this line so that we can see collections in worldwide level
            //if ( _mapZoom < HyperCities.config.ZOOM_THRESHOLD ) {
            //	HyperCities.city.renderList(_mapBounds);
            //} else {
            $.post("./getCollectionList.php", params, _parseCollectionList, "xml");
        //}
        },

        /**
         * Adds an object to the map, opens its info window, and returns that object.
         */
        addObject: function ($id) {
            
           var id = $id + "";
           HyperCities.debug(_id + "Checking item " + id);
            _checkItem(id);
            
            return _objects[_getObjectIndexById(id)];
			/*
            // OLD METHOD:
			// Note _createPlacemark parameter changes, need to check again, call _updatePlacemark instead
            var markerDom = _createPlacemark (id, $("title", $data).text(), "http://hypercities.ats.ucla.edu/" + id + ".kml", $($data).find("Placemark")[0], true);

            var offset = _getObjectIndexById(id);
            HyperCities.mainMap.addOverlay(_objects[offset].overlay);
            //HyperCities.debug(_id + "Current map center: " + HyperCities.mainMap.getMapInstance().getCenter());
            HyperCities.mainMap.openHCInfoWindow(_objects[offset]);
            // Done to compensate for bug in openHCInfoWindow -- HCOldLatLng doesn't always equal HyperCities.mainMap.getCenter().
            HyperCities.mainMap.getMapInstance().HCOldLatLng = HyperCities.mainMap.getCenter();
			*/
        }, // end function addObject($itemId)

        
        getObjectById: function ($id) {
            // Counterintutitively, ids are actually stored as strings.
            // The $id + "" casts an int to a string.
            return _objects[_getObjectIndexById($id + "")];
        },

        highlightItem: function($itemId) {
            //			HyperCities.debug(_id + "Hover over object " + $itemId);

            var itemIndex = _getObjectIndexById($itemId),
            item, latLng;

            if ( itemIndex >= 0 && _HMarker.isHidden() ) {
                item = _objects[itemIndex];

                // Get LatLng of Item
                if ( typeof(item) !== 'undefined' && item.type === CLASSES.item ) {
                    // item.overlay already exist and is Correct
                    if ( item.overlay instanceof GOverlay ){
                        latLng = item.overlay.getLatLng();
                        if ( latLng instanceof GLatLng ) {
                            _HMarker.setLatLng(latLng);
                            _HMarker.show();
                        }
                    }
                    // Highlight Item in Collection list
                    $("#treeviewWrapper ." + CLASSES.item + $itemId + " ." + CLASSES.markerLink)
                    .addClass("hover");
                }
            }
            return false;
        },

        unHighlightItem: function($itemId) {
            //			HyperCities.debug(_id + "Hover off object " + $itemId);
            if ( _HMarker instanceof GMarker ) {
                _HMarker.hide();
            }
            // unHighlight Item in Collection list
            $("#treeviewWrapper ." + CLASSES.item + $itemId + " ." + CLASSES.markerLink)
            .removeClass("hover");

            return false;
        },

        // show Info Windows on map
        showInfoWindow: function($itemId, $collectionId) {

            var objectIndex = _getObjectIndexById($itemId),
            item, options = {};
			
            if ( objectIndex >= 0 ) {
                item = _objects[objectIndex];

                // Make sure we have the information of object
                if ( typeof(item) !== 'undefined' && item.overlay instanceof GOverlay ) {
                    //HyperCities.debug(_id + "[A2] Show InfoWindow of Item " + $itemId);

                    // Setup InfoWindow Options
                    options.isCollection = (item.type === CLASSES.collection);
                    if ( typeof($collectionId) !== 'undefined' ) {
                        options.collectionId = $collectionId;
                    }

                    // Open HyperCities InfoWindow
                    HyperCities.mainMap.openHCInfoWindow(item, options);
                }
            }
        },

        // Get List of Collection Id that is opened
        getOpenedCollections: function() {
            return _opened;
        },

        openCollection: function ($collectionId) {
            _setFolderStatus ($collectionId, true);
        },

        // Get List of Colelction Id that is checked
        getCheckedCollections: function() {
            return _checked;
        },

        checkCollection: function ($itemId) {
            _checkItem($itemId);
        },

        uncheck: function ($item) {
            if ($item instanceof Array) {
                for (var i in $item) {
                    _uncheckItem($item[i]);
                }
            } else {
                _uncheckItem($item);
            }
        },

        // Uncheck All checked items, and therefore remove all overlay on the map
        uncheckAllItems: function() {
            var isFocused = $("#collectionTab").parent().hasClass("highlight");

            // uncheck each checkedItem by yielding processes
            if ( _checked.length > 0 ) {
                setTimeout(function() {
                    var itemId = _checked[0];

                    if ( isFocused ) {
                        _uncheckItem(itemId);
                    } else {
                        _hideItemOverlay(itemId);
                        _checked.shift();
                    }

                    if ( _checked.length > 0 ) {
                        setTimeout(arguments.callee, 10);
                    }
                }, 10);
            }
        },

        collapseAllFolders: function() {
            var isFocused = $("#collectionTab").parent().hasClass("highlight");

            // collapse each openedItem by yielding processes
            if ( _opened.length > 0 && isFocused ) {
                _progressCount = _opened.length;

                setTimeout(function() {
                    var folderId = _opened[0];

                    _setFolderStatus(folderId, false);

                    if ( _opened.length > 0 ) {
                        setTimeout(arguments.callee, 10);
                    }

                    _progressCount--;
                    $("#treeviewWrapper").trigger('HCUpdateFinish');
                }, 10);
            } else {
                _opened = [];
            }
        },

        collapseFolders: function ($folders) {
            if ($folders instanceof Array) {
                for (var i in $folders) {
                    _setFolderStatus($folders[i], false);
                }
            }
        },

        panToItem: function($itemId, $options) {

            var options    = $options || {},
            openWindow = (options.openWindow === true),
            itemIndex  = _getObjectIndexById($itemId),
            item, latLng;

            if ( itemIndex >= 0 ) {
                item = _objects[itemIndex];

                // Get LatLng of Item
                if (( typeof(item) !== 'undefined' ) &&
                    ( item.type === CLASSES.item ) &&
                    ( item.overlay instanceof GOverlay)) {

                    latLng = item.overlay.getLatLng();
                    if ( latLng instanceof GLatLng ) {
                        HyperCities.mainMap.panTo(latLng);
                    }
                }
            }
        },

        updateCollection: function($data) {
            _updateCollection($data);
        },

        queuePostSyncOperation: function ($op, $data) {
            _queuedOperations.push({op:$op, data:$data});
        },

        addCitation: function ($id, $refCode, $content) {
            if (typeof(_citations[$id]) == 'undefined') _citations[$id] = [];
            _citations[$id][$refCode] = $content;
            
        },

        addCitations: function ($itemId, $citationData) {
            _citations[$itemId] = [];
            $("citation", $citationData).each(function () {
                _citations[$itemId][$(this).attr("ref")] = $(this).text();
                //HyperCities.debug($(this).text());
            });
        },

        getCitation: function ($id, $refCode) {
            //HyperCities.debug(_citations[$id][$refCode]);
            return _citations[$id][$refCode];
        },

        parseSearchResult: function ($data) {
            HyperCities.debug(_id + "Search result returned");
            if (!$('#collectionList').hasClass('highlight')) {
                //HyperCities.debug(_id + "Clearing collection list");
                $('#mapAutoSync').attr('checked', false);
                $('#mapTab').parent().removeClass('highlight');
//                $('#mapTab').removeClass('highlight');
                $('#collectionTab').parent().addClass('highlight');
            }
            HyperCities.intelliList.reset();
            // Reset collection list -- don't keep Public collections, My Collections, etc.
            // Because they will be added if they have items in the search result
            HyperCities.debug (_id + "Clearing collection list");
            _resetCollectionList();

            // Create or Get collection tree root
            var treeRoot = $("#treeviewWrapper");
            if ( treeRoot.length <= 0 ) {
                treeRoot = _initCollectionList();
            }
            
            // For each item in each level of data, parse it
            var _parseChildren = function ($data, $parentNode) {
                var id = parseInt($($data).attr('id'));
                // for each collection at this level, create a child
                if ($($data).is ("Folder")) {
                    //HyperCities.debug(_id + "Folder found");
                    //HyperCities.debug ($data);
                    //var id = parseInt($($data).attr('id'));
                    _parseFolder($parentNode, $data);
                    //var self = this;
                    //var newNode = _parseFolder($node, self);
                    //var newNode = _createFolder (id, $("name:first", $data).text());
                    /*HyperCities.debug ($("name:first", $data).text());
                    $parentNode.find(">li:last")
					.removeClass(CLASSES.last)
					.removeClass(CLASSES.lastCollapsable)
					.removeClass(CLASSES.lastExpandable)
					.find(">.hitarea")
					.removeClass(CLASSES.lastCollapsableHitarea)
					.removeClass(CLASSES.lastExpandableHitarea).end().end()
					.append(newNode);*/
                    HyperCities.debug (_id + "Parsing search result " + id);
                    _setFolderStatus(id, true, false);
                    //_setCheckBoxStatus(id, true);
                    //_parseCollection($data);
                    $(this).children("Folder,NetworkLink,Placemark").each( function () {
                        _parseChildren (this, newNode);
                        //_updateFolder(newNode, this);
                    })
                    //_updated.push(id);
                    //HyperCities.debug($data);
                    // parse it at this node
                    //var self = this;
                    //var newNode = _parseFolder($node, $data);
                    //_updateFolder(newNode, $data);
                    $($data).children("Folder,NetworkLink").each(function () {
                        //_updateFolder(newNode, this);
                        //_parseCollection(this);
                        //_parseChildren (this, newNode);
                    });
                    /*$($data).children("Placemark").each( function () {
                        _parseChildren (this, newNode);
                    });*/
                } else if ($($data).is("NetworkLink")) {
                    
                    _setFolderStatus(id, true);
                    _setCheckBoxStatus(id, true);
                    HyperCities.debug(_id + "NetworkLink found");
                    //_parseCollection($data);
                } else if ($($data).is("Placemark")) {
                    HyperCities.util.debug (_id + "Placemark found");
                } else {
                    HyperCities.debug (_id + " Invalid item type.");
                }
            };
            // Append folders to collection tree
            //_parseCollectionList($data);
            $("Document > Folder", $data).each (function () {
                var self = this;
                var newNode = _parseFolder(treeRoot, self);
                var id = parseInt($(this).attr('id'));
                HyperCities.debug (_id + "Parsing search result " + id);
                //_opened.push(id);
                _setFolderStatus(id, true, false);
                //_setCheckBoxStatus(id, true);
                //_parseCollection($data);
                $(this).children("Folder,NetworkLink,Placemark").each( function () {
                    _parseChildren (this, newNode);
                    //_updateFolder(newNode, this);
                })
                //__parseChildren (this, newNode);
            })
            /*$("Document > Folder > Folder,NetworkLink,Placemark ", $data).children().each( function() {
                var self = this;
                var newNode = _parseFolder(treeRoot, self);
                var id = parseInt($($data).attr('id'));
                //_opened.push(id);
                _setFolderStatus(id, true);
                //_setCheckBoxStatus(id, true);
                //_parseCollection($data);
                $(this).children("Folder,NetworkLink,Placemark").each( function () {
                    _parseChildren (this, newNode);
                    //_updateFolder(newNode, this);
                })
                //__parseChildren (this, newNode);
            });*/
            // Get all immediate children of the document root
            // Parse them and put them at the first level
            // On each of their children, call the same function, passing it the parent node
            
        }
   
    }; // end of public methods
}(); // end of Object

// end of file
