// initialise urchin

_uacct = "UA-387811-1";
urchinTracker();

// browser detection

var BrowserDetect = {
  init: function () {
    this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
    this.version = this.searchVersion(navigator.userAgent)
      || this.searchVersion(navigator.appVersion)
      || "an unknown version";
    this.OS = this.searchString(this.dataOS) || "an unknown OS";
  },
  searchString: function (data) {
    for (var i=0;i<data.length;i++) {
      var dataString = data[i].string;
      var dataProp = data[i].prop;
      this.versionSearchString = data[i].versionSearch || data[i].identity;
      if (dataString) {
        if (dataString.indexOf(data[i].subString) != -1)
          return data[i].identity;
      }
      else if (dataProp)
        return data[i].identity;
    }
  },
  searchVersion: function (dataString) {
    var index = dataString.indexOf(this.versionSearchString);
    if (index == -1) return;
    return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
  },
  dataBrowser: [
    { 
      string: navigator.userAgent,
      subString: "OmniWeb",
      versionSearch: "OmniWeb/",
      identity: "OmniWeb"
    },
    {
      string: navigator.vendor,
      subString: "Apple",
      identity: "Safari"
    },
    {
      prop: window.opera,
      identity: "Opera"
    },
    {
      string: navigator.vendor,
      subString: "iCab",
      identity: "iCab"
    },
    {
      string: navigator.vendor,
      subString: "KDE",
      identity: "Konqueror"
    },
    {
      string: navigator.userAgent,
      subString: "Firefox",
      identity: "Firefox"
    },
    {
      string: navigator.vendor,
      subString: "Camino",
      identity: "Camino"
    },
    {   // for newer Netscapes (6+)
      string: navigator.userAgent,
      subString: "Netscape",
      identity: "Netscape"
    },
    {
      string: navigator.userAgent,
      subString: "MSIE",
      identity: "Explorer",
      versionSearch: "MSIE"
    },
    {
      string: navigator.userAgent,
      subString: "Gecko",
      identity: "Mozilla",
      versionSearch: "rv"
    },
    {     // for older Netscapes (4-)
      string: navigator.userAgent,
      subString: "Mozilla",
      identity: "Netscape",
      versionSearch: "Mozilla"
    }
  ],
  dataOS : [
    {
      string: navigator.platform,
      subString: "Win",
      identity: "Windows"
    },
    {
      string: navigator.platform,
      subString: "Mac",
      identity: "Mac"
    },
    {
      string: navigator.platform,
      subString: "Linux",
      identity: "Linux"
    }
  ]

};
BrowserDetect.init();

//search field

if (BrowserDetect.browser == 'Safari') {
  addLoadEvent(function() {
    var search = document.getElementById('search');
    search.type = 'search';
    search.style.width = '150px';
  });
}

// release notes functions

function applyExpansion() {
  var notes = getElementsByClassName(document,'dl','release-notes');
  var headings = getElementsByTagName(notes[0],'dt');
  for (var i = 0;i < headings.length;i++) {
    headings[i].innerHTML += ' <a class="expander" href="javascript:expandElement(' + i + ')">+</a>';
  }
  var items = getElementsByTagName(notes[0],'ul');
  for (var i = 0;i < items.length;i++) {
    items[i].style.display = 'none';
  }
  expandElement(0);
}

function expandElement(index) {
  var notes = getElementsByClassName(document,'dl','release-notes');
  var expanders = getElementsByClassName(document,'a','expander');
  if (expanders[index].innerHTML == '+') expanders[index].innerHTML = '-';
  else expanders[index].innerHTML = '+';
  var items = getElementsByTagName(notes[0],'ul');
  if (items[index].style.display == 'none') items[index].style.display = '';
  else items[index].style.display = 'none';
}

// support page functions

var versions = new Array();

function showVersions(product) {
  var versionList = document.getElementById('versions');
  var versions = getElementsByTagName(versionList,'option');
  
  if (versions.length == 0) {
    for (var i = 0;i < versions.length;i++) versions[versions.length] = versions[i];
  }
  
  for (var i = 0;i < versions.length;i++) {
    if (elementHasClass(versions[i], product)) versions[i].style.display = '';
    else versions[i].style.display = 'none';
  }
}

// weblog form

function imageSelect(select) {
  if (select.options[select.selectedIndex].innerHTML == 'Uploaded image') {
    document.getElementById('preview-image').src = 'data:image/png;base64,' + document.getElementById('image-data').value;
    document.getElementById('image-alt').value = '';
  } else {
    document.getElementById('preview-image').src = 'images/' + select.value;
    document.getElementById('image-alt').value = select.options[select.selectedIndex].innerHTML;
  }
}

// screenshots

function getTop(p) {
  if(!document.getElementById) return;

  var value = p.style["top"];

  if(!value) {
    if(document.defaultView) {
      value = document.defaultView.getComputedStyle(p,"").getPropertyValue("top");
    } else if(p.currentStyle) {
      value = p.currentStyle["top"];
    }
  }

  return parseInt(value);
}

function getLeft(p) {
  if(!document.getElementById) return;

  var value = p.style["left"];

  if(!value) {
    if(document.defaultView) {
      value = document.defaultView.getComputedStyle(p,"").getPropertyValue("left");
    } else if(p.currentStyle) {
      value = p.currentStyle["left"];
    }
  }

  return parseInt(value);
}

function mouseX(e) {
  if (e.pageX) return e.pageX;
  if (e.clientX) return e.clientX + document.documentElement.scrollLeft;
  return -1;
}

function mouseY(e) {
  if (e.pageY) return e.pageY;
  if (e.clientY) return e.clientY + document.documentElement.scrollTop;
  return -1;
}

function initScreenshots(f) {
  addLoadEvent(function() {
  
    var p = createElement('div');
    insertElement(document.getElementById('main'),p);
    
    p.id = 'inspector';
    var pi = createElement('div');
    insertElement(p,pi);
    
    var i = document.getElementById('screenshot');
    pi.style.backgroundImage = 'url(' + i.src + ')';
    
    addEvent(document.body, 'mousemove', function(e) {
  
      if (!e) var e = window.event;
      
      var i = document.getElementById('screenshot');
      var p = document.getElementById('inspector');
  
      var x = mouseX(e);
      var y = mouseY(e);
  
      var offset = getElementPosition(i);
  
      var minx = offset.left + 100/f;
      var maxx = minx + 610 - 200/f;
      var miny = offset.top + 100/f;
      var maxy = miny + 458 - 200/f;
      
      if (x < offset.left || x > offset.left+610 || y < offset.top || y > offset.top+458) {
      
        p.style.display = 'none';
        
      } else {
      
        p.style.display = 'block';
        
        if (x < minx) x = minx;
        if (x > maxx) x = maxx;
        if (y < miny) y = miny;
        if (y > maxy) y = maxy;
        
        p.style.left = x-120+'px';
        p.style.top = y-120+'px';
        
        p.firstChild.style.backgroundPosition = - Math.ceil((x-offset.left)*f - 100) + 'px '
        + - Math.floor((y-offset.top)*f - 100) + 'px';
        
      }
  
    });
  
  });
}

// dates

Date.prototype.getDayOfYear = function() {
  var d = new Date();
  d.setFullYear(this.getFullYear());
  d.setMonth(0);
  d.setDate(0);
  d.setHours(0);
  d.setMinutes(0);
  d.setSeconds(0);
  return Math.ceil((this.getTime() - d.getTime()) / (3600000*24));
}

Date.prototype.getCalendarWeek = function() {
  var d = new Date();
  d.setTime(this.getTime());
  var week = 0;
  while (d.getFullYear() == this.getFullYear()) {
    d.setDate(d.getDate() - 7);
    week ++;
  }  return week;
}

function getWeekday(day) {
  switch (day) {  case 0: return 'Sunday';
  case 1: return 'Monday';  case 2: return 'Tuesday';  case 3: return 'Wednesday';  case 4: return 'Thursday';  case 5: return 'Friday';  case 6: return 'Saturday';
  }
}

function getMonth(month) {
  switch (month) {  case 0: return 'January';  case 1: return 'February';  case 2: return 'March';  case 3: return 'April';  case 4: return 'May';  case 5: return 'June';  case 6: return 'July';  case 7: return 'August';  case 8: return 'September';  case 9: return 'October';  case 10: return 'November';  case 11: return 'December';  }
}

function to12Hour(hours) {
  hours = hours % 12;  if (hours == 0) hours = 12;  return hours;
}

// general utility functions

String.prototype.toTitleCase = function() {
  //title case function for string
  return this.replace(/\b([a-z])/g,function($0) {
    return $0.toUpperCase();
  });
}

function addEvent(element, event, func) {
  //add an event to the specified element, preserving any existing events that are attached
  if (!element) return;
  if (element.addEventListener) {
    element.addEventListener(event, func, false);
    return true;  
  } else {
    var oldFn = element['on' + event];
    var fn;
    if (oldFn) {
      fn = function() {
        return oldFn();
        return func();
      }
    } else {
      fn = func;
    }
    if (element.attachEvent) return element.attachEvent('on' + event, fn);
    else element['on' + event] = fn;
  }
}

function addLoadEvent(func) {
  //add a page load event
  addEvent(window, 'load', func);
}

function elementHasClass(element, className) {
  //return true if the element has the given class name
  className = className.replace(/\-/g, '\\-');
  var re = new RegExp('(^|\\s)' + className + '(\\s|$)');
  return re.test(element.className);
}

function getElementsByTagName(container, tagName) {
  //get all html nodes of a given type within a given container
  if (container) return container.getElementsByTagName(tagName);
  else return new Array();
}

function getElementsByClassName(container, tagName, className) {
  //get all html nodes of a given type and class within a given container
  var elements = getElementsByTagName(container, tagName);
  var result = new Array();
  for(var i=0;i < elements.length;i++) {
    var e = elements[i];
    if (elementHasClass(e,className)) result.push(e);
  }
  return result;   
}

function createElement(tagName) {  //create an html node of the specified type  return document.createElement(tagName);}function createTextNode(text) {  //create an html text node  return document.createTextNode(text);}function replaceElement(element,replacement) {  //replace an html node with the specified alternative  if (element) element.parentNode.replaceChild(replacement,element);}function insertElement(parent,child) {  //insert an html node within the specified parent, after the last child  if (parent) parent.appendChild(child);}function removeElement(element) {  //remove the specified node from the dom tree  if (element && element.parentNode) element.parentNode.removeChild(element);}function insertElementBefore(element,before) {  //insert an html node before the specified element  if (before && before.parentNode) before.parentNode.insertBefore(element,before);}function insertElementAfter(element,after) {  //insert an html node after the specified element  if (after && after.parentNode) {    if (after.nextSibling) insertElementBefore(element,after.nextSibling);    else insertElement(after.parentNode,element);  }}

function getElementPosition(element) {
  //return an element absolute position
  if(!element) return;
  var pos = new Object;
  //get width and height
  pos.width = element.offsetWidth;
  pos.height = element.offsetHeight;
  //get left and top
  pos.left = 0;
  pos.top = 0;
  //stop at body
  while(element != null && element.nodeName != 'BODY'){
    pos.left += element.offsetLeft;
    pos.top += element.offsetTop;
    element = element.offsetParent;
  }   
  //right and bottom
  pos.right = (pos.left + pos.width);
  pos.bottom = (pos.top + pos.height);
  return pos;
}

function getQueryParams(query) {
  //decode query parameters into an associative array
  var params = new Object();
  if (!query) return params;
  var start = query.indexOf('?');
  if (start > -1) query = query.substr(start + 1);
  var paramArray = query.split("&");
  for (var i in paramArray) {
    var param = paramArray[i];
    var splitPos = param.indexOf("=");
    var name = unescape(param.substring(0,splitPos));
    var value = unescape(param.substring(splitPos+1));
    params[name] = value;
  }
  return params;
}

function setCookie(name, value, expires, path, domain, secure) {
  //set a cookie
  document.cookie = name + '=' + escape(value) +
    ((typeof(expires) != 'undefined' && expires) ? '; expires=' + expires.toGMTString() : '') +
    ((typeof(path) != 'undefined' && path) ? '; path=' + path : '; path=/') +
    ((typeof(domain) != 'undefined' && domain) ? '; domain=' + domain : '') +
    ((typeof(secure) != 'undefined' && secure) ? '; secure' : '');
}

function deleteCookie(name) {
  //delete a cookie
  document.cookie = name + '=; expires=0; path=/';
}

function getCookie(name) {
  //get a cookie
  var dc = document.cookie;
  var prefix = name + '=';
  var begin = dc.indexOf('; ' + prefix);
  if (begin == -1) {
    begin = dc.indexOf(prefix);
    if (begin != 0) return null;
  } else begin += 2;
  var end = document.cookie.indexOf(';', begin);
  if (end == -1) end = dc.length;
  return unescape(dc.substring(begin + prefix.length, end));
}