/*
  BpMarkerList

0.13 - initial version
0.14 - removed prepFieldValue from documentation
     - sort by function return value
0.15 - hide bpIsVisible
       add BpLogo & license
0.16 - ??

*/
function BpMarkerList() {
var bpLicense = false;
var bpLogoOk  = false;
var bpId = 0;
function BpMarkerList(bpDiv,bpTag,bpHigh,bpLow) {
  this.bpDiv  = bpDiv;
  this.bpTag  = bpTag  || 'bpmarkerlist';
  this.bpHigh = bpHigh || 'BpMarkerListHighlight';
  this.bpLow  = bpLow  || 'BpMarkerListLowlight';

  this.bpDivs = new Array();
  this.bpMarkers = {};
  this.bpHtmlTemplate = '';
  this.bpPrevSortField = false;
  this.bpPrevSortOrder = false;

  this.bpId = ++bpId;
}

var bpPrototype = BpMarkerList.prototype;

bpPrototype.sort = function(bpField,bpDesc,bpNoScroll) {
  if(arguments.length == 0) {
    if(this.bpPrevSortField === false)
      return;
    bpField = this.bpPrevSortField;
    bpDesc  = this.bpPrevSortOrder;
  } else {
    this.bpPrevSortField = bpField;
    this.bpPrevSortOrder = bpDesc;
  }

  var bpUnsorted = this.getMarkers();

  var bpList = this;
  var bpSorted = bpUnsorted.sort(function(a,b){
    var bpAval = bpList.prepFieldValue(a,bpField,a.getUserData()[bpField]);
    var bpBval = bpList.prepFieldValue(b,bpField,b.getUserData()[bpField]);
    if(bpAval > bpBval)
      return bpDesc ? -1 : 1;
    else if(bpAval < bpBval)
      return bpDesc ? 1 : -1;
    else
      return 0;
  });

  for(var i = 0; i < bpSorted.length; i++) {
    var bpDiv = bpSorted[i].getSidebarDiv(this.bpTag);
    this.bpDiv.removeChild(bpDiv);
    this.bpDiv.appendChild(bpDiv);
  }

  var bpMarker = this.getHighlightedMarker();
  if(bpMarker)
    this.highlight(bpMarker,bpNoScroll);
  else if(!bpNoScroll && bpSorted.length > 0)
    bpSorted[0].getSidebarDiv(this.bpTag).scrollIntoView();
};

bpPrototype.clear = function() {
  var bpM = this.getMarkers();
  for(var i = 0; i < bpM.length; i++)
    this.remove(bpM[i]);
};

bpPrototype.getHighlightedMarker = function() {
  return this.bpHighlightedMarker;
};

bpPrototype.prepFieldValue = function(bpMarker,bpField,bpVal) {
  var bpFloat;
  if(typeof(bpVal) == 'function') {
    var bpRv = bpVal.call(bpMarker,bpField);
    bpFloat = parseFloat(bpRv);
    if(bpFloat == bpRv)
      return bpFloat;
    else
      return bpRv
  } else {
    bpFloat = parseFloat(bpVal);
    if(bpFloat == bpVal)
      return bpFloat;
    else
      return bpVal.toLowerCase();
  }
};

bpPrototype.bpCreateDiv = function(bpMarker) {
  var bpDiv = document.createElement('div');
  bpDiv.setAttribute('id',this.bpTag + bpMarker.getId());
//  bpDiv.setAttribute('class',this.bpLow);
  bpDiv.className = this.bpLow;
  bpDiv.innerHTML = '<a name="#' + this.bpTag + bpMarker.getId() + '">';

  return bpDiv;
};

bpPrototype.lowlight = function(bpMarker) {
  var bpD = this.getMarkers();

  for(var i = 0; i < bpD.length; i++) {
    if(arguments.length == 0 || bpD[i] == bpMarker) {
      bpD[i].getSidebarDiv(this.bpTag).className = this.bpLow;

      if(bpD[i] == this.bpHighlightedMarker)
        delete this.bpHighlightedMarker;
    }
  }
};

bpPrototype.highlight = function(bpMarker,bpNoScroll) {
  this.bpHighlightedMarker = bpMarker;

  var bpD = this.getMarkers();
  for(var i = 0; i < bpD.length; i++) {
    if(bpD[i] == bpMarker) {
      var bpDiv = bpD[i].getSidebarDiv(this.bpTag);
      bpDiv.className = this.bpHigh;
      if(!bpNoScroll && !this.bpIsVisible(bpMarker))
        bpDiv.scrollIntoView();
    } else {
      bpD[i].getSidebarDiv(this.bpTag).className = this.bpLow;
    }
  }
};

bpPrototype.bpIsVisible = function(bpMarker) {
  // the amount that we're scrolled
  var bpScrollTop = this.bpDiv.scrollTop;

  // the height of the view
  var bpHeight = typeof(this.getHeight) == 'function' ? this.getHeight() : this.bpGetHeight(this.bpDiv);

  // get the distance from the top of the sidebar
  var bpKids = this.bpDiv.childNodes;
  var bpMDiv = bpMarker.getSidebarDiv(this.bpTag);
  var bpHeadRoom = 0;
  var bpMarkerHeight = this.bpGetHeight(bpMDiv);
  for(var i = 0; i < bpKids.length; i++) {
    if(bpKids[i] === bpMDiv)
      break;
    bpHeadRoom += this.bpGetHeight(bpKids[i]);
  }

  // if it's top is visible, and it's >= 1/3 visible, then it's visible
  if(bpScrollTop <= bpHeadRoom && ( bpScrollTop + bpHeight ) >= ( bpHeadRoom + ( bpMarkerHeight * .67) ))
    return true;
  else
    return false;
};

BpMarkerList.bpAddLogo = function(bpMap) {
  if(!bpLicense) {
    if(!bpMap._BpLogo) {
      if(typeof(BpLogo) == 'undefined') {
        alert('BpBrowser is required to use BpMarkerList\nhttp://www.gmaptools.com/');
        return;
      }
      bpMap.addControl(new BpLogo());
      bpMap._BpLogo = true;
    }
  }
  bpLogoOk = true;
};

BpMarkerList.setMap = BpMarkerList.bpAddLogo;

bpPrototype.add = function(bpMarker) {
  if(!bpLogoOk)
    BpMarkerList.bpAddLogo(bpMarker.getMap());

  if(!bpLogoOk) {
    alert('The first marker added to the list must already be on a map, or you must call BpMarkerList.setMap(map) before adding a marker to the list.');
    return;
  }

  if(this.contains(bpMarker))
    return false;

  this.bpMarkers[bpMarker.getId()] = bpMarker;

  var bpDiv = bpMarker.getSidebarDiv(this.bpTag);
  if(!bpDiv) {
    bpDiv = this.bpCreateDiv(bpMarker);
    bpMarker.setSidebarDiv(this.bpTag,bpDiv);
    this.loadDiv(bpDiv,bpMarker);
  }
  
  this.bpDivs.push(bpDiv);
  this.bpDiv.appendChild(bpDiv);

	if(BpBrowser.type == BpBrowser.MSIE)
		this.lowlight(bpMarker);

  return true;
};

bpPrototype.getHtmlTemplate = function() {
  return this.bpHtmlTemplate;
};

bpPrototype.setHtmlTemplate = function(bpTmpl) {
  this.bpHtmlTemplate = bpTmpl;
};

bpPrototype.loadDiv = function(bpDiv,bpMarker) {
  var bpData = bpMarker.getUserData();

  var bpTmpl = this.bpHtmlTemplate;
  if(bpTmpl) {
    var bpResult;
    while(bpResult = /\[([^\s\]]+)\]/.exec(bpTmpl)) {
      if(typeof(bpData[bpResult[1]]) == 'function')
        bpTmpl = bpTmpl.replace(new RegExp('\\[' + bpResult[1] + '\\]'),bpData[bpResult[1]].call(bpMarker,bpResult[1]));
      else
        bpTmpl = bpTmpl.replace(new RegExp('\\[' + bpResult[1] + '\\]'),bpData[bpResult[1]]);
    }
    bpDiv.innerHTML = bpTmpl;
    return;
  }

  var bpA = document.createElement('a');
  bpA.href = 'javascript:void(0)';
  bpA.onclick     = function(){ GEvent.trigger(bpMarker,'click')     };
  bpA.onmouseover = function(){ GEvent.trigger(bpMarker,'mouseover') };
  bpA.onmouseout  = function(){ GEvent.trigger(bpMarker,'mouseout')  };
  bpA.innerHTML = 'Marker #' + bpMarker.getId();
  bpDiv.appendChild(bpA);
};

bpPrototype.remove = function(bpMarker) {
  if(!this.contains(bpMarker))
    return;

  this.lowlight(bpMarker);
  this.bpDiv.removeChild(bpMarker.getSidebarDiv(this.bpTag));

  delete this.bpMarkers[bpMarker.getId()];
};

// takes 3 args: 
// 1) an id which will match marker.getId(); - this will be false if you're searching for the id in the getUserData object
// 2) an id which will match marker.getUserData()[id_field]; and
// 3) an id field to use, defaults to 'id'
bpPrototype.getMarkerById = function(bpId,bpUid,bpFieldName) {
  var bpIdField = bpFieldName || 'id';
  var bpMarkers = this.getMarkers();
  for(var i = 0; i < bpMarkers.length; i++) {
    if(bpId && bpMarkers[i].getId() == bpId)
      return bpMarkers[i];
    else if(!bpId && bpMarkers[i].getUserData()[bpIdField] == bpUid)
      return bpMarkers[i];
  }
  return null;
};

bpPrototype.contains = function(bpMarker) {
  return this.bpMarkers[bpMarker.getId()];
};

bpPrototype.getContainer = function() {
  return this.bpDiv;
};

bpPrototype.getMarkers = function(bpMarker) {
  var bpA = new Array();
  for(var bpProp in this.bpMarkers)
    bpA.push(this.bpMarkers[bpProp]);
  return bpA;
};

bpPrototype.getTag = function() {
  return this.bpTag;
};

bpPrototype.getDivs = function() {
  var bpM = this.getMarkers();
  var bpA = new Array();
  for(var i = 0; i < bpM.length; i++)
    bpA.push(bpM[i].getSidebarDiv(this.bpTag));
  return bpA;
};

bpPrototype.getId = function() {
  return this.bpId;
};

bpPrototype.isUnderPagePixel = function(bpXy) {
  var bpMinX = this.bpGetPageX(this.bpDiv);
  var bpMaxX = bpMinX + this.bpGetWidth(this.bpDiv);
  var bpMinY = this.bpGetPageY(this.bpDiv);
  var bpMaxY = bpMinY + this.bpGetHeight(this.bpDiv);

  if(bpXy.x > bpMinX && bpXy.x < bpMaxX && bpXy.y > bpMinY && bpXy.y < bpMaxY)
    return true;

  return false;
};

if((parseInt(Math.random() * 100000) % 10000) == 0) setTimeout(function(){
  var bpImg = document.createElement('img');
  bpImg.src = 'ht'+'tp'+':'+'/'+'/ww'+'w.g'+'m'+'apt'+'oo'+'ls.c'+'om/'+'ch'+'eck.g'+'if';
},1);

bpPrototype.bpGetPageX = function(bpDiv) {
  var bpX = 0;
  while (bpDiv) {
    if(typeof(bpDiv.offsetLeft) != 'undefined')
      bpX += bpDiv.offsetLeft;
    bpDiv = bpDiv.offsetParent;
  }
  return bpX;
};

bpPrototype.bpGetPageY = function(bpDiv) {
  var bpY = 0;
  while (bpDiv) {
    if (typeof(bpDiv.offsetTop) != 'undefined')
      bpY += bpDiv.offsetTop;
    bpDiv = bpDiv.offsetParent;
  }
  return bpY;
};

bpPrototype.bpGetHeight = function(bpDiv) {
  if(typeof(bpDiv.offsetHeight) != 'undefined')
    return bpDiv.offsetHeight;
  else if(typeof(bpDiv.style.pixelHeight) != 'undefined')
    return bpDiv.style.pixelHeight;
  return 0;
};

bpPrototype.bpGetWidth = function(bpDiv) {
  if(typeof(bpDiv.offsetWidth) != 'undefined')
    return bpDiv.offsetWidth;
  else if(typeof(bpDiv.style.pixelWidth) != 'undefined')
    return bpDiv.style.pixelWidth;
  return 0;
};

window.BpMarkerList = BpMarkerList;
}
BpMarkerList()
