/* PicLens Lite JavaScript: version 1.2.0
 * Copyright (c) 2008 Cooliris, Inc.
 * All Rights Reserved.
 *
 * The JavaScript portion of PicLens Lite is licensed under BSD.
 * For details, see http://lite.piclens.com/bsdlicense
 * This launcher includes and interacts with SWFObject (MIT), BrowserDetect (BSD Compatible), and Lytebox (CC Attribution 3.0).
 *
 * There are two versions of this JS:
 * http://lite.piclens.com/current/piclens.js     contains the full file with comments  (~42KB)
 * http://lite.piclens.com/current/piclens_optimized.js contains a light version for deployment (~25KB)
 */
var PicLensLite = {
  // PUBLIC API

  // PicLens Lite can be deployed in one of two ways:
  // 1) include http://lite.piclens.com/current/piclens.js in the <head> of your webpage
  // 2) download the zip file and deploy it on your own website (unzip it anywhere, and point to the JS file in the <head> of your page)
  //
  // For example: the directory layout looks like:
  //   lite.piclens.com/current/ contains the SWF, JS, and image files
  //           /lytebox/ contains slideshow support for browsers w/o Flash
  //
  // Pointing to the JS will automatically configure PicLens Lite relative to that URL...
  // Alternatively, you can customize the URLs with PicLensLite.setLiteURLs

  // 1) Call PicLensLite.start() to launch the default feed (specified in the head)
  // 2) Call PicLensLite.start({feedUrl:'http://myWebsite.com/myFeed.rss', ...}) to launch a specific feed
  //  Option 2 supports the following named arguments:
  //    feedUrl  : String  // is the URL to the specific Media RSS feed you want to launch
  //    feedData : String  // is the Media RSS feed itself (do not use feedUrl if you want to programmatically generate & pass in the feed text)
  //    guid   : String  // starts from the item in the feed that is tagged w/ this unique id
  //    maxScale : Number  // normally, images fill the stage; 0 -> never scale up; any other positive number S --> scale up to S times the original size of the photo (but never bigger than the stage)
  //    loadFeedInFlash : Boolean // if true, we ask Flash to load the feed, instead of AJAX (expert option)
  //    loop   : Boolean // if true, we turn looping on by default
  //    paused   : Boolean // if true, we start the slideshow in paused mode
  // To enable smoothing for images. a crossdomain.xml file is required at the root of your image server.
  // Lite detects this crossdomain.xml and applies smoothing automatically.
  start : function (namedArgs) {
    this.determineBrowserParams();
    clearTimeout(this.REMOVE_TIMER_ID);
    clearTimeout(this.AUTO_CLOSE_TIMER_ID);
    this.ARGS = {}; // clear out previous args

    // handle named arguments
    if (typeof namedArgs !== "undefined" && namedArgs !== null) {
      this.ARGS = namedArgs;

      //////////////////////////////////////////////////////////////////////
      // if feedUrl is specified, it launches immediately
      if (namedArgs.feedUrl) {
        this.THE_FEED_URL = namedArgs.feedUrl;
        if (this.checkForPluginAndLaunchIfPossible(namedArgs.feedUrl)) {
          return;
        }
        if (namedArgs.loadFeedInFlash) {
          // read up on flash crossdomain.xml if you choose this option
          // Flash can only load feeds from servers hosting a crossdomain.xml
          // pass the URL as a FlashVar, and load the contents via a GET request
          this.showFlashUI("");
        } else {
          // load the contents of the URL via AJAX, and launch the Flash UI afterward....
          this.loadViaXHR(namedArgs.feedUrl);
        }
      }
      // pass in the feed XML directly through Javascript
      // use feedUrl OR feedData, but not both!
      if (typeof namedArgs.feedData !== 'undefined') {
        this.showFlashUI(namedArgs.feedData);
      }
    } else {
      // find the feed from the header, since none was specified
      // build list of XML feeds
      var feeds = this.indexFeeds();
      if (feeds.length !== 0) { // view the first feed, if available
        var feed = feeds[0];
        this.THE_FEED_URL = feed.url;
        if (this.checkForPluginAndLaunchIfPossible(feed.url)) {
          return;
        }
        this.loadViaXHR(feed.url);
      }
    }
  },
  // check if the slideshow is currently running
  isRunning : function () {
    return this.LITE_IS_RUNNING;
  },
  // check if the user has the PicLens browser plug-in installed
  hasClient : function () {
    return this.hasPicLensClient();
  },
  // OPTIONAL: provide callbacks to be notified in certain situations. Call this BEFORE PicLensLite.start(...)
  //  onNoPlugins():Boolean
  //    is called when the user invokes Lite but does not have PicLens / Flash installed
  //  onExit(itemUID):void
  //    is called when the user exits from Lite
  //    we provide the item's GUID if it exists, and the item's content URL otherwise
  //    itemUID is undefined if the user exited before Lite launched, or if the user did not have Flash
  setCallbacks : function (args) {
    if (args.onNoPlugins) {
      this.ON_NO_PLUGINS = args.onNoPlugins;
    }
    if (args.onExit) {
      this.ON_EXIT = args.onExit;
    }
  },
  // OPTIONAL: customize the location of resources. Call this BEFORE PicLensLite.start(...)
  // Normally, we locate the PicLensLite files relative to the JS file
  // To use this function, pass in an object with the following named arguments:
  // args = {
  //    lite  : other paths can be determined from this (make sure it ends in a slash)
  //    swf   : the URL of the SWF file         1
  //    button  : image allowing users to download piclens  1
  //    lbox  : where to find lytebox           1
  //    lboxcss : the CSS file                2
  //    lboxjs  : the JS file               2
  // }
  // 1: Can be determined from args.lite
  // 2: Can be determined from args.lbox or args.lite
  setLiteURLs : function (args) {
    if (!this.LITE_URL) {
      if (args.swf) {
        this.LITE_URL = args.swf;
      } else if (args.lite) {
        this.LITE_URL = args.lite + "PicLensLite.swf";
      } // if both lite & swf aren't set, it won't work
    }
    if (!this.BUTTON_URL) {
      if (args.button) {
        this.BUTTON_URL = args.button;
      } else if (args.lite) {
        this.BUTTON_URL = args.lite + "NoFlash.jpg";
      }
    }

    var lboxUrl = "";
    if (args.lbox) {
      lboxUrl = args.lbox;
    } else if (args.lite) {
      lboxUrl = args.lite + "../lytebox/";
    }

    if (!this.LBOX_CSS_URL) {
      if (args.lboxcss) {
        this.LBOX_CSS_URL = args.lboxcss;
      } else if (lboxUrl != "") {
        this.LBOX_CSS_URL = lboxUrl + "lytebox.css";
      }
    }

    if (!this.LBOX_JS_URL) {
      if (args.lboxjs) {
        this.LBOX_JS_URL = args.lboxjs;
      } else if (lboxUrl != "") {
        this.LBOX_JS_URL = lboxUrl + "lytebox.js";
      }
    }
  },



  //////////////////////////////////////////////////////////////////////////////////////////////////////////
  // The PRIVATE API is below
  // DO NOT USE these functions or variables directly, as they WILL change in future releases
  // Please email us to request changes to the public API if necessary
  ARGS      : {},
  DEBUG_NOCLIENT  : false,  // if true, we will NEVER launch the PicLens Client (for testing Lite)
  DEBUG_NOFLASH : false,  // if true, we will assume the user does not have Flash (for testing Lite)
  HPAD    : 60,   // horizontal padding
  VPAD    : 20,   // vertical padding
  LITE_BG_DIV   : null,   // the grey/black background overlay
  LITE_FG_DIV   : null,   // the foreground div that contains the flash component
  LITE_URL    : null,   // the location of PicLensLite.SWF
  BUTTON_URL    : null,   // image to display if the user doesn't have flash
  LBOX_CSS_URL  : null,   // where to find lytebox css/js files
  LBOX_JS_URL   : null,
  LBOX_COUNT    : 0,    // try to start lytebox, but if it doesn't exist after a few tries, give up...
  SHOW_LBOX   : false,  // if true, skip flash altogether
  OS_WIN      : false,  // OS Detect
  OS_MAC      : false,  // sadly, sometimes we have to do something different depending on our Browser/OS/Configuration
  BROWSER_FFX   : false,  // Browser Detect
  BROWSER_SAF   : false,
  BROWSER_IE    : false,
  BROWSER_IE6   : false,
  THE_FEED    : "",     // the feed text
  THE_FEED_URL  : "",     // the feed url
  LITE_IS_RUNNING   : false,  // use isRunning()
  piclensIsRunning_ : false,  // maintain compatibility with the Wordpress Plugin for a few iterations...
  FLASH_ID_1    : "pllflash1",  // outer
  FLASH_ID_2    : "pllflash2",  // inner
  FLASH_VER   : null,     // the version of Flash we're running
  FLASH_URL   : "http://www.adobe.com/go/getflashplayer",
  PL_URL      : "http://download.piclens.com/partner/",   // downloads PL immediately
  LEARN_PL_URL  : "http://affiliate.piclens.com/partner/",  // landing page to read about / download PL
  FONT      : "font-family: Lucida Grande, Myriad Pro, Verdana, Helvetica, Arial, sans-serif;",
  KEY_HANDLERS  : "", // save the old key handlers, if any
  ON_NO_PLUGINS : null, // callback
  ON_EXIT     : null, // callback
  AUTO_CLOSE_TIMER_ID   : 0,  //
  REMOVE_TIMER_ID     : 0,  // the timer for removing the children...
  RESIZE_TIMER_IE6    : null, // every second, it auto resizes the UI
  RESIZE_HANDLER_EXISTS : false,// for safari, it adds a handler to detect user resize events
  CUSTOM_BUTTON     : null, // add an action to the UI

  // call this before starting lite. we currently support a single custom button
  // the button icon is a PNG, 32x32 or smaller
  // WARNING: In the near future, this will change to a REST API, where instead of a JavaScript callback,
  // we will perform a GET request of a provided URL, w/ the image GUID
  addCustomButton : function (buttonCallback, buttonLabel, buttonIcon) {
    this.CUSTOM_BUTTON = {callback: buttonCallback, labelText: buttonLabel, iconImage: buttonIcon};
  },
  addKeyHandlers : function () {
    var self = this;
    if (typeof document.onkeydown !== 'undefined') { // save & later restore key handlers...
      this.KEY_HANDLERS = document.onkeydown;
    }
    document.onkeydown = function (e) {
      var keycode;
      if (typeof e === "undefined" || e === null) { // ie
        keycode = window.event.keyCode;
      } else { // mozilla
        keycode = e.which;
      }
      var val=self.handleKeyPress(keycode);
      if (typeof e != "undefined" && e != null) {
        e.returnValue = val;
      }
      return val;
    };
  },
  addMouseHandlers : function () {
    if (window.addEventListener) {  // Firefox
      window.addEventListener("DOMMouseScroll", this.handleMouseWheel, false);
    }
    if (document.attachEvent) {   // IE/Opera
      document.attachEvent("onmousewheel", this.handleMouseWheel);
    }
    window.onmousewheel = document.onmousewheel = this.handleMouseWheel; // other browsers
  },
  // call this at the last possible moment (especially for Win/Firefox)
  appendElementsToDocument : function () {
    if (this.BROWSER_FFX && this.OS_MAC) {  // avoid redraw bug by not showing the background
      this.LITE_BG_DIV.style.display = "none";
    }
    document.body.appendChild(this.LITE_BG_DIV);
    document.body.appendChild(this.LITE_FG_DIV);
  },
  autoResize : function () { // for the IE6 auto resize
    if (!this.isRunning()) {
      // unregister the timer
      clearInterval(this.RESIZE_TIMER_IE6);
      return;
    }

    // resize the BG and FG divs
    var size = this.getPageSize();
    var bg = this.LITE_BG_DIV;
    if (bg) {
      bg.style.height = size.h + 'px';
      bg.style.width  = size.w + 'px';
    }
    if (this.LITE_FG_DIV) {
      var fgs = this.LITE_FG_DIV.style;
      this.resizeToPaddedBox(fgs);
      this.resizeToFitPaddedBox(fgs, size);
      this.resizeFlashToFitPaddedBox();
    }
  },
  clickCustomButton : function (buttonIndex, itemGUID) {
    this.CUSTOM_BUTTON.callback(itemGUID);
  },
  checkForPluginAndLaunchIfPossible : function (url) {
    // if we have the correct version of piclens, pass it onto the client and do not use LITE
    if (this.hasPicLensClient()) {
      window.piclens.launch(url,'','');
      return true; // launched!
    }
    return false;
  },
  createBackgroundOverlay : function () {
    // create a background that covers the page
    var bg = document.createElement('div');
    this.LITE_BG_DIV = bg;
    bg.id = "lite_bg_div";

    var bgs = bg.style;
    bgs.position = 'fixed';

    // stick to the sides when the window resizes
    bgs.width = bgs.height = "100%";

    if (this.BROWSER_IE6) {
      bgs.position = 'absolute';
      var page = this.getPageSize();
      bgs.height = page.h + 'px';
      bgs.width  = page.w + 'px';
    }

    bgs.left = bgs.right = bgs.top = bgs.bottom = '0px';
    bgs.backgroundColor = '#000';
    bgs.zIndex = 1000;
    bgs.opacity = '0.5';
    bgs.filter = 'alpha(opacity=50)';   // IE7

    var self = this;
    bg.onclick = function () {
      self.exitPicLensLite();
    };
  },
  createForegroundFlashComponent : function () { // configure the box
    var fg = document.createElement('div');
    this.LITE_FG_DIV = fg;
    fg.id = "lite_fg_div";

    var fgs = fg.style;
    fgs.backgroundColor = '#000';
    fgs.position = 'fixed';
    fgs.border = '2px solid #555';
    fgs.zIndex = 1001;     // above the bg

    this.resizeToPaddedBox(fgs);

    if (this.BROWSER_IE6) {
      fgs.position = 'absolute';
      this.resizeToFitPaddedBox(fgs);
    }
  },
  // this just removes the HTML elements
  // we call this from Flash (thus, we need to allow the function to return before removing the children)
  closeFlashUI : function (itemID) {
    var doc = document;

    // remove the keyboard & mouse handlers...
    doc.onkeydown = this.KEY_HANDLERS;
    window.onmousewheel = doc.onmousewheel = "";
    if (window.removeEventListener) {
      window.removeEventListener("DOMMouseScroll", this.handleMouseWheel, false);
    }
    if (doc.detachEvent) { // IE/Opera
      doc.detachEvent("onmousewheel", this.handleMouseWheel);
    }

    // hide the div now; remove them later
    this.LITE_BG_DIV.style.display = this.LITE_FG_DIV.style.display = 'none';
    this.REMOVE_TIMER_ID = setTimeout(function (){PicLensLite.removeChildren();}, 150); // 0.15s

    if (this.ON_EXIT !== null) {
      this.ON_EXIT(itemID); // call on exit
    }
    this.setRunningFlag(false);
  },
  // for handling cross-browser quirks...
  determineBrowserParams : function () {
    // BrowserDetect {.OS, .browser, .version} e.g., "Mac Firefox 2" and "Windows Explorer 7"
    var os = BrowserDetect.OS;
    var b = BrowserDetect.browser;
    this.OS_MAC = (os == "Mac");
    this.OS_WIN = (os == "Windows");
    this.BROWSER_FFX = (b == "Firefox");
    this.BROWSER_SAF = (b == "Safari");
    this.BROWSER_IE = (b == "Explorer");
    this.BROWSER_IE6 = (this.BROWSER_IE && BrowserDetect.version == "6");
    this.FLASH_VER = swfobject.getFlashPlayerVersion(); // what version of Flash is the browser running?
  },
  // we should tell Flash we are exiting when this is called...
  // this should only be called when the user clicks outside of the flash component
  // all other exits are handled through Flash
  exitPicLensLite : function () {
    var fl = this.getFlash();
    if (fl !== null && fl.fl_exitPicLensLite) { // binding exists
      // tell flash that we are quitting
      fl.fl_exitPicLensLite();
      // close after .5 seconds, if nothing happened
      // TODO: make sure this doesn't crash any browsers
      // TODO: Check the Return Value to Fire this Timer?
      this.AUTO_CLOSE_TIMER_ID = setTimeout(function (){ if (PicLensLite.isRunning()) { PicLensLite.closeFlashUI();}}, 500); // 0.5s
    } else {
      // if it's not running already, we just remove the DIVs (flash isn't defined)
      this.closeFlashUI();
    }
  },
  // a website should include the absolute URL of the piclens.js in its header
  // This function looks for the script tag and extracts the ROOT_URL
  // <script type="text/javascript" src="ROOT_URL/piclens.js"></script>
  // we assume the SWF and JPEG/PNG/GIF files are relative to this ROOT_URL...
  findScriptLocation : function () {
    var scriptTags = document.getElementsByTagName("script");
    for (var i = 0; i != scriptTags.length; ++i) {
      var script = scriptTags[i];
      var type = script.getAttribute("type");
      if (type == "text/javascript") {
        var src = script.getAttribute("src");
        if (src === null) {
          continue;
        }
        var index = src.indexOf("piclens.js");
        if (index != -1) {
          this.setLiteURLs({lite:src.substring(0,index)});
          return;
        } else {
          index = src.indexOf("piclens_optimized.js");
          if (index != -1) {
            this.setLiteURLs({lite:src.substring(0,index)});
            return;
          }
        }
      }
    }
  },
  getFeedURL : function () {    // for Flash to find the feed
    return encodeURIComponent(this.THE_FEED_URL);
  },
  // returns an object describing the page size of the browser window
  getPageSize : function () {
    var xScroll, yScroll, winW, winH;
    var doc = document;
    var body = doc.body;
    var html;
    if (window.innerHeight && window.scrollMaxY) {
      xScroll = doc.scrollWidth;
      yScroll = (this.isFrame ? parent.innerHeight : self.innerHeight) + (this.isFrame ? parent.scrollMaxY : self.scrollMaxY);
    } else if (body.scrollHeight > body.offsetHeight){
      xScroll = body.scrollWidth;
      yScroll = body.scrollHeight;
    } else {
      html = doc.getElementsByTagName("html").item(0);
      xScroll = html.offsetWidth;
      yScroll = html.offsetHeight;
      xScroll = (xScroll < body.offsetWidth) ? body.offsetWidth : xScroll;
      yScroll = (yScroll < body.offsetHeight) ? body.offsetHeight : yScroll;
    }
    var docElement = doc.documentElement;
    if (self.innerHeight) {
      winW = (this.isFrame) ? parent.innerWidth : self.innerWidth;
      winH = (this.isFrame) ? parent.innerHeight : self.innerHeight;
    } else if (docElement && docElement.clientHeight) {
      winW = docElement.clientWidth;
      winH = docElement.clientHeight;
    } else if (body) {
      html = doc.getElementsByTagName("html").item(0);
      winW = html.clientWidth;
      winH = html.clientHeight;
      winW = (winW == 0) ? body.clientWidth : winW;
      winH = (winH == 0) ? body.clientHeight : winH;
    }
    var pageHeight = (yScroll < winH) ? winH : yScroll;
    var pageWidth = (xScroll < winW) ? winW : xScroll;
    return {pw:pageWidth, ph:pageHeight, w:winW, h:winH}; // pw and ph are the larger pair. use w and h.
  },
  getElementsFromXMLFeed : function () {
    var xmlDoc;
    if (window.ActiveXObject) { // IE
        xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async=false;
        xmlDoc.loadXML(PicLensLite.THE_FEED);
    } else { // Mozilla, Firefox, Opera, etc.
      var parser = new DOMParser();
      xmlDoc = parser.parseFromString(PicLensLite.THE_FEED, "text/xml");
    }
    var elements = xmlDoc.getElementsByTagName('*');
    return elements;
  },
  getBasicSlideShowHTML : function () {
    if (!this.LBOX_JS_URL || !this.LBOX_CSS_URL) {
      return "";
    }

    // make sure the lytebox JS is included
    var head = document.getElementsByTagName('head').item(0);

    // add the script tag
    var script  = document.createElement('script');
    script.src  = this.LBOX_JS_URL;
    script.type = 'text/javascript';
    head.appendChild(script);

    // add the lytebox CSS too
    var link = document.createElement('link');
    link.rel = "stylesheet";
    link.href = this.LBOX_CSS_URL;
    link.type = "text/css";
    link.media = "screen";
    head.appendChild(link);

    // find all image URLs from the feed.
    var xmlElements = this.getElementsFromXMLFeed();

    var i;
    var hiddenURLs = "";
    for (i = 0; i < xmlElements.length; i++) {
      if (xmlElements[i].nodeName == "media:content") { // what about the namespace?
        var url = xmlElements[i].getAttribute("url");
        if (url.indexOf(".flv") == -1) {        // images only... avoid FLV files
          hiddenURLs += '<a id="lboxImage" href="' + url + '" rel="lytebox[lite]"></a> ';
        }
      }
    }
    // rel="lytebox[lite]"
    var basicSlideShow = "<div id='lightbox_images' align='center' style='display: none; padding-top:10px; color:#FFFFFF; font-size:.8em; " +this.FONT+ " color:#999999;'>";
    basicSlideShow +=  '( Alternatively, <a onclick="javascript:PicLensLite.invokeLytebox();return false;" href="#" style="color:#656588">click here for a basic slideshow</a>. )';
    basicSlideShow += hiddenURLs;
    basicSlideShow += "</div><br/>";

    return basicSlideShow;
  },
  generateAlternativeContent : function () {
    var altContentHTML = '<div id="altContent" style="text-align:center; margin: 0 0 0 0; padding: 0 0 0 0; background-color: #252525; min-width:860px;">';
    altContentHTML += '<div align="center" style="width: 100%; padding-top:60px; '+this.FONT+'">';

    var v = this.FLASH_VER;
    var flashMessage;
    if (v.major > 0) { // has some version of Flash
      flashMessage = "update your Flash Player from version "+ v.major + '.' + v.minor + '.' + v.release + " to version 9.0.28 or newer";
    } else {
      flashMessage = "install the most recent Flash Player";
    }

    var basicSlideShow = "";
    if (this.THE_FEED !== "") {   // do this if we've loaded the feed in AJAX
      basicSlideShow = this.getBasicSlideShowHTML();
    }

    var downloadPL = this.PL_URL;
    var learnPL = this.LEARN_PL_URL;
    var pid = this.ARGS.pid;
    if (pid) {
      downloadPL += pid + "/";
      learnPL += pid + "/";
    } else {
      var x = "000000000001/";
      downloadPL += x;
      learnPL += x;
    }

    if (this.SHOW_LBOX) {
      // don't show the image, because we will invoke lytebox immediately
    } else {
      var sp = "<span style='padding-left:25px; color:#C6C6C6; font-size:";
      altContentHTML +=
        "<div style='padding:10px;'>" +
          sp+"1.5em; font-weight: bold; " +this.FONT+ "'>You're clicks away from going full screen!</span><br/>" +
          sp+".9em; padding-bottom: 15px; " +this.FONT+ "'>You must get the <a href='"+downloadPL+"' style='color:#656588'>PicLens</a> browser plugin, or "+flashMessage+".</span>" +
        "</div>";
      if (!this.BUTTON_URL) {
        altContentHTML +=
        '<a href="' + downloadPL + '">Get PicLens Now!</a>';
      } else {
        var area = '<area shape="rect" coords=';
        altContentHTML +=
        '<img src="'+this.BUTTON_URL+'" alt="" border="0" usemap="#Map">' +
        '<map name="Map" id="Map">' +
          area+'"0,0,28,28" href="#" onclick="javascript:PicLensLite.closeFlashUI();" />' +
          area+'"31,34,316,293" href="' + downloadPL +'" />' +
          area+'"593,209,825,301" href="' + this.FLASH_URL +'" />' +
          area+'"328,136,448,158" href="' + learnPL +'" />' +
        '</map>';
      }
    }

    altContentHTML += '</div>';
    altContentHTML += basicSlideShow;
    altContentHTML += '<div align="center" style="color:#666666; font-size:11px; '+this.FONT+'">&copy; 2008 Cooliris, Inc. All trademarks are property of their respective holders.<br/><br/><br/></div>';
    altContentHTML += '</div>';
    return altContentHTML;
  },
  generateFlashVars : function () {
    var fv = '';
    var args = this.ARGS;
    if (typeof args.guid !== 'undefined') {
      fv += "&startItemGUID=" + args.guid;
    }
    if (args.loadFeedInFlash) {
      fv += "&feedURL=" + this.getFeedURL();  // may need crossdomain.xml to allow loading of feed
    }
    if (args.paused) {
      fv += "&paused=" + args.paused;
    }
    if (args.loop) {
      fv += "&loop=" + args.loop;
    }
    if (args.delay) { // seconds: from 1-10
      fv += "&delay=" + args.delay;
    }
    if (args.pid) {
      fv += "&pid=" + args.pid;
    }
    if (typeof args.maxScale != 'undefined') {  // allow 0
      fv += "&maxScale=" + args.maxScale;
    }
    if (typeof args.overlayToolbars != 'undefined') {
      fv += "&overlayToolbars=" + args.overlayToolbars;
    }
    var button = this.CUSTOM_BUTTON;
    if (button != null) {
      fv += "&customButton=" + encodeURIComponent(button.labelText);
      if (button.iconImage != null) {
        fv += "__icon__" + encodeURIComponent(button.iconImage);
      }
    }
    fv += "&swfURL="+encodeURIComponent(this.LITE_URL);
    fv = fv.substring(1); // kill the first &
    return fv;
  },
  // does the right thing for each browser
  // returns the Flash object, so we can communicate with it over the ExternalInterface
  getFlash : function () {
    // we should determine which one to pass back depending on Browser/OS configuration
    if (this.BROWSER_SAF || this.BROWSER_IE) {
      return document.getElementById(this.FLASH_ID_1); // outer <object>
    } else {
      return document.getElementById(this.FLASH_ID_2); // inner <object>
    }
  },
  getWindowSize : function () { // inner size
    var docElement = document.documentElement;
    var docBody = document.body;
    var w = 0, h = 0;
    if (typeof(window.innerWidth) == 'number') {
      // not IE
      w = window.innerWidth;
      h = window.innerHeight;
    } else if (docElement && (docElement.clientWidth || docElement.clientHeight)) {
      // IE 6+ in 'standards compliant mode'
      w = docElement.clientWidth;
      h = docElement.clientHeight;
    } else if (docBody && (docBody.clientWidth || docBody.clientHeight)) {
      // IE 4 compatible
      w = docBody.clientWidth;
      h = docBody.clientHeight;
    }
    return {w:w, h:h};
  },
  handleKeyPress : function (code) {
    if (!this.isRunning()) { return true; }
    var fl = this.getFlash();
    if (fl != null && fl.fl_keyPressed) {
      fl.fl_keyPressed(code); // forward to Flash
    } else {
      if (code == 27) { // ESC to close
        this.closeFlashUI();
        return false;
      }
    }
    if (code == 9 || code == 13) { // trap tab, enter
      return false;
    }
    return true; // allow the browser to process the key
  },
  handleMouseWheel : function (e) {
    // e.wheelDelta
    // Safari/Windows (MouseWheel Up is +120; Down is -120)
    var delta = 0;
    if (!e) {
      e = window.event;
    }
    if (e.wheelDelta) { // IE/Opera
      delta = e.wheelDelta/120;
      if (window.opera) {
        delta = -delta;
      }
    } else if (e.detail) { // Firefox/Moz
      var d = e.detail;
      // on mac, don't divide by 3...
      if (Math.abs(d) < 3) {
        delta = -d;
      } else {
        delta = -d/3;
      }
    }
    if (delta) {
      // don't send abs values < 1; otherwise, you can only scroll next
      PicLensLite.sendMouseScrollToFlash(delta);
    }
    if (e.preventDefault) {
      e.preventDefault();
    }
    e.returnValue = false;
    return false;
  },
  // check if PicLens is available
  hasPicLensClient : function () {
    // if we are debugging, don't checking
    if (this.DEBUG_NOCLIENT) {
      return false;
    }

    // check if the bridge has already been defined
    var clientExists = false;
    if (window.piclens) {
      clientExists = true;
    } else {
      // if not, try to define it here...
      var context = null;
      if (typeof PicLensContext != 'undefined') { // Firefox ONLY
        context = new PicLensContext();
      } else {                  // IE ONLY
        try {
          context = new ActiveXObject("PicLens.Context");
        } catch (e) {
          context = null;
        }
      }

       window.piclens = context;
      if (window.piclens) {
        clientExists = true;
      }
    }
    if (clientExists) { // check the version number
      var version;
      try { version = window.piclens.version; } catch (e) { return false; }

      var parts = version.split('.'); // minimum version is: 1.6.0.824
      if (parts[0] > 1) {         // a version 2.X product
        return true;
      } else if (parts[0] == 1) {     // a 1.X product
        if (parts[1] > 6) {       // a version 1.7.X product
          return true;
        } else if (parts[1] == 6) { // a 1.6 product
          if (parts[2] > 0) {     // a version 1.6.1.X product
            return true;
          } else if (parts[2] == 0) {
            if (parts[3] >= 824) { // 1.6.0.824 or newer...
              return true;
            }
          }
        }
      }
      return false; // e.g., a 0.X product
    } else {
      return false;
    }
  },
  invokeLytebox : function () {
    this.SHOW_LBOX = true; // user has specified that she wants to use the basic slideshow
    myLytebox.start(document.getElementById("lboxImage"), false, false);
    this.closeFlashUI();
  },
  showLyteboxLink : function () {
    myLytebox.updateLyteboxItems();
    myLytebox.doAnimations = false;
    var lboxImages = document.getElementById('lightbox_images');
    if (lboxImages != null) {
      lboxImages.style.display = "block";
      if (this.SHOW_LBOX && this.getFlash()==null) { // the user has clicked on lbox once, so we assume it going forward
        this.invokeLytebox();
      }
    }
  },
  startLytebox : function () { // allows us to include lytebox, unmodified
    if (typeof myLytebox != "undefined") {
      this.showLyteboxLink();
    } else {
      if (typeof initLytebox != "undefined") {
        initLytebox();
        this.showLyteboxLink();
      } else {
        if (this.LBOX_COUNT >= 4) {
          return; // give up after 600 ms
        }
        setTimeout(function (){PicLensLite.startLytebox();}, 150); // try again in 150 ms
        this.LBOX_COUNT++;
      }
    }
  },
  injectFlashPlayer : function () {
    var fg = this.LITE_FG_DIV;

    // determine the width and height of the flash component
    var flashWInner;
    var flashHInner;
    flashWInner = flashHInner = '100%';
    if (this.BROWSER_IE6) {
      flashWInner = flashHInner = '0';
    }

    var flashVars = this.generateFlashVars();
    var altContentHTML = this.generateAlternativeContent(); // non-flash content

    if (this.meetsRequirements()) {
      var par = '<param name=';
      fg.innerHTML =
        '<object id="'+ this.FLASH_ID_1 +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%">' + // SAF & IE
          par+'"movie" value="' + this.LITE_URL + '" />' +
          par+'"quality" value="high"/> ' +
          par+'"bgcolor" value="#000000"/> ' +
          par+'"allowScriptAccess" value="always"/> ' +
          par+'"FlashVars" value="' + flashVars + '"/> ' +
          par+'"allowFullScreen" value="true"/> ' +
          par+'"wmode" value="window"/> ' +
          par+'"scale" value="noscale"/> ' +
            '<object type="application/x-shockwave-flash" data="' + this.LITE_URL + '" width="'+flashWInner+'" height="'+flashHInner+'" ' + // NOT IE
              'quality="high" ' +
              'bgcolor="#000000" id="'+ this.FLASH_ID_2 + '" ' +
              'quality="high" ' +
              'FlashVars="' + flashVars + '" ' +
              'allowFullScreen="true" ' +
              'scale="noscale" ' +
              'wmode="window" ' +
              'allowScriptAccess="always">' +
              altContentHTML + // IE
            '</object>'+ // NOT IE
        '</object>';
      // fg.style.backgroundColor = '#252525'; // IE 100% div height problem
    } else {
      if (this.ON_NO_PLUGINS) {
        this.ON_NO_PLUGINS(); // callback instead of showing NoFlash.jpg
      } else {
        fg.innerHTML = altContentHTML;
        fg.style.minWidth = "860px";
        fg.style.minHeight = "550px";
        fg.style.backgroundColor = '#252525';
      }
    }

    if (this.BROWSER_SAF) {
      this.resizeUI(); // fixes layout
    }
  },
  // find the RSS feeds on this page, and return an array
  indexFeeds : function () {
    var linkTags = document.getElementsByTagName("link");
    var feeds = [];
    for (var i = 0; i != linkTags.length; ++i) {
      var link = linkTags[i], type = link.getAttribute("type");
      if (type == "application/rss+xml" || type == "text/xml") {
        feeds.push({ title: link.getAttribute("title"), url: link.getAttribute("href") });
      }
    }
    return feeds;
  },
  // once we get the response text, we launch flash
  loadViaXHR : function (url) {
    var self = this;
    var request = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("MSXML2.XMLHTTP.3.0");
    try {
      request.open("GET", url, true);
      request.onreadystatechange = function () {
        if (request.readyState == 4 && (request.status == 200 || request.status == 0)) { // 0 -> File System Testing
          if (request.responseText) {
            // at this point, we have the text
            self.showFlashUI(request.responseText);
          }
        }
      };
      request.send("");
    } catch (err) { // probably a crossdomain issue, so ask flash to try loading
      this.ARGS.loadFeedInFlash = true;
      this.showFlashUI("");
    }
  },
  meetsRequirements : function () {
    if (this.DEBUG_NOFLASH) {
      return false;
    }
    // if IE7, and Flash Detect returns ver 0, we show the Flash anyways
    var ie7FlashDetectionWorkaround = (this.FLASH_VER.major == 0) && this.BROWSER_IE;
    return swfobject.hasFlashPlayerVersion("9.0.28") || ie7FlashDetectionWorkaround;
  },
  removeChildren : function () {
    this.REMOVE_TIMER_ID = 0;
    // remove the divs after a timeout
    if (this.LITE_BG_DIV !== null) {
      document.body.removeChild(this.LITE_BG_DIV);
      this.LITE_BG_DIV = null;
    }
    if (this.LITE_FG_DIV !== null) {
      document.body.removeChild(this.LITE_FG_DIV);
      this.LITE_FG_DIV = null;
    }
  },
  resizeFlashToFitPaddedBox : function () {
    var flash = this.getFlash();
    if (flash) {
      var w = size.w - this.HPAD * 2;
      var h = size.h - this.VPAD * 2;
      flash.style.width = w; flash.style.height = h;
      flash.width = w; flash.height = h;
    }
  },
  resizeToFitPaddedBox : function (s, size) {
    if (typeof size == 'undefined') {
      size = this.getPageSize();
    }
    s.width = (size.w - this.HPAD * 2) + 'px';
    s.height = (size.h - this.VPAD * 2) + 'px';
  },
  resizeToPaddedBox : function (s) {
    s.left = s.right = this.HPAD + 'px';
    s.top = s.bottom = this.VPAD + 'px';
  },
  resizeUI : function () { // resize handler for Safari
    if (this.LITE_FG_DIV) {
      var fgs = this.LITE_FG_DIV.style;
      this.resizeToPaddedBox(fgs);
      this.resizeToFitPaddedBox(fgs);
      this.resizeFlashToFitPaddedBox();
    }
  },
  setRunningFlag : function (flag) {
    this.LITE_IS_RUNNING = flag;
    this.piclensIsRunning_ = flag;
  },
  setResizeHandler : function () { // for safari
    if (!this.RESIZE_HANDLER_EXISTS && this.BROWSER_SAF) {
      var self = this;
      window.addEventListener('resize', function () { self.resizeUI(); }, false);
      this.RESIZE_HANDLER_EXISTS = true;
    }
  },
  setResizeTimer : function () { // only do it for IE6...
    if (this.BROWSER_IE6) {
      this.RESIZE_TIMER_IE6 = setInterval(function () { PicLensLite.autoResize(); }, 1000);
    }
  },
  showFlashUI : function (feedText) {
    this.THE_FEED = feedText; // is "" if we are loading the feed in Flash
    this.findScriptLocation();
    this.createBackgroundOverlay();
    this.createForegroundFlashComponent();
    if (this.BROWSER_IE) {
      this.appendElementsToDocument();
    }
    this.injectFlashPlayer();
    if (!this.BROWSER_IE) {
      // Win Firefox needs this to be last
      // Other Browsers are OK with this
      this.appendElementsToDocument();
    }
    this.addKeyHandlers();
    this.addMouseHandlers();
    this.setRunningFlag(true);
    this.setResizeTimer();
    this.setResizeHandler();
    this.startLytebox();
  },
  sendMouseScrollToFlash : function (delta) {
    if (!this.isRunning()) { return; }
    var fl = this.getFlash();
    if (fl != null && fl.fl_mouseMoved) {
      fl.fl_mouseMoved(delta);
    }
  }
  // don't end the last function with a comma; it messes up IE7
};



/*  SWFObject v2.0 RC4: http://code.google.com/p/swfobject/
  Copyright 2007 Geoff Stearns, Michael Williams, and Bobby van der Sluis
  MIT License: http://www.opensource.org/licenses/mit-license.php */
var swfobject=function(){var X="undefined",P="object",a="visibility:visible",e="visibility:hidden",B="Shockwave Flash",h="ShockwaveFlash.ShockwaveFlash",V="application/x-shockwave-flash",K="SWFObjectExprInst",G=window,g=document,N=navigator,f=[],H=[],Q=null,L=null,S=false,C=false;var Y=function(){var l=typeof g.getElementById!=X&&typeof g.getElementsByTagName!=X&&typeof g.createElement!=X&&typeof g.appendChild!=X&&typeof g.replaceChild!=X&&typeof g.removeChild!=X&&typeof g.cloneNode!=X,t=[0,0,0],n=null;if(typeof N.plugins!=X&&typeof N.plugins[B]==P){n=N.plugins[B].description;if(n){n=n.replace(/^.*\s+(\S+\s+\S+$)/,"$1");t[0]=parseInt(n.replace(/^(.*)\..*$/,"$1"),10);t[1]=parseInt(n.replace(/^.*\.(.*)\s.*$/,"$1"),10);t[2]=/r/.test(n)?parseInt(n.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof G.ActiveXObject!=X){var o=null,s=false;try{o=new ActiveXObject(h+".7")}catch(k){try{o=new ActiveXObject(h+".6");t=[6,0,21];o.AllowScriptAccess="always"}catch(k){if(t[0]==6){s=true}}if(!s){try{o=new ActiveXObject(h)}catch(k){}}}if(!s&&o){try{n=o.GetVariable("$version");if(n){n=n.split(" ")[1].split(",");t=[parseInt(n[0],10),parseInt(n[1],10),parseInt(n[2],10)]}}catch(k){}}}}var v=N.userAgent.toLowerCase(),j=N.platform.toLowerCase(),r=/webkit/.test(v)?parseFloat(v.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,i=false,q=j?/win/.test(j):/win/.test(v),m=j?/mac/.test(j):/mac/.test(v);/*@cc_on i=true;@if(@_win32)q=true;@elif(@_mac)m=true;@end@*/return{w3cdom:l,pv:t,webkit:r,ie:i,win:q,mac:m}}();var d=function(){if(!Y.w3cdom){return }J(I);if(Y.ie&&Y.win){try{g.write("<script id=__ie_ondomload defer=true src=//:><\/script>");var i=b("__ie_ondomload");if(i){i.onreadystatechange=function(){if(this.readyState=="complete"){this.parentNode.removeChild(this);U()}}}}catch(j){}}if(Y.webkit&&typeof g.readyState!=X){Q=setInterval(function(){if(/loaded|complete/.test(g.readyState)){U()}},10)}if(typeof g.addEventListener!=X){g.addEventListener("DOMContentLoaded",U,null)}M(U)}();function U(){if(S){return }if(Y.ie&&Y.win){var m=W("span");try{var l=g.getElementsByTagName("body")[0].appendChild(m);l.parentNode.removeChild(l)}catch(n){return }}S=true;if(Q){clearInterval(Q);Q=null}var j=f.length;for(var k=0;k<j;k++){f[k]()}}function J(i){if(S){i()}else{f[f.length]=i}}function M(j){if(typeof G.addEventListener!=X){G.addEventListener("load",j,false)}else{if(typeof g.addEventListener!=X){g.addEventListener("load",j,false)}else{if(typeof G.attachEvent!=X){G.attachEvent("onload",j)}else{if(typeof G.onload=="function"){var i=G.onload;G.onload=function(){i();j()}}else{G.onload=j}}}}}function I(){var l=H.length;for(var j=0;j<l;j++){var m=H[j].id;if(Y.pv[0]>0){var k=b(m);if(k){H[j].width=k.getAttribute("width")?k.getAttribute("width"):"0";H[j].height=k.getAttribute("height")?k.getAttribute("height"):"0";if(O(H[j].swfVersion)){if(Y.webkit&&Y.webkit<312){T(k)}}else{if(H[j].expressInstall&&!C&&O("6.0.65")&&(Y.win||Y.mac)){D(H[j])}else{c(k)}}}}A("#"+m,a)}}function T(m){var k=m.getElementsByTagName(P)[0];if(k){var p=W("embed"),r=k.attributes;if(r){var o=r.length;for(var n=0;n<o;n++){if(r[n].nodeName.toLowerCase()=="data"){p.setAttribute("src",r[n].nodeValue)}else{p.setAttribute(r[n].nodeName,r[n].nodeValue)}}}var q=k.childNodes;if(q){var s=q.length;for(var l=0;l<s;l++){if(q[l].nodeType==1&&q[l].nodeName.toLowerCase()=="param"){p.setAttribute(q[l].getAttribute("name"),q[l].getAttribute("value"))}}}m.parentNode.replaceChild(p,m)}}function F(i){if(Y.ie&&Y.win&&O("8.0.0")){G.attachEvent("onunload",function(){var k=b(i);for(var j in k){if(typeof k[j]=="function"){k[j]=function(){}}}k.parentNode.removeChild(k)})}}function D(j){C=true;var o=b(j.id);if(o){if(j.altContentId){var l=b(j.altContentId);if(l){L=l}}else{L=Z(o)}if(!(/%$/.test(j.width))&&parseInt(j.width,10)<310){j.width="310"}if(!(/%$/.test(j.height))&&parseInt(j.height,10)<137){j.height="137"}g.title=g.title.slice(0,47)+" - Flash Player Installation";var n=Y.ie&&Y.win?"ActiveX":"PlugIn",k=g.title,m="MMredirectURL="+G.location+"&MMplayerType="+n+"&MMdoctitle="+k,p=j.id;if(Y.ie&&Y.win&&o.readyState!=4){var i=W("div");p+="SWFObjectNew";i.setAttribute("id",p);o.parentNode.insertBefore(i,o);o.style.display="none";G.attachEvent("onload",function(){o.parentNode.removeChild(o)})}R({data:j.expressInstall,id:K,width:j.width,height:j.height},{flashvars:m},p)}}function c(j){if(Y.ie&&Y.win&&j.readyState!=4){var i=W("div");j.parentNode.insertBefore(i,j);i.parentNode.replaceChild(Z(j),i);j.style.display="none";G.attachEvent("onload",function(){j.parentNode.removeChild(j)})}else{j.parentNode.replaceChild(Z(j),j)}}function Z(n){var m=W("div");if(Y.win&&Y.ie){m.innerHTML=n.innerHTML}else{var k=n.getElementsByTagName(P)[0];if(k){var o=k.childNodes;if(o){var j=o.length;for(var l=0;l<j;l++){if(!(o[l].nodeType==1&&o[l].nodeName.toLowerCase()=="param")&&!(o[l].nodeType==8)){m.appendChild(o[l].cloneNode(true))}}}}}return m}function R(AE,AC,q){var p,t=b(q);if(typeof AE.id==X){AE.id=q}if(Y.ie&&Y.win){var AD="";for(var z in AE){if(AE[z]!=Object.prototype[z]){if(z=="data"){AC.movie=AE[z]}else{if(z.toLowerCase()=="styleclass"){AD+=' class="'+AE[z]+'"'}else{if(z!="classid"){AD+=" "+z+'="'+AE[z]+'"'}}}}}var AB="";for(var y in AC){if(AC[y]!=Object.prototype[y]){AB+='<param name="'+y+'" value="'+AC[y]+'" />'}}t.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AD+">"+AB+"</object>";F(AE.id);p=b(AE.id)}else{if(Y.webkit&&Y.webkit<312){var AA=W("embed");AA.setAttribute("type",V);for(var x in AE){if(AE[x]!=Object.prototype[x]){if(x=="data"){AA.setAttribute("src",AE[x])}else{if(x.toLowerCase()=="styleclass"){AA.setAttribute("class",AE[x])}else{if(x!="classid"){AA.setAttribute(x,AE[x])}}}}}for(var w in AC){if(AC[w]!=Object.prototype[w]){if(w!="movie"){AA.setAttribute(w,AC[w])}}}t.parentNode.replaceChild(AA,t);p=AA}else{var s=W(P);s.setAttribute("type",V);for(var v in AE){if(AE[v]!=Object.prototype[v]){if(v.toLowerCase()=="styleclass"){s.setAttribute("class",AE[v])}else{if(v!="classid"){s.setAttribute(v,AE[v])}}}}for(var u in AC){if(AC[u]!=Object.prototype[u]&&u!="movie"){E(s,u,AC[u])}}t.parentNode.replaceChild(s,t);p=s}}return p}function E(k,i,j){var l=W("param");l.setAttribute("name",i);l.setAttribute("value",j);k.appendChild(l)}function b(i){return g.getElementById(i)}function W(i){return g.createElement(i)}function O(k){var j=Y.pv,i=k.split(".");i[0]=parseInt(i[0],10);i[1]=parseInt(i[1],10);i[2]=parseInt(i[2],10);return(j[0]>i[0]||(j[0]==i[0]&&j[1]>i[1])||(j[0]==i[0]&&j[1]==i[1]&&j[2]>=i[2]))?true:false}function A(m,j){if(Y.ie&&Y.mac){return }var l=g.getElementsByTagName("head")[0],k=W("style");k.setAttribute("type","text/css");k.setAttribute("media","screen");if(!(Y.ie&&Y.win)&&typeof g.createTextNode!=X){k.appendChild(g.createTextNode(m+" {"+j+"}"))}l.appendChild(k);if(Y.ie&&Y.win&&typeof g.styleSheets!=X&&g.styleSheets.length>0){var i=g.styleSheets[g.styleSheets.length-1];if(typeof i.addRule==P){i.addRule(m,j)}}}return{registerObject:function(l,i,k){if(!Y.w3cdom||!l||!i){return }var j={};j.id=l;j.swfVersion=i;j.expressInstall=k?k:false;H[H.length]=j;A("#"+l,e)},getObjectById:function(l){var i=null;if(Y.w3cdom&&S){var j=b(l);if(j){var k=j.getElementsByTagName(P)[0];if(!k||(k&&typeof j.SetVariable!=X)){i=j}else{if(typeof k.SetVariable!=X){i=k}}}}return i},embedSWF:function(n,u,r,t,j,m,k,p,s){if(!Y.w3cdom||!n||!u||!r||!t||!j){return }r+="";t+="";if(O(j)){A("#"+u,e);var q=(typeof s==P)?s:{};q.data=n;q.width=r;q.height=t;var o=(typeof p==P)?p:{};if(typeof k==P){for(var l in k){if(k[l]!=Object.prototype[l]){if(typeof o.flashvars!=X){o.flashvars+="&"+l+"="+k[l]}else{o.flashvars=l+"="+k[l]}}}}J(function(){R(q,o,u);A("#"+u,a)})}else{if(m&&!C&&O("6.0.65")&&(Y.win||Y.mac)){A("#"+u,e);J(function(){var i={};i.id=i.altContentId=u;i.width=r;i.height=t;i.expressInstall=m;D(i);A("#"+u,a)})}}},getFlashPlayerVersion:function(){return{major:Y.pv[0],minor:Y.pv[1],release:Y.pv[2]}},hasFlashPlayerVersion:O,createSWF:function(k,j,i){if(Y.w3cdom&&S){return R(k,j,i)}else{return undefined}},createCSS:function(j,i){if(Y.w3cdom){A(j,i)}},addDomLoadEvent:J,addLoadEvent:M,getQueryParamValue:function(m){var l=g.location.search||g.location.hash;if(m==null){return l}if(l){var k=l.substring(1).split("&");for(var j=0;j<k.length;j++){if(k[j].substring(0,k[j].indexOf("="))==m){return k[j].substring((k[j].indexOf("=")+1))}}}return""},expressInstallCallback:function(){if(C&&L){var i=b(K);if(i){i.parentNode.replaceChild(L,i);L=null;C=false}}}}}();

/* BrowserDetect: http://www.quirksmode.org/js/detect.html */
var BrowserDetect={
  init:function() { this.browser = this.searchString(this.dataBrowser) || "Unknown Browser"; this.version = this.searchVersion(navigator.userAgent) || this.searchVersion(navigator.appVersion) || "Unknown Version"; this.OS = this.searchString(this.dataOS) || "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" },
    { string: navigator.userAgent, subString: "Netscape", identity: "Netscape" }, // newer Netscapes (6+)
    { string: navigator.userAgent, subString: "MSIE", identity: "Explorer", versionSearch: "MSIE" },
    { string: navigator.userAgent, subString: "Gecko", identity: "Mozilla", versionSearch: "rv" },
    { string: navigator.userAgent, subString: "Mozilla", identity: "Netscape", versionSearch: "Mozilla" } // older Netscapes (4-)
  ],
  dataOS:[{ string: navigator.platform, subString: "Win", identity: "Windows" }, { string: navigator.platform, subString: "Mac", identity: "Mac" }, { string: navigator.platform, subString: "Linux", identity: "Linux" } ]
};
BrowserDetect.init();