
// Polar Rose Widget
// http://info.polarrose.com/partners
// http://info.polarrose.com/terms/
// http://info.polarrose.com/partners/#Terms
//
// Copyright (c) 2009, Polar Rose
//
// 2009-02-02 v0.10.0

if (!window.polarrosewidget) {
(function(){
this.polarrosewidget = {};

//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

function PolarRoseFrontend() {
  this.dashboard = new PolarRoseFrontendDashboard();
  this.widget = new PolarRoseFrontendWidget();
}

//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

function PolarRoseFrontendDashboard() {
  this.dashboard = null;
  this.url = "";
  this.batchurl = "";
  this.thumburl = "";
  this.imageurl = "";
}

PolarRoseFrontendDashboard.prototype.validateDashboard = function(response) {
  polarrose.debug("Validating Dashboard Response");
  if (response && (response.constructor === Object)) {
    if (response.collectionName && (response.collectionName.constructor === String)
      && response.totalFaces && (response.totalFaces.constructor === Number) && (parseInt(response.totalFaces,10) > 0)) {
      
      this.dashboard = {
        "collection":response.collectionName,
        "total":parseInt(response.totalFaces,10),
        "named":0
      };
      if (response.namedFaces && (response.namedFaces.constructor === Number) && (parseInt(response.namedFaces,10) > 0)) {
        this.dashboard.named = Math.min(parseInt(response.namedFaces,10),this.dashboard.total);
      }
      
      if (this.dashboard.named > 0) {
        polarrose.frontend.widget.collection = this.dashboard.collection;
        polarrose.frontend.widget.addDocumentEvents(document);
        polarrose.frontend.widget.addWindowEvents(window);
        polarrose.backend.widget.submitPage(document);
      }
      
      this.dashboard.groups = new Array();
      if (response.groups && (response.groups.constructor === Array)) {
        for (var i=0; i<response.groups.length; i++) {
          if (response.groups[i].face && (response.groups[i].face.constructor === String)
            && response.groups[i].name && (response.groups[i].name.constructor === String)
            && response.groups[i].count && (response.groups[i].count.constructor === Number) && (parseInt(response.groups[i].count,10) > 0)) {
            this.dashboard.groups.push({
              "id":response.groups[i].face,
              "name":response.groups[i].name,
              "count":parseInt(response.groups[i].count,10)
            });
          }
        }
        var sortingfunction = function(a,b){return b.count-a.count;}
        this.dashboard.groups.sort(sortingfunction);
        // TODO: cut array?
        this.dashboard.groups.splice(5,(this.dashboard.groups.length-5));
      }
      
      this.buildDashboard(this.dashboard, null, null);
    }
  }
}

PolarRoseFrontendDashboard.prototype.buildDashboard = function(dashboard, message, message2) {
  polarrose.debug("Building Dashboard");
  var result = (dashboard||message||message2)?this.createDashboard((message||message2),(dashboard&&dashboard.named===0)):null;
  if (result && result.catfish) {
    result.catfish.appendChild(this.createBatchNameButton(dashboard.collection));
  } else if (result && result.dashboard) {
    var polarrosedashboard = result.dashboard;
    if (message||message2) {
      polarrosedashboard.appendChild(this.createLinkedLogo());
      if (message) {
        var status = document.createElement("span");
        status.className = "polarrosedashboard-status";
        status.appendChild(document.createTextNode(message));
        polarrosedashboard.appendChild(status);
      }
      if (message2) {
        var status2 = document.createElement("span");
        status2.className = "polarrosedashboard-status2";
        status2.appendChild(document.createTextNode(message2));
        polarrosedashboard.appendChild(status2);
      }
    } else if (dashboard) {
      if (dashboard.named === 0 && polarrose.config.owner) {
        polarrosedashboard.appendChild(this.createLinkedLogo());
        polarrosedashboard.appendChild(this.createBatchNameButton(dashboard.collection));
      } else {
        var search = this.createModule("Search");
        
        var searchform = document.createElement("form");
        searchform.id = "polarrosedashboard-searchform";
        searchform.setAttribute("method","get");
        searchform.setAttribute("action",(this.url+dashboard.collection));
        searchform.setAttribute("target","_top");
        var searchfieldset = document.createElement("fieldset");
        var searchinput = document.createElement("input");
        searchinput.id = "polarrosedashboard-searchinput";
        searchinput.setAttribute("type","text");
        searchinput.setAttribute("name","search");
        searchinput.setAttribute("value","Enter a name here...");
        this.addEvent(searchinput,"focus",function(e){
          if (!e) var e = window.event;
          var t = e.target || e.srcElement;
          if (t && polarrose.isIE) {
            t.style.fontStyle = "normal";
          }
          if (t && t.value === "Enter a name here...") {
            t.value = "";
          }
        });
        // JAlbum stuff...
        if (window.turnOffListeners && window.turnOffListeners.constructor===Function) {
          searchinput.onfocus = window.turnOffListeners;
          searchinput.onclick = window.turnOffListeners;
        }
        if (window.turnOnListeners && window.turnOnListeners.constructor===Function) {
          searchinput.onblur = window.turnOnListeners;
        }
        searchfieldset.appendChild(searchinput);
        searchform.appendChild(searchfieldset);
        search.appendChild(searchform);
        
        var logolink = document.createElement("a");
        logolink.className = "polarrosedashboard-logotype";
        logolink.setAttribute("href","http://www.polarrose.com/");
        logolink.setAttribute("title","www.polarrose.com");
        logolink.setAttribute("target","_top");
        var logo = document.createElement("img");
        logo.className = "polarrosedashboard-logotype";
        if (polarrose.config.theme && polarrose.config.theme === "fire") {
          logo.setAttribute("src",this.imageurl+"/images/logo-small-color.gif");
        } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
          logo.setAttribute("src",this.imageurl+"/images/logo-small-color.gif");
        } else {
          logo.setAttribute("src",this.imageurl+"/images/logo-small.gif");
        }
        logolink.appendChild(logo);
        search.appendChild(logolink);
        
        var searchlink = document.createElement("a");
        searchlink.id = "polarrosedashboard-searchbutton";
        searchlink.className = "polarrosedashboard-searchbutton";
        searchlink.setAttribute("href",(this.url+dashboard.collection+"?search="));
        searchlink.setAttribute("target","_top");
        var updateSearchUrl = function(url){
          return function(e){
            var searchbutton = document.getElementById("polarrosedashboard-searchbutton");
            if (searchbutton) {
              var searchurl = url;
              var inputelement = document.getElementById("polarrosedashboard-searchinput");
              if (inputelement && inputelement.value && !(inputelement.value==="Enter a name here...")) {
                searchurl += encodeURIComponent(inputelement.value.replace(/[<>&"]/gi," ")).replace(/(%20)+/g,"+")
              }
              searchbutton.setAttribute("href",searchurl);
            }
          };
        }((this.url + dashboard.collection + "?search="));
        this.addEvent(searchlink,"mouseover",updateSearchUrl);
        this.addEvent(searchlink,"click",function(e){
          var inputelement = document.getElementById("polarrosedashboard-searchinput");
          if (inputelement && inputelement.value==="Enter a name here...") {
            inputelement.value = "";
          }
          var formelement = document.getElementById("polarrosedashboard-searchform");
          if (formelement) {
            formelement.submit();
          }
        });
        searchlink.appendChild(document.createTextNode("Search"));
        search.appendChild(searchlink);
          
        polarrosedashboard.appendChild(search);
      
        // * * * * *
      
        var statistics = this.createModule("Statistics");
        statistics.appendChild(this.createStatistic((dashboard.total),"PEOPLE",dashboard.collection));
        statistics.appendChild(this.createStatistic((dashboard.named),"NAMED",dashboard.collection));
        statistics.appendChild(this.createStatistic((dashboard.total-dashboard.named),"UNNAMED",dashboard.collection));
        polarrosedashboard.appendChild(statistics);
        
        // * * * * *
        
        var toppeoplesize = (polarrose.config.layout==="vertical") ? 3 : Math.min( (dashboard.groups.length), (polarrose.config.toppeoplesize||5) );
        var people = this.createModule("Top people", toppeoplesize);
        for (var i=0; i<toppeoplesize; i++) {
          people.appendChild(this.createThumb(dashboard.groups[i].id,dashboard.groups[i].name,dashboard.groups[i].count,dashboard.collection,(i===0?true:false)));
        }
        polarrosedashboard.appendChild(people);
      }
    }
  }
  this.setDashboardVisibility(polarrose.config.dashboardvisibility); // TODO ?
}

PolarRoseFrontendDashboard.prototype.createDashboard = function(message, unnamed) {
  polarrose.debug("Creating Dashboard");
  this.createStyleSheet();
  var polarrosedashboard = document.getElementById("polarrosedashboard") || null;
  if (polarrosedashboard) {
    while (polarrosedashboard.hasChildNodes()) {
  	  polarrosedashboard.removeChild(polarrosedashboard.firstChild);
  	}
  } else {
    polarrosedashboard = document.createElement("div");
    polarrosedashboard.id = "polarrosedashboard";
    if (polarrose.config.insert) {
      if (document.getElementById(polarrose.config.insert)) {
        document.getElementById(polarrose.config.insert).appendChild(polarrosedashboard);
      } else {
        return null;
      }
    } else if (message) {
      return null;
    } else if (unnamed && !polarrose.config.owner) {
      return null;
    } else {
      if (unnamed && polarrose.config.owner) {
        var catfishtop = this.createCatfish(unnamed);
        return {"dashboard":null,"catfish":catfishtop};
      } else {
        var catfish = this.createCatfish();
        catfish.appendChild(polarrosedashboard);
      }
    }
  }
  return {"dashboard":polarrosedashboard,"catfish":null};
}
  
PolarRoseFrontendDashboard.prototype.createStyleSheet = function() {
  polarrose.debug("Creating Style Sheet");
  if (!(polarrose.config.css===false)) {
    var styles = document.getElementsByTagName("style");
    for (var i=0; i<styles.length; i++) {
      if (styles[i].getAttribute("title") === "polarrosedashboard") {
        return;
      }
    }
    this.addStyleSheet();
  }
}

PolarRoseFrontendDashboard.prototype.createBatchNameButton = function(collection) {
  var batchnamebutton = document.createElement("a");
  batchnamebutton.id = "polarrosedashboard-batchnamebutton";
  batchnamebutton.setAttribute("href",(this.batchurl+collection+"&returnPageUrl="+ polarrose.backend.encodeUrl(polarrose.backend.cleaneUrl(document.location.href)) ));
  batchnamebutton.setAttribute("target","_top");
  batchnamebutton.appendChild(document.createTextNode("Name the people appearing in these photos"));
  return batchnamebutton;
}

PolarRoseFrontendDashboard.prototype.createLinkedLogo = function() {
  var imagelink = document.createElement("a");
  imagelink.setAttribute("href","http://www.polarrose.com/");
  imagelink.setAttribute("title","www.polarrose.com");
  imagelink.setAttribute("target","_top");
  imagelink.style.cursor = "pointer";
  var image = document.createElement("img");
  image.className = "polarrosedashboard-logo";
  image.style.cursor = "pointer";
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    image.setAttribute("src",this.imageurl+"/images/logo-small-color.gif");
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    image.setAttribute("src",this.imageurl+"/images/logo-small-color.gif");
  } else {
    image.setAttribute("src",this.imageurl+"/images/logo-small.gif");
  }
  imagelink.appendChild(image);
  return imagelink;  
}

PolarRoseFrontendDashboard.prototype.clearStyleSheet = function() {
  polarrose.debug("Clearing Style Sheet");
  var styles = document.getElementsByTagName("style");
  for (var i=(styles.length-1); i>=0; i--) {
    if (styles[i].getAttribute("title") === "polarrosedashboard" && styles[i].parentNode) {
      styles[i].parentNode.removeChild(styles[i]);
    }
  }
}

PolarRoseFrontendDashboard.prototype.clearCatfish = function() {
  polarrose.debug("Clearing Catfish");
  this.clearDashboard();
  var polarrosedashboardCatfish = document.getElementById("polarrosedashboard-catfish");
  if (polarrosedashboardCatfish && polarrosedashboardCatfish.parentNode) {
    polarrosedashboardCatfish.parentNode.removeChild(polarrosedashboardCatfish);
  }
}

PolarRoseFrontendDashboard.prototype.clearDashboard = function() {
  polarrose.debug("Clearing Dashboard");
  this.dashboard = null;
  var polarrosedashboard = document.getElementById("polarrosedashboard");
  if (polarrosedashboard && polarrosedashboard.parentNode) {
    polarrosedashboard.parentNode.removeChild(polarrosedashboard);
  }
}

//****************************************************************************************************

PolarRoseFrontendDashboard.prototype.createModule = function(headline, toppeoplesize) {
  var module = document.createElement("div");
  if (toppeoplesize && toppeoplesize >= 5) {
    module.className = "polarrosedashboard-module polarrosedashboard-module-five";
  } else if (toppeoplesize && toppeoplesize >= 4) {
    module.className = "polarrosedashboard-module polarrosedashboard-module-four";
  } else {
    module.className = "polarrosedashboard-module";
  }
  var header = document.createElement("span");
  header.className = "polarrosedashboard-headline";
  header.appendChild(document.createTextNode(headline));
  module.appendChild(header);
  var questionlink = document.createElement("a");
  questionlink.className = "polarrosedashboard-questionmark";
  questionlink.setAttribute("href","#");
  questionlink.setAttribute("target","_top");
  questionlink.setAttribute("title","Explain this...");
  questionlink.appendChild(document.createTextNode("?"));
  module.appendChild(questionlink);
  return module;
}

PolarRoseFrontendDashboard.prototype.createStatistic = function(number,what,collection) {
  var statistic = document.createElement("div");
  statistic.className = "polarrosedashboard-statistic";
  var statisticcontent = document.createElement("div");
  statisticcontent.className = "polarrosedashboard-statisticcontent";
  var statisticlink = document.createElement("a");
  statisticlink.setAttribute("target","_top");
  if (what === "NAMED") {
    statisticlink.setAttribute("href",(this.url+collection+"?named=true"));
    statisticlink.setAttribute("title","View all named people in this album...");
  } else if (what === "UNNAMED") {
    if (number === 0) {
      statisticlink.setAttribute("href",(this.url+collection));
      statisticlink.setAttribute("title","View all people in this album...");
    } else if (polarrose.config.owner) {
      statisticlink.setAttribute("href",(this.batchurl+collection+"&returnPageUrl="+ polarrose.backend.encodeUrl(polarrose.backend.cleaneUrl(document.location.href)) ));
      statisticlink.setAttribute("title","Launch batch namer and name these people...");
      statistic.className = "polarrosedashboard-statistic polarrosedashboard-statistic-button"; // TODO ?
      statisticcontent.className = "polarrosedashboard-statisticcontent polarrosedashboard-statisticcontent-button";
    } else {
      statisticlink.setAttribute("href",(this.url+collection+"?named=false"));
      statisticlink.setAttribute("title","View all unnamed people in this album...");
    }
  } else {
    statisticlink.setAttribute("href",(this.url+collection));
    statisticlink.setAttribute("title","View all people in this album...");
  }
  statisticlink.appendChild(document.createTextNode(number));
  statisticlink.appendChild(document.createElement("br"));
  var forwhat = document.createElement("span");
  forwhat.appendChild(document.createTextNode(what));
  statisticlink.appendChild(forwhat);
  statisticcontent.appendChild(statisticlink);
  statistic.appendChild(statisticcontent);
  return statistic;
}

PolarRoseFrontendDashboard.prototype.createThumb = function(id,name,count,collection) {
  var thumblink = document.createElement("a");
  thumblink.className = "polarrosedashboard-mugshot";
  thumblink.setAttribute("target","_top");
  thumblink.setAttribute("href",(this.url+collection+"?name="+( encodeURIComponent(name.replace(/[<>&"]/gi," ")).replace(/(%20)+/g,"+") )));
  thumblink.setAttribute("title","View all photos of "+name+"...");
  var thumb = document.createElement("img");
  thumb.setAttribute("src",(this.thumburl+"/"+id));
  thumblink.appendChild(thumb);
  return thumblink;
}

//****************************************************************************************************

PolarRoseFrontendDashboard.prototype.createCatfish = function(batchnamebutton) {
  var catfish1 = document.createElement("div");
  var catfish2 = document.createElement("div");
  var catfish3 = document.createElement("div");
  var catfish4 = document.createElement("div");
  var catfishtop = document.createElement("div");
  
  catfish1.id = "polarrosedashboard-catfish";
  
  var basestyle = "background: transparent none repeat scroll top left; border: 0px solid transparent; "
  +"clear: none; cursor: auto; display: block; float: left; position: static; visibility: visible; "
  +"height: auto; width: auto; line-height: normal; font: normal normal normal 13px sans-serif; "
  +"margin: 0px; outline: transparent none 0px; padding: 0px; "
  +"top: auto; right: auto; bottom: auto; left: auto; "
  +"overflow: visible; vertical-align: baseline; z-index: 1600; color: black; direction: ltr; "
  +"line-height: normal; letter-spacing: normal; text-align: right; text-decoration: none; "
  +"text-indent: 0; text-shadow: none; text-transform: none; white-space: normal; word-spacing: normal; ";

  var backgroundcolor = "black";
  var bordercolor = "white";
  var backgroundimage = this.imageurl+"/images/logo-small.gif";
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    backgroundcolor = "yellow"; // #C0FF3E
    bordercolor = "orange";
    backgroundimage = this.imageurl+"/images/logo-small-color.gif";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    backgroundcolor = "white";
    bordercolor = "black";
    backgroundimage = this.imageurl+"/images/logo-small-color.gif";
  }

  this.setStyle(catfish1, basestyle+"position:fixed; left:0px; right:0px; bottom:0px; background-color:"+backgroundcolor+"; overflow:hidden; border-top: 3px double "+bordercolor+"; ");
  this.setStyle(catfish2, basestyle+"position:relative; left:50%; width:1000px; ");
  this.setStyle(catfish3, basestyle+"position:relative; left:0px; ");
  this.setStyle(catfish4, basestyle+"position:relative; left:-50%; ");
  this.setStyle(catfishtop, basestyle+"width:100%; left:0px; right:0px; height:0px; background: transparent url("+backgroundimage+") no-repeat scroll 6px 4px; overflow:hidden; ");

  this.catfish = catfish1;
  this.catfishtop = catfishtop;
  this.catfishbottom = catfish2;
  this.heights = {
    top:0,
    bottom:0,
    topTimer:0,
    bottomTimer:0
  };
  
  if (!batchnamebutton) {
    this.addEvent(catfish1,"mouseover",function(/*catfishRef,*/heightsRef){
      return function(e) {
        //if (!e) var e = window.event;
        //var t = e.target || e.srcElement; // to (image)
        //var rt = e.relatedTarget || e.fromElement; // from
        if (heightsRef.bottom!==97) {
          polarrose.frontend.dashboard.showCatfish();
        }
      };
    }(/*catfish1,*/this.heights));
    this.addEvent(catfish1,"mouseout",function(catfishRef){
      return function(e) {
        if (!e) var e = window.event;
        //var t = e.target || e.srcElement; // from (image)
        var rt = e.relatedTarget || e.toElement; // to
        for (var c=25; rt&&c; c--) {
          if (rt === catfishRef) return;
          rt = rt.parentNode;
        }
        polarrose.frontend.dashboard.hideCatfish();
      };
    }(catfish1));
  }
  
  catfish3.appendChild(catfish4);
  catfish2.appendChild(catfish3);
  catfish1.appendChild(catfishtop);
  catfish1.appendChild(catfish2);
  document.body.appendChild(catfish1);
  
  this.hideCatfish();
  
  return (batchnamebutton)?catfishtop:catfish4;
}

PolarRoseFrontendDashboard.prototype.showCatfish = function() {
  this.setNewTopHeight(0);
  this.setNewBottomHeight(97);
}

PolarRoseFrontendDashboard.prototype.hideCatfish = function() {
  this.setNewTopHeight(32);
  this.setNewBottomHeight(32);
}

PolarRoseFrontendDashboard.prototype.setNewTopHeight = function(height) {
  clearTimeout(this.heights.topTimer);
  if (this.heights.top !== height) {
    this.heights.top = this.getNewHeight(this.heights.top,height);;
    this.catfishtop.style.height = (this.heights.top+"px");
    if (this.heights.top !== height) {
      var temp = function(h) {
        return function() {
          polarrose.frontend.dashboard.setNewTopHeight(h);
        };
      } (height);
      clearTimeout(this.heights.topTimer);
      this.heights.topTimer = setTimeout(temp, 40);
    }
  }
}

PolarRoseFrontendDashboard.prototype.setNewBottomHeight = function(height) {
  clearTimeout(this.heights.bottomTimer);
  if (this.heights.bottom !== height) {
    this.heights.bottom = this.getNewHeight(this.heights.bottom,height);;
    this.catfish.style.height = (this.heights.bottom+"px");
    if (this.heights.bottom !== height) {
      var temp = function(h) {
        return function() {
          polarrose.frontend.dashboard.setNewBottomHeight(h);
        };
      } (height);
      clearTimeout(this.heights.bottomTimer);
      this.heights.bottomTimer = setTimeout(temp, 40);
    }
  }
}

PolarRoseFrontendDashboard.prototype.getNewHeight = function(actualHeight,desiredHeight) {
  var newHeight = desiredHeight;
  if (actualHeight < desiredHeight) {
    newHeight = Math.round((3*desiredHeight + actualHeight) * 0.25);
  } else {
    newHeight = Math.round((desiredHeight + 3*actualHeight) * 0.25);
  }
  if (newHeight === actualHeight) {
    if (newHeight < desiredHeight) newHeight++;
    else if (newHeight > desiredHeight) newHeight--;
  }
  return newHeight;
}

//****************************************************************************************************

PolarRoseFrontendDashboard.prototype.addStyleSheet = function() {
  var style = document.createElement("style");
  style.setAttribute('type','text/css');
  style.setAttribute('title','polarrosedashboard');
  
  var head = document.getElementsByTagName('head')[0];
  if (head.hasChildNodes()) {
    head.insertBefore(style,head.firstChild);
  } else {
    head.appendChild(style);
  }
  
  // * * * * * base style
  
  var styles = ""
  +"background: transparent none repeat scroll top left; \n"
  +"border: 0px solid transparent; \n"
  +"clear: none; \n"
  +"cursor: auto; \n"
  +"display: block; \n"
  +"float: left; \n"
  +"position: static; \n"
  +"visibility: visible; \n"
  +"height: auto; \n"
  +"width: auto; \n"
  +"line-height: normal; \n"
  +"font-style: normal; \n"
  +"font-variant: normal; \n"
  +"font-weight: normal; \n"
  +"font-size: 11px; \n"
  +"font-family: arial,helvetica,sans-serif; \n"
  +"margin: 0px; \n"
  +"outline: transparent none 0px; \n"
  +"padding: 0px; \n"
  +"top: auto; \n"
  +"right: auto; \n"
  +"bottom: auto; \n"
  +"left: auto; \n"
  +"overflow: visible; \n"
  +"vertical-align: baseline; \n"
  +"z-index: auto; \n"
  //+"color: black; \n"
  +"direction: ltr; \n"
  +"line-height: normal; \n"
  +"letter-spacing: normal; \n"
  +"text-align: right; \n"
  +"text-decoration: none; \n"
  +"text-indent: 0; \n"
  +"text-shadow: none; \n"
  +"text-transform: none; \n"
  +"white-space: normal; \n"
  +"word-spacing: normal; \n";
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles += "color: black; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles += "color: white; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles += "color: #555555; \n";
  } else { // dark (default)
    styles += "color: #AFAFAF; \n";
  }
  this.addStyle(style, "div#polarrosedashboard, div#polarrosedashboard *", styles);
  
  // * * * * * dashboard
  
  styles = ""
  +"padding: 4px 0px; \n"
  +"height: 89px; \n"
  +"min-height: 89px; \n"
  //+"width: 600px; \n"
  +"min-width: 600px; \n"
  +"";
  
  if (polarrose.config.layout==='vertical') {
    styles += "height: 273px; \n";
    styles += "min-height: 273px; \n";
    styles += "width: 200px; \n";
    styles += "min-width: 200px; \n";
  }
  
  this.addStyle(style, "div#polarrosedashboard", styles);
  //this.addStyle(style, "div#polarrosedashboard br", "float: none; \n");
  
  // * * * * * batchnamebutton
  
  styles = ""
  +"background: #71AA30 url("+this.imageurl+"/buttons/button-background-green.gif) repeat scroll top left; \n"
  //+"border: 2px solid white; \n"
  +"clear: none; \n"
  +"cursor: pointer; \n"
  +"display: block; \n"
  +"float: right; \n"
  +"position: static; \n"
  +"visibility: visible; \n"
  +"height: auto; \n"
  +"width: auto; \n"
  +"line-height: normal; \n"
  +"font-style: normal; \n"
  +"font-variant: normal; \n"
  +"font-weight: bold; \n"
  +"font-size: 12px; \n"
  +"font-family: arial,helvetica,sans-serif; \n"
  +"margin: 3px 8px 3px 8px; \n"
  +"outline: transparent none 0px; \n"
  +"padding: 3px 7px; \n"
  +"top: auto; \n"
  +"right: auto; \n"
  +"bottom: auto; \n"
  +"left: auto; \n"
  +"overflow: visible; \n"
  +"vertical-align: baseline; \n"
  +"z-index: auto; \n"
  //+"color: white; \n"
  +"direction: ltr; \n"
  +"line-height: normal; \n"
  +"letter-spacing: normal; \n"
  +"text-align: right; \n"
  +"text-decoration: none; \n"
  +"text-indent: 0; \n"
  +"text-shadow: none; \n"
  +"text-transform: none; \n"
  +"white-space: normal; \n"
  +"word-spacing: normal; \n"
  +"-moz-border-radius: 6px; \n"
  +"-khtml-border-radius: 6px; \n"
  +"-webkit-border-radius: 6px; \n"
  +"border-radius: 6px; \n"
  +"";
  
  if (polarrose.config.insert) {
    styles += "float: left; \n";
    styles += "margin: 30px 0px 30px 30px; \n";
  }
  
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles += "color: orange; \n";
    styles += "border: 2px solid orange; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles += "color: #8B3626; \n";
    styles += "border: 2px solid #8B3626; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles += "color: white; \n";
    styles += "border: 2px solid white; \n";
  } else {
    styles += "color: white; \n";
    styles += "border: 2px solid white; \n";
  }
  
  if (polarrose.config.layout==='vertical') {
    //styles += "clear: left; \n";
    styles += "margin: 10px 10px 10px 10px; \n";
    styles += "text-align: left; \n";
  }
  
  this.addStyle(style, "a#polarrosedashboard-batchnamebutton", styles);
  this.addStyle(style, "a#polarrosedashboard-batchnamebutton:hover", "background: #71AA30 none repeat scroll top left; \n");
  
  this.addStyle(style, "div#polarrosedashboard a#polarrosedashboard-batchnamebutton", styles);
  this.addStyle(style, "div#polarrosedashboard a#polarrosedashboard-batchnamebutton:hover", "background: #71AA30 none repeat scroll top left; \n");
  
  // * * * * * logo
  
  styles = ""
  +"margin: 30px 0px 30px 30px; \n"
  +"";
  
  if (polarrose.config.layout==='vertical') {
    //styles += "clear: left; \n";
    styles += "margin: 20px 10px 10px 10px; \n";
  }
  
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-logo", styles);
  
  // * * * * * status
  
  styles = ""
  +"font-weight: bold; \n"
  +"font-size: 12px; \n"
  +"font-family: arial,helvetica,sans-serif; \n"
  +"margin: 30px 0px 30px 30px; \n"
  +"padding: 3px 7px; \n"
  +"-moz-border-radius: 6px; \n"
  +"-khtml-border-radius: 6px; \n"
  +"-webkit-border-radius: 6px; \n"
  +"border-radius: 6px; \n"
  +"";
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles += "color: orange; \n";
    styles += "border: 2px solid orange; \n";
    styles += "background: white; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles += "color: #8B3626; \n";
    styles += "border: 2px solid #8B3626; \n";
    styles += "background: white; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles += "color: white; \n";
    styles += "border: 2px solid white; \n";
    styles += "background: #333333; \n";
  } else {
    styles += "color: white; \n";
    styles += "border: 2px solid white; \n";
    styles += "background: #333333; \n";
  }
  if (polarrose.config.layout==='vertical') {
    //styles += "clear: left; \n";
    styles += "margin: 10px 10px 10px 10px; \n";
    styles += "text-align: left; \n";
  }
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-status", styles);
  
  styles = ""
  //+"font-weight: bold; \n"
  +"font-size: 12px; \n"
  +"font-family: arial,helvetica,sans-serif; \n"
  +"font-style: italic; \n"
  +"margin: 30px 0px 30px 25px; \n"
  +"padding: 3px 7px; \n"
  +"-moz-border-radius: 6px; \n"
  +"-khtml-border-radius: 6px; \n"
  +"-webkit-border-radius: 6px; \n"
  +"border-radius: 6px; \n"
  +"";
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles += "color: orange; \n";
    styles += "border: 2px solid transparent; \n";
    //styles += "background: white; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles += "color: #8B3626; \n";
    styles += "border: 2px solid transparent; \n";
    //styles += "background: white; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles += "color: #333333; \n";
    styles += "border: 2px solid transparent; \n";
    //styles += "background: #333333; \n";
  } else {
    styles += "color: white; \n";
    styles += "border: 2px solid transparent; \n";
    //styles += "background: #333333; \n";
  }
  if (polarrose.config.layout==='vertical') {
    //styles += "clear: left; \n";
    styles += "margin: 10px 10px 10px 5px; \n";
    styles += "text-align: left; \n";
  }
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-status2", styles);

  // * * * * * modules
  
  styles = ""
  +"position: relative; \n"
  +"margin: 2px 3px; \n"
  +"width: 194px; \n"
  +"min-width: 194px; \n"
  +"height: 85px; \n"
  +"min-height: 85px; \n"
  +"overflow: hidden; \n"
  +"-moz-border-radius: 5px; \n"
  +"-khtml-border-radius: 5px; \n"
  +"-webkit-border-radius: 5px; \n"
  +"border-radius: 5px; \n";
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles += "background-color: orange; \n";
    //styles += "border: 1px solid red; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles += "background-color: #8B3626; \n";
    //styles += "border: 1px solid black; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles += "background-color: white; \n";
    //styles += "border: 1px solid white; \n";
  } else {
    styles += "background-color: black; \n";
    //styles += "border: 1px solid black; \n";
  }
  
  if (polarrose.config.layout==='vertical') {
    styles += "clear: left; \n";
    styles += "margin: 3px 3px; \n";
  }
  
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module", styles);
  
  styles = ""
  +"width: 257px; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module-four", styles);
  
  styles = ""
  +"width: 320px; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module-five", styles);
 
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles = "background-color: red; \n";
    //styles += "border: 1px solid orange; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles = "background-color: #CD4F39; \n";
    //styles += "border: 1px solid white; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles = "background-color: #EEEEEE; \n";
    //styles += "border: 1px solid #EEEEEE; \n";
  } else {
    styles = "background-color: #333333; \n";
    //styles += "border: 1px solid #333333; \n";
  }
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module:hover", styles);

  //this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module + .polarrosedashboard-module", "margin-left: 5px; \n");
  
  styles = ""
  +"position: absolute; \n"
  +"left: 5px; \n"
  +"top: 5px; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-headline", styles);
  
  styles = ""
  +"position: absolute; \n"
  +"right: 5px; \n"
  +"top: 5px; \n"
  +"visibility: hidden; \n" // TODO remove when we want to show the question mark links
  +"font-style: italic; \n"
  +"cursor: pointer; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-questionmark", styles);
  
  styles = ""
  +"text-decoration: underline; \n"
  +"color: white; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-questionmark:hover", styles);

  // * * * * * search
  
  styles = ""
  +"margin-top: 22px; \n"
  +"margin-left: 5px; \n"
  +"-moz-border-radius: 5px; \n"
  +"-khtml-border-radius: 5px; \n"
  +"-webkit-border-radius: 5px; \n"
  +"border-radius: 5px; \n";
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles += "border: 1px solid white; \n";
    styles += "background-color: yellow; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles += "border: 1px solid white; \n";
    styles += "background-color: #333333; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles += "border: 1px solid #999999; \n";
    styles += "background-color: #FFFFFF; \n";
  } else {
    styles += "border: 1px solid #999999; \n";
    styles += "background-color: #FFFFFF; \n";
  }
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module form", styles);
  
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles = "border: 1px solid white; \n";
    styles += "background-color: orange; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles = "border: 1px solid white; \n";
    styles += "background-color: #444444; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles = "border: 1px solid #999999; \n";
    styles += "background-color: #FFFFFF; \n";
  } else {
    styles = "border: 1px solid #999999; \n";
    styles += "background-color: #FFFFFF; \n";
  }
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module form:hover", styles);
  
  styles = ""
  +"margin-top: 2px; \n"
  +"margin-left: 2px; \n"
  +"font-size: 18px; \n"
  +"font-style: italic; \n"
  +"width: 180px; \n"
  +"min-width: 180px; \n"
  +"max-width: 180px; \n"
  +"height: 24px; \n"
  +"min-height: 24px; \n"
  +"max-height: 24px; \n"
  +"text-align: left; \n"
  +"";
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    //styles += "color: black; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles += "color: #999999; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles += "color: #AAAAAA; \n";
  } else {
    styles += "color: #AAAAAA; \n";
  }
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module form input", styles);
  
  styles = ""
  +"font-style: normal; \n";
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    //
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles += "color: white; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles += "color: #333333; \n";
  } else {
    styles += "color: #333333; \n";
  }
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module form input:focus", styles);
  
  styles = ""
  +"position: absolute; \n"
  +"left: 3px; \n"
  +"top: 29px; \n"
  +"cursor: pointer; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-logotype", styles);
  
  styles = ""
  +"position: absolute; \n"
  +"right: 5px; \n"
  +"top: 0px; \n"
  +"margin-top: 55px; \n"
  +"cursor: pointer; \n"
  +"font-size: 12px; \n"
  +"line-height: 15px; \n"
  +"font-weight: bold; \n"
  +"color: white; \n"
  +"border: 2px solid white; \n"
  +"padding: 3px 7px; \n"
  +"background: #71AA30 url("+this.imageurl+"/buttons/button-background-green.gif) repeat scroll top left; \n"
  +"-moz-border-radius: 6px; \n"
  +"-khtml-border-radius: 6px; \n"
  +"-webkit-border-radius: 6px; \n"
  +"border-radius: 6px; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-searchbutton", styles);
  
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-searchbutton:hover", "background: #71AA30 none repeat scroll top left; \n");
  
  // * * * * * statistics
  
  styles = ""
  +"margin-top: 22px; \n"
  +"margin-left: 5px; \n"
  +"-moz-border-radius: 3px; \n"
  +"-khtml-border-radius: 3px; \n"
  +"-webkit-border-radius: 3px; \n"
  +"border-radius: 3px; \n";
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles += "border: 1px solid white; \n";
    styles += "background-color: yellow; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles += "border: 1px solid white; \n";
    styles += "background-color: #333333; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles += "border: 1px solid #EEEEEE; \n";
    styles += "background-color: #EEEEEE; \n";
  } else {
    styles += "border: 1px solid #333333; \n";
    styles += "background-color: #333333; \n";
  }
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-statistic", styles);
  
  styles = ""
  +"width: 56px; \n"
  +"min-width: 56px; \n"
  +"height: 56px; \n"
  +"min-height: 56px; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-statisticcontent", styles);
  
  styles = ""
  +"border: 2px solid white; \n"
  +"background: #71AA30 url("+this.imageurl+"/buttons/button-background-green.gif) repeat scroll top left; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-statistic-button", styles);
  
  styles = ""
  +"width: 54px; \n"
  +"min-width: 54px; \n"
  +"height: 54px; \n"
  +"min-height: 54px; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-statisticcontent-button", styles);
  
  styles = ""
  +"margin-top: 9px; \n"
  +"text-align: center; \n"
  +"cursor: pointer; \n"
  +"font-size: 24px; \n"
  +"float: none; \n";
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles += "color: black; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles += "color: white; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles += "color: #555555; \n";
  } else {
    styles += "color: #FFFFFF; \n";
  }
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-statistic a", styles);
  
  styles = ""
  +"margin-top: 8px; \n"
  +"color: #FFFFFF; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-statistic-button a", styles);
  
  styles = ""
  +"text-align: center; \n"
  +"cursor: pointer; \n"
  +"font-size: 9px; \n"
  +"font-weight: bold; \n"
  +"float: none; \n"
  +"margin-top: 1px; \n";
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles += "color: black; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles += "color: white; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles += "color: #555555; \n";
  } else {
    styles += "color: #AAAAAA; \n";
  }
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-statistic span", styles);
  
  styles = ""
  +"color: #FFFFFF; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-statistic-button span", styles);
  
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles = "border: 1px solid white; \n";
    styles += "background-color: orange; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles = "border: 1px solid white; \n";
    styles += "background-color: #444444; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles = "border: 1px solid #DDDDDD; \n";
    styles += "background-color: #DDDDDD; \n";
  } else {
    styles = "border: 1px solid #222222; \n";
    styles += "background-color: #222222; \n";
  }
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-statistic:hover", styles);
  
  styles = "border: 2px solid white; \n";
  styles += "background: #71AA30 none repeat scroll top left; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-statistic-button:hover", styles);
  
  //this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-statistic + .polarrosedashboard-statistic", "margin-left: 5px; \n");
  
  // * * * * * mugshots
  
  styles = ""
  +"padding: 3px 0px; \n"
  +"cursor: pointer; \n"
  +"margin-top: 22px; \n"
  +"margin-left: 5px; \n"
  +"-moz-border-radius: 3px; \n"
  +"-khtml-border-radius: 3px; \n"
  +"-webkit-border-radius: 3px; \n"
  +"border-radius: 3px; \n";
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles += "border: 1px solid white; \n";
    styles += "background-color: yellow; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles += "border: 1px solid white; \n";
    styles += "background-color: #333333; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles += "border: 1px solid #CCCCCC; \n";
    styles += "background-color: #FFFFFF; \n";
    styles += "-moz-border-radius: 0px; \n"
    styles += "-khtml-border-radius: 0px; \n"
    styles += "-webkit-border-radius: 0px; \n"
    styles += "border-radius: 0px; \n";
  } else {
    styles += "border: 1px solid #FFFFFF; \n";
    styles += "background-color: #FFFFFF; \n";
    styles += "-moz-border-radius: 0px; \n"
    styles += "-khtml-border-radius: 0px; \n"
    styles += "-webkit-border-radius: 0px; \n"
    styles += "border-radius: 0px; \n";
  }
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-mugshot", styles);
  
  if (polarrose.config.theme && polarrose.config.theme === "fire") {
    styles = "border: 1px solid white; \n";
    styles += "background-color: orange; \n";
  } else if (polarrose.config.theme && polarrose.config.theme === "solli") {
    styles = "border: 1px solid white; \n";
    styles += "background-color: #444444; \n";
  } else if (polarrose.config.theme && (polarrose.config.theme === "light" || polarrose.config.theme === "bright")) {
    styles = "border: 1px solid #CCCCCC; \n";
    styles += "background-color: #BBBBBB; \n";
  } else {
    styles = "border: 1px solid #BBBBBB; \n";
    styles += "background-color: #BBBBBB; \n";
  }
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-mugshot:hover", styles);
  
  styles = ""
  +"cursor: pointer; \n"
  +"margin: 0px 3px; \n";
  this.addStyle(style, "div#polarrosedashboard .polarrosedashboard-module .polarrosedashboard-mugshot img", styles);

}

PolarRoseFrontendDashboard.prototype.addStyle = function(styleelement,selector,styles) {
  var stylestring = ("\n" + selector + " { \n" + styles + "}\n ");
  if (styleelement.styleSheet /*polarrose.isIE*/) { // IE?
    styleelement.styleSheet.cssText = styleelement.styleSheet.cssText + stylestring;
  } else {
    styleelement.appendChild(document.createTextNode(stylestring));
  }
}

PolarRoseFrontendDashboard.prototype.setStyle = function(element,stylestring) {
  var styles = stylestring.split(/[;]+[ ]*/);
  for (var i=0, leni=styles.length; i<leni; i++) {
    var s = styles[i].split(/[:]+(?!\/\/)[ ]*/);
    if (s.length === 2) {
      var what = s[0].toString();
      while (/-([a-z])/.test(what)) {
        what = what.replace(/-([a-z])/,RegExp.$1.toUpperCase());
      }
      var how = s[1].toString();
      if (what === "float") {
        element.style["cssFloat"] = how;
        element.style["styleFloat"] = how;
      } else {
        element.style[what] = how;
      }
    }
  }
}

PolarRoseFrontendDashboard.prototype.setDashboardVisibility = function(visible) {
  var polarrosedashboard = document.getElementById("polarrosedashboard");
  if (polarrosedashboard) {
    this.setStyle(polarrosedashboard, visible?"display:block; visibility:visible; ":"display:none; visibility:hidden; ");
  }
  var polarrosedashboardCatfish = document.getElementById("polarrosedashboard-catfish");
  if (polarrosedashboardCatfish) {
    this.setStyle(polarrosedashboardCatfish, visible?"display:block; visibility:visible; ":"display:none; visibility:hidden; ");
  }
}

//****************************************************************************************************

PolarRoseFrontendDashboard.prototype.addEvent = function(element,what,todo) {
  if (window.addEventListener) {
    element.addEventListener(what, todo, false);
  } else if (window.attachEvent) {
    element.attachEvent(('on'+what), todo);
  }
}

//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

function PolarRoseFrontendWidget() {
  this.collection = "";
  this.url = "";
  this.imageUrl = "";
  this.subscriptions = {};
  this.imageEvents = ["mouseover","mouseout","load"];
  this.areaEvents = ["mouseover","mouseout"];
  this.roseEvents = ["mouseover","mouseout","click"];
  this.documentEvents = ["click"];
  this.windowEvents = ["resize"];
}

//****************************************************************************************************

PolarRoseFrontendWidget.prototype.addFaces = function(img, faces) {
  if (faces && (faces.constructor === Array) && (faces.length > 0)
  && polarrose.backend.widget.validateImage(img) 
  && polarrose.backend.widget.validateImageSize(img.naturalWidth,img.naturalHeight)) {
    this.addImageEvents(img);
    for (var i=0; i<faces.length; i++) {
      var facebox = {
        "image":img,
        "map":this.getImageMap(img),
        "layout":this.getImageLayout(img),
        "face":{
          "id":(faces[i].id.toString()||''),
          "x":(parseInt(faces[i].x,10)||0),
          "y":(parseInt(faces[i].y,10)||0),
          "size":(parseInt(faces[i].size,10)||0),
          "angle":(parseInt(faces[i].angle,10)||0),
          "named":((faces[i].named===true||faces[i].named==="true")?true:false)
        },
        "name":null
      }
      this.addFacebox(facebox);
    }
  }
}

//****************************************************************************************************

PolarRoseFrontendWidget.prototype.addFacebox = function(rose) {
  
  polarrose.debug("Adding facebox: \n"+polarrose.format(rose));

  var facebox = document.createElement("a");
  if (this.collection) {
    facebox.setAttribute("href",(this.url + this.collection + "?named=false"));
  } else {
    facebox.setAttribute("href",(this.url + "/photo/" + rose.face.id));
  }
  facebox.setAttribute("target","_top");
  facebox.style.background = "transparent none repeat scroll top left";
  facebox.style.border = "0px solid transparent";
  facebox.style.clear = "none";
  facebox.style.cursor = "auto";
  facebox.style.display = "block";
  facebox.style.float = "left";
  facebox.style.position = "absolute";
  facebox.style.visibility = "visible";
  facebox.style.height = "auto";
  facebox.style.width = "auto";
  facebox.style.lineHeight = "normal";
  facebox.style.fontStyle = "normal";
  facebox.style.fontVariant = "normal";
  facebox.style.fontWeight = "bold";
  facebox.style.fontSize = "2px";
  facebox.style.fontFamily = "arial,helvetica,sans-serif";
  facebox.style.margin = "0px";
  facebox.style.outline = "transparent none 0px";
  facebox.style.padding = "0px";
  facebox.style.top = "auto";
  facebox.style.right = "auto";
  facebox.style.bottom = "auto";
  facebox.style.left = "auto";
  facebox.style.overflow = "visible";
  facebox.style.verticalAlign = "baseline";
  facebox.style.zIndex = "1510";
  facebox.style.color = "black";
  facebox.style.direction = "ltr";
  facebox.style.lineHeight = "normal";
  facebox.style.letterSpacing = "normal";
  facebox.style.textAlign = "left";
  facebox.style.textDecoration = "none";
  facebox.style.textIndent = "0";
  facebox.style.textShadow = "none";
  facebox.style.textTransform = "none";
  facebox.style.whiteSpace = "normal";
  facebox.style.wordSpacing = "normal";
  
  var faceboxname = document.createElement("span");
  faceboxname.style.background = "black none repeat scroll top left";
  faceboxname.style.border = "0px solid transparent";
  faceboxname.style.clear = "none";
  faceboxname.style.cursor = "pointer";
  faceboxname.style.display = "inline";
  faceboxname.style.float = "left";
  faceboxname.style.position = "absolute";
  faceboxname.style.visibility = "hidden";
  faceboxname.style.height = "auto";
  faceboxname.style.width = "auto";
  faceboxname.style.lineHeight = "normal";
  faceboxname.style.fontStyle = "normal";
  faceboxname.style.fontVariant = "normal";
  faceboxname.style.fontWeight = "bold";
  faceboxname.style.fontSize = "10px";
  faceboxname.style.fontFamily = "arial,helvetica,sans-serif";
  faceboxname.style.margin = "0px";
  faceboxname.style.outline = "transparent none 0px";
  faceboxname.style.padding = "3px 4px";
  faceboxname.style.top = "auto";
  faceboxname.style.right = "auto";
  faceboxname.style.bottom = "auto";
  faceboxname.style.left = "auto";
  faceboxname.style.overflow = "visible";
  faceboxname.style.verticalAlign = "baseline";
  //faceboxname.style.zIndex = "1510";
  faceboxname.style.color = "white";
  faceboxname.style.direction = "ltr";
  faceboxname.style.lineHeight = "normal";
  faceboxname.style.letterSpacing = "normal";
  faceboxname.style.textAlign = "left";
  faceboxname.style.textDecoration = "none";
  faceboxname.style.textIndent = "0";
  faceboxname.style.textShadow = "none";
  faceboxname.style.textTransform = "none";
  faceboxname.style.whiteSpace = "normal";
  faceboxname.style.wordSpacing = "normal";
  faceboxname.style.MozBorderRadius = "4px";
  faceboxname.style.KhtmlBorderRadius = "4px";
  faceboxname.style.WebkitBorderRadius = "4px";
  faceboxname.style.borderRadius = "4px";
  facebox.appendChild(faceboxname);
  
  var boxW = document.createElement("div");
  boxW.style.background = "transparent none repeat scroll top left";
  boxW.style.border = "2px solid white";
  boxW.style.clear = "none";
  boxW.style.cursor = "auto";
  boxW.style.display = "block";
  boxW.style.float = "left";
  boxW.style.position = "absolute";
  boxW.style.visibility = "visible";
  boxW.style.height = "auto";
  boxW.style.width = "auto";
  boxW.style.lineHeight = "normal";
  boxW.style.fontStyle = "normal";
  boxW.style.fontVariant = "normal";
  boxW.style.fontWeight = "bold";
  boxW.style.fontSize = "2px";
  boxW.style.fontFamily = "arial,helvetica,sans-serif";
  boxW.style.margin = "0px";
  boxW.style.outline = "transparent none 0px";
  boxW.style.padding = "0px";
  boxW.style.top = "auto";
  boxW.style.right = "auto";
  boxW.style.bottom = "auto";
  boxW.style.left = "auto";
  boxW.style.overflow = "visible";
  boxW.style.verticalAlign = "baseline";
  //boxW.style.zIndex = "1510";
  boxW.style.color = "black";
  boxW.style.direction = "ltr";
  boxW.style.lineHeight = "normal";
  boxW.style.letterSpacing = "normal";
  boxW.style.textAlign = "right";
  boxW.style.textDecoration = "none";
  boxW.style.textIndent = "0";
  boxW.style.textShadow = "none";
  boxW.style.textTransform = "none";
  boxW.style.whiteSpace = "normal";
  boxW.style.wordSpacing = "normal";
  
  var boxB = document.createElement("div");  
  boxB.style.background = "transparent none repeat scroll top left";
  boxB.style.border = "1px solid black";
  boxB.style.clear = "none";
  boxB.style.cursor = "auto";
  boxB.style.display = "block";
  boxB.style.float = "left";
  boxB.style.position = "absolute";
  boxB.style.visibility = "visible";
  boxB.style.height = "auto";
  boxB.style.width = "auto";
  boxB.style.lineHeight = "normal";
  boxB.style.fontStyle = "normal";
  boxB.style.fontVariant = "normal";
  boxB.style.fontWeight = "bold";
  boxB.style.fontSize = "2px";
  boxB.style.fontFamily = "arial,helvetica,sans-serif";
  boxB.style.margin = "0px";
  boxB.style.outline = "transparent none 0px";
  boxB.style.padding = "0px";
  boxB.style.top = "auto";
  boxB.style.right = "auto";
  boxB.style.bottom = "auto";
  boxB.style.left = "auto";
  boxB.style.overflow = "visible";
  boxB.style.verticalAlign = "baseline";
  //boxB.style.zIndex = "1510";
  boxB.style.color = "black";
  boxB.style.direction = "ltr";
  boxB.style.lineHeight = "normal";
  boxB.style.letterSpacing = "normal";
  boxB.style.textAlign = "right";
  boxB.style.textDecoration = "none";
  boxB.style.textIndent = "0";
  boxB.style.textShadow = "none";
  boxB.style.textTransform = "none";
  boxB.style.whiteSpace = "normal";
  boxB.style.wordSpacing = "normal";
  
  var boxT = document.createElement("div");  
  boxT.style.background = "transparent none repeat scroll top left";
  boxT.style.border = "0px solid transparent";
  boxT.style.clear = "none";
  boxT.style.cursor = "pointer";
  boxT.style.display = "block";
  boxT.style.float = "left";
  boxT.style.position = "absolute";
  boxT.style.visibility = "visible";
  boxT.style.height = "auto";
  boxT.style.width = "auto";
  boxT.style.lineHeight = "normal";
  boxT.style.fontStyle = "normal";
  boxT.style.fontVariant = "normal";
  boxT.style.fontWeight = "bold";
  boxT.style.fontSize = "2px";
  boxT.style.fontFamily = "arial,helvetica,sans-serif";
  boxT.style.margin = "0px";
  boxT.style.outline = "transparent none 0px";
  boxT.style.padding = "0px";
  boxT.style.top = "auto";
  boxT.style.right = "auto";
  boxT.style.bottom = "auto";
  boxT.style.left = "auto";
  boxT.style.overflow = "visible";
  boxT.style.verticalAlign = "baseline";
  //boxT.style.zIndex = "1510";
  boxT.style.color = "black";
  boxT.style.direction = "ltr";
  boxT.style.lineHeight = "normal";
  boxT.style.letterSpacing = "normal";
  boxT.style.textAlign = "right";
  boxT.style.textDecoration = "none";
  boxT.style.textIndent = "0";
  boxT.style.textShadow = "none";
  boxT.style.textTransform = "none";
  boxT.style.whiteSpace = "normal";
  boxT.style.wordSpacing = "normal";
  
  boxT.title = ""; // TODO ?
  
  if (polarrose.isIE) {
    boxW.style.filter = "alpha(opacity=40)";
    boxB.style.filter = "alpha(opacity=40)";
    boxT.style.backgroundColor = "white";
    boxT.style.filter = "alpha(opacity=1)";
  } else {
    boxW.style.opacity = "0.40";
    boxB.style.opacity = "0.40";
    boxT.style.backgroundColor = "transparent";
  }
  
  boxW.appendChild(boxB);
  facebox.appendChild(boxW);
  facebox.appendChild(boxT);
  
  // * * * * *
  
  rose.facebox = facebox;
  rose.faceboxname = faceboxname;
  rose.boxW = boxW;
  rose.boxB = boxB;
  rose.boxT = boxT;
  rose.isVisible = true;
  
  if (!this.validateRose(rose)) {
    // TODO: remove rose?
    this.remove(rose);
    return;
  }
  
  // * * * * *
  
  this.addRoseEvents(boxT);
  this.addRoseEvents(faceboxname);
  
  var onMessage = function(roseRef) {
    return function(message) {
      if (message && roseRef) {
        if (polarrose.frontend.widget.validateRose(roseRef)) {
          switch(message.what) {
            case "imagehover":
              if (roseRef.image===message.image || (roseRef.map && roseRef.map===message.map)) {
                if (!message.hover && message.to) {
                  if (/^a$/i.test(message.to.parentNode.nodeName) && message.to.parentNode.getAttribute("href").indexOf(polarrose.frontend.widget.url)===0) {
                    message.hover = true;
                  } else if (/^area$/i.test(message.to.nodeName) && message.to.parentNode===roseRef.map) {
                    message.hover = true;
                  }
                }
                if (message.hover && roseRef.isVisible && roseRef.layout.visible) {
                  roseRef.facebox.style.visibility = "visible";
                  roseRef.facebox.style.display = "block";
                } else {
                  roseRef.facebox.style.visibility = "hidden";
                  roseRef.facebox.style.display = "none";
                }
                // TODO: check if image is visible?
              }
              break;
            case "rosehover":
              if (roseRef.boxT/*roseImage*/ === message.roseImage || roseRef.faceboxname === message.roseImage) {
                if (message.hover) {
                  roseRef.boxW.style.border = "2px solid black";
                  roseRef.boxB.style.border = "1px solid white";
                  if (polarrose.isIE) {
                    roseRef.boxW.style.filter = "alpha(opacity=99)";
                    roseRef.boxB.style.filter = "alpha(opacity=99)";
                  } else {
                    roseRef.boxW.style.opacity = "0.99";
                    roseRef.boxB.style.opacity = "0.99";
                  }
                  roseRef.facebox.style.zIndex = "1511";
                } else {
                  roseRef.boxW.style.border = "2px solid white";
                  roseRef.boxB.style.border = "1px solid black";
                  if (polarrose.isIE) {
                    roseRef.boxW.style.filter = "alpha(opacity=40)";
                    roseRef.boxB.style.filter = "alpha(opacity=40)";
                  } else {
                    roseRef.boxW.style.opacity = "0.40";
                    roseRef.boxB.style.opacity = "0.40";
                  }
                  roseRef.facebox.style.zIndex = "1510";
                  if (polarrose.config.hover) {
                    polarrose.frontend.widget.publish({"what":"imagehover", "image":roseRef.image, "hover":false, "to":message.to});
                  }
                }
              }
              break;
            case "roseplace":
              if (true /*!(message.roseImage && roseRef.roseImage !== message.roseImage)*/) {
                var layout = polarrose.frontend.widget.getImageLayout(roseRef.image);
                if (!polarrose.frontend.widget.isImageLayoutsEqual(layout,roseRef.layout)) {
                  if (!layout) {
                    polarrose.frontend.widget.remove(roseRef);
                  } else if (layout.src !== roseRef.layout.src) {
                    polarrose.frontend.widget.remove(roseRef);
                    // TODO: submit image for processing
                    // make sure that the image is loaded?
                    polarrose.backend.widget.submitImages(document, roseRef.image);
                  } else {
                    roseRef.layout = layout;
                    polarrose.frontend.widget.place(roseRef);
                  }
                }
              }
              break;
            case "rosevisibility":
              polarrose.frontend.widget.place(roseRef);
              break;
            case "roseremove":
              if (true /*!(message.roseImage && roseRef.roseImage !== message.roseImage)*/) {
                polarrose.frontend.widget.remove(roseRef);
              }
              break;
            default:
              //
          }
        } else {
          polarrose.frontend.widget.remove(roseRef);
        }
      }
    };
  }(rose);
  rose.subscribeId = this.subscribe(onMessage);
  
  document.body.appendChild(facebox);
  
  this.place(rose);
  
  // * * * * *
  
  if (rose.face.named) { // TODO ?
    var requestId = polarrose.backend.getRequestId();
    var jsonpcallback = function(requestIdRef, roseRef) {
      return function(json) {
        polarrose.debug("Response ("+requestIdRef+"): \n"+polarrose.format(json));
        if (json) {
          if (json[roseRef.face.id]) { // named
            roseRef.faceboxname.appendChild(document.createTextNode( json[roseRef.face.id].replace(/ /g,"\u00a0")));
            roseRef.facebox.style.visibility = "visible";
            roseRef.facebox.style.display = "block";
            roseRef.faceboxname.style.visibility = "visible";
            var faceboxnamewidth = (roseRef.faceboxname.clientWidth || roseRef.faceboxname.offsetWidth || 0);
            roseRef.name = json[roseRef.face.id];
            polarrose.frontend.widget.place(roseRef, faceboxnamewidth);
            if (polarrose.frontend.widget.collection) {
              var url = (polarrose.frontend.widget.url + polarrose.frontend.widget.collection);
              url += ("?name="+(encodeURIComponent(roseRef.name.replace(/[<>&"]/gi," ")).replace(/(%20)+/g,"+")));
              roseRef.facebox.setAttribute("href",url);
            }
          }
        }
        polarrose.backend.removeScript(requestIdRef);
        polarrose.backend.removeCallback(requestIdRef);
      };
    } (requestId, rose);
    polarrose.backend.addCallback(requestId, jsonpcallback);
    var scriptSrc = (this.url + "/namefor/" + rose.face.id + "?callback=polarrosewidget.callback" + requestId);
    polarrose.backend.addScript(requestId, scriptSrc);
  }
}

//****************************************************************************************************

PolarRoseFrontendWidget.prototype.validateRose = function(rose) {
  if (!rose || !rose.image) return false;
  if (!rose.layout) rose.layout = this.getImageLayout(rose.image);
  if (!rose.layout || !rose.face || !rose.facebox) return false;
  return true;
}

//****************************************************************************************************

PolarRoseFrontendWidget.prototype.place = function(rose, faceboxnamewidth) {
  if (!this.validateRose(rose)) {
    this.remove(rose); // TODO ?
    return;
  }

  var imgX = 1*rose.layout.x; // Left image edge location.
  var imgY = 1*rose.layout.y; // Top image edge location.
  var imgWidth = 1*rose.layout.width;   // Image width.
  var imgHeight = 1*rose.layout.height; // Image height.
  var imgXScale = 1.0*(imgWidth/(1*(rose.image.naturalWidth||1)));   // Horizontal image scale.
  var imgYScale = 1.0*(imgHeight/(1*(rose.image.naturalHeight||1))); // Vertical image scale.
  
  // Center position and scale for face.
  var faceX = imgX + Math.round(imgXScale*rose.face.x);
  var faceY = imgY + Math.round(imgYScale*rose.face.y);
  var size = Math.floor((imgXScale+imgYScale)/2.0*rose.face.size);
  
  if ((faceX < rose.layout.innerX)
  || (faceY < rose.layout.innerY)
  || (faceX >= (rose.layout.innerX + rose.layout.innerWidth))
  || (faceY > (rose.layout.innerY + rose.layout.innerHeight))
  || !polarrose.config.widgetvisibility
  || (size<7 && !rose.name)
  || (size<4)) {
    rose.isVisible = false;
  } else {
    rose.isVisible = true;
  }
  
  if (polarrose.config.hover || !rose.layout.visible || !rose.isVisible) {
    rose.facebox.style.visibility = "hidden";
    rose.facebox.style.display = "none";
  } else {
    rose.facebox.style.visibility = "visible";
    rose.facebox.style.display = "block";
  }
  
  var boxX = faceX-size      -parseInt((size*0.25),10);
  var boxY = faceY-size      -parseInt((size*0.25),10);
  var boxSize = size+size+1  +parseInt((size*0.5),10);
  
  rose.facebox.style.left = (boxX) + "px";
  rose.facebox.style.top = (boxY) + "px";
  rose.facebox.style.width = (boxSize) + "px";
  rose.facebox.style.height = (boxSize) + "px";
  
  rose.faceboxname.style.top = (boxSize + 5) + "px";
  if (faceboxnamewidth) {
    rose.faceboxname.style.left = parseInt((boxSize-faceboxnamewidth)*0.5, 10) + "px";
  }
  
  rose.boxT.style.left = (0) + "px";
  rose.boxT.style.top = (0) + "px";
  rose.boxT.style.width = (boxSize) + "px";
  rose.boxT.style.height = (boxSize) + "px";
  
  rose.boxW.style.left = (0) + "px";
  rose.boxW.style.top = (0) + "px";
  //rose.boxW.style.right = "0px";
  //rose.boxW.style.bottom = "0px";
  rose.boxW.style.width = Math.max((boxSize-4),0) + "px";
  rose.boxW.style.height = Math.max((boxSize-4),0) + "px";
  
  rose.boxB.style.left = (0) + "px";
  rose.boxB.style.top = (0) + "px";
  //rose.boxB.style.right = "0px";
  //rose.boxB.style.bottom = "0px";
  rose.boxB.style.width = Math.max((boxSize-4-2),0) + "px";
  rose.boxB.style.height = Math.max((boxSize-4-2),0) + "px";
  
  if (polarrose.isIE && document.compatMode && document.compatMode==="BackCompat") {
    rose.boxW.style.width = (boxSize) + "px";
    rose.boxW.style.height = (boxSize) + "px";
    rose.boxB.style.width = Math.max((boxSize-4),0) + "px";
    rose.boxB.style.height = Math.max((boxSize-4),0) + "px";
  }
}

//****************************************************************************************************

PolarRoseFrontendWidget.prototype.remove = function(rose) {
  if (rose && !rose.removed) {
    this.unsubscribe(rose.subscribeId);
    rose.isVisible = false;
    rose.layout = null;
    rose.face = null;
    // image ?
    // map ?
    // rose events ?
    if (rose.facebox && rose.facebox.parentNode) {
      rose.facebox.parentNode.removeChild(rose.facebox);
      rose.facebox = null;
    }
    if (rose.faceboxname && rose.faceboxname.parentNode) {
      rose.faceboxname.parentNode.removeChild(rose.faceboxname);
    }
    rose.removed = true;
  }
}

//****************************************************************************************************

PolarRoseFrontendWidget.prototype.subscribe = function(func) {
  if (func) {
    this.subscribeId = ((this.subscribeId+1) || 1);
    var id = "polarrose" + this.subscribeId.toString(10);
    this.subscriptions[id] = func;
    return id;
  }
  return null;
}

PolarRoseFrontendWidget.prototype.unsubscribe = function(id) {
  if (id && this.subscriptions[id]) {
    this.subscriptions[id] = null;
    delete this.subscriptions[id];
  }
}

PolarRoseFrontendWidget.prototype.publish = function(message) {
  if (message) {
    for (var i in this.subscriptions) {
      if (/^polarrose[0-9]+$/.test(i)) {
        this.subscriptions[i](message);
      }
    }
  }
}

//****************************************************************************************************

PolarRoseFrontendWidget.prototype.addImageEvents = function(img) {
  this.removeImageEvents(img);
  this.addEvents(img, this.imageEvents, this.onImageEvent);
  this.addAreaEvents(img);
};

PolarRoseFrontendWidget.prototype.removeImageEvents = function(img) {
  this.removeEvents(img, this.imageEvents, this.onImageEvent);
  this.removeAreaEvents(img);
};

PolarRoseFrontendWidget.prototype.addAreaEvents = function(img) {
  if (img.useMap) {
    var id = img.useMap.replace("#","");
    var maps = document.getElementsByTagName("map");
    for (var i=0; i<maps.length; i++) {
      if (id && (maps[i].id===id || maps[i].name===id)) {
        var areas = maps[i].getElementsByTagName("area");
        for (var j=0; j<areas.length; j++) {
          this.addEvents(areas[j], this.areaEvents, this.onAreaEvent);
        }
      }
    }
  }
};

PolarRoseFrontendWidget.prototype.removeAreaEvents = function(img) {
  if (img.useMap) {
    var id = img.useMap.replace("#","");
    var maps = document.getElementsByTagName("map");
    for (var i=0; i<maps.length; i++) {
      if (id && (maps[i].id===id || maps[i].name===id)) {
        var areas = maps[i].getElementsByTagName("area");
        for (var j=0; j<areas.length; j++) {
          this.removeEvents(areas[j], this.areaEvents, this.onAreaEvent);
        }
      }
    }
  }
};

PolarRoseFrontendWidget.prototype.addRoseEvents = function(roseimg) {
  this.removeRoseEvents(roseimg);
  this.addEvents(roseimg, this.roseEvents, this.onRoseEvent);
};

PolarRoseFrontendWidget.prototype.removeRoseEvents = function(roseimg) {
  this.removeEvents(roseimg, this.roseEvents, this.onRoseEvent);
};

PolarRoseFrontendWidget.prototype.addDocumentEvents = function(doc) {
  this.removeDocumentEvents(doc);
  this.addEvents(doc, this.documentEvents, this.onDocumentEvent);
};

PolarRoseFrontendWidget.prototype.removeDocumentEvents = function(doc) {
  this.removeEvents(doc, this.documentEvents, this.onDocumentEvent);
};

PolarRoseFrontendWidget.prototype.addWindowEvents = function(win) {
  this.removeWindowEvents(win);
  this.addEvents(win, this.windowEvents, this.onWindowEvent);
};

PolarRoseFrontendWidget.prototype.removeWindowEvents = function(win) {
  this.removeEvents(win, this.windowEvents, this.onWindowEvent);
};

PolarRoseFrontendWidget.prototype.addEvents = function(element, types, handler) {
  for (var i in types) {
    if (element.addEventListener) element.addEventListener(types[i], handler, false);
    else if (element.attachEvent) element.attachEvent("on"+types[i], handler);
  }
};

PolarRoseFrontendWidget.prototype.removeEvents = function(element, types, handler) {
  for (var i in types) {
    if (element.removeEventListener) element.removeEventListener(types[i], handler, false);
    else if (element.detachEvent) element.detachEvent("on"+types[i], handler);
  }
};

//****************************************************************************************************

PolarRoseFrontendWidget.prototype.onImageEvent = function(e) {
  if (!e) var e = window.event;
  var t = e.target || e.srcElement;
  if (polarrose.config.hover) {
    switch (e.type) {
      case "mouseover":
        polarrose.frontend.widget.publish({"what":"imagehover", "image":t, "hover":true, "from":(e.relatedTarget||e.fromElement)});
        break;
      case "mouseout":
        polarrose.frontend.widget.publish({"what":"imagehover", "image":t, "hover":false, "to":(e.relatedTarget||e.toElement)});
        break;
    }
  }
  switch (e.type) {
    case "load":
      // TODO? remove roses and submit image?
      polarrose.frontend.widget.rePlaceRosesDelayed(); // TODO ?
      break;
  }
};

PolarRoseFrontendWidget.prototype.onAreaEvent = function(e) {
  if (!e) var e = window.event;
  var t = e.target || e.srcElement;
  var map = t.parentNode;
  if (polarrose.config.hover && map) {
    switch (e.type) {
      case "mouseover":
        polarrose.frontend.widget.publish({"what":"imagehover", "map":map, "hover":true, "from":(e.relatedTarget||e.fromElement)});
        break;
      case "mouseout":
        polarrose.frontend.widget.publish({"what":"imagehover", "map":map, "hover":false, "to":(e.relatedTarget||e.toElement)});
        break;
    }
  }
};

PolarRoseFrontendWidget.prototype.onRoseEvent = function(e) {
  if (!e) var e = window.event;
  var t = e.target || e.srcElement;
  switch (e.type) {
    case "mouseover":
      polarrose.frontend.widget.publish({"what":"rosehover", "roseImage":t, "hover":true, "from":(e.relatedTarget||e.fromElement)});
      break;
    case "mouseout":
      polarrose.frontend.widget.publish({"what":"rosehover", "roseImage":t, "hover":false, "to":(e.relatedTarget||e.toElement)});
      break;
    case "click":
      e.cancelBubble = true;
	    if (e.stopPropagation) e.stopPropagation();
      break;
  }
};

PolarRoseFrontendWidget.prototype.onDocumentEvent = function(e) {
  if (!e) var e = window.event;
  //var t = e.target || e.srcElement;
  switch (e.type) {
    case "click":
      polarrose.frontend.widget.rePlaceRosesDelayed(); // TODO ?
      break;
  }
};

PolarRoseFrontendWidget.prototype.onWindowEvent = function(e) {
  if (!e) var e = window.event;
  //var t = e.target || e.srcElement;
  switch (e.type) {
    case "resize":
      polarrose.frontend.widget.rePlaceRosesDelayed();
      break;
  }
};

//****************************************************************************************************

PolarRoseFrontendWidget.prototype.rePlaceRosesDelayed = function() {
  if (this.rePlaceTimer) clearTimeout(this.rePlaceTimer);
  this.rePlaceTimer = setTimeout(this.rePlaceRoses, 333);
}

PolarRoseFrontendWidget.prototype.rePlaceRoses = function() {
  polarrose.frontend.widget.publish({"what":"roseplace"});
}

//****************************************************************************************************

PolarRoseFrontendWidget.prototype.getImageMap = function(img) {
  if (img.useMap) {
    var id = img.useMap.replace("#","");
    var maps = document.getElementsByTagName("map");
    for (var i=0; i<maps.length; i++) {
      if (id && (maps[i].id===id || maps[i].name===id)) {
        return maps[i];
      }
    }
  }
  return null;
}

//****************************************************************************************************

PolarRoseFrontendWidget.prototype.getImageLayout = function(img) {

  if (!img || !/^img$/i.test(img.nodeName)) {
    // TODO ?
    return null;
  }
  
  var layout = {
    "x":img.offsetLeft,
    "y":img.offsetTop,
    "width":img.clientWidth,
    "height":img.clientHeight,
    "visible":true,
    "src":img.src
  };
  
  if (!layout.x && !layout.y && (!layout.width || !layout.height)) {
    // TODO ?
    return null;
  }
  
  var imgs = null;
  try {
    imgs = img.currentStyle || document.defaultView.getComputedStyle(img,null);
  } catch(e){};
  
  if (imgs) {
    if (polarrose.isIE) {
      layout.x += (parseInt(imgs.borderLeftWidth)||0);
      layout.y += (parseInt(imgs.borderTopWidth)||0);
    } else if (polarrose.isFF) {
      layout.x += (parseInt(imgs.borderLeftWidth)||0);
      layout.x += (parseInt(imgs.paddingLeft)||0);
      layout.y += (parseInt(imgs.borderTopWidth)||0);
      layout.y += (parseInt(imgs.paddingTop)||0);
      layout.width -=  (parseInt(imgs.paddingLeft)||0);
      layout.width -=  (parseInt(imgs.paddingRight)||0);
      layout.height -= (parseInt(imgs.paddingTop)||0);
      layout.height -= (parseInt(imgs.paddingBottom)||0);
    } else if (polarrose.isSafari) {
      layout.x += (parseInt(imgs.borderLeftWidth)||0);
      layout.y += (parseInt(imgs.borderTopWidth)||0);
    }
    if (imgs.display==="none" || imgs.visibility==="hidden") {
      layout.visible = false;
    }
  }
  
  var cutOffLeft = 0;
  var cutOffRight = 0;
  var cutOffTop = 0;
  var cutOffBottom = 0;
      
  var p = img.parentNode;
  var op = img.offsetParent;

  while (op && p && !/^body|html$/i.test(p.nodeName)) {
    
    var s = null;
    try {
      s = p.currentStyle || document.defaultView.getComputedStyle(p,null);
    } catch(e){};
    
    if (op === p) {
      layout.x += op.offsetLeft;
      layout.y += op.offsetTop;
      //if (s && !/^t(able|d|h)$/i.test(p.nodeName)) {
      if (s && ((polarrose.isMozilla && !/^t(able|d|h)$/i.test(p.nodeName)) || (polarrose.isSafari>2))) {
        layout.x += (parseInt(s.borderLeftWidth, 10) || 0);
        layout.y += (parseInt(s.borderTopWidth, 10) || 0);
      }
      op = op.offsetParent;
    }
    
    if (!(s && s.overflow === "visible")) {
      
      //var w = p.clientWidth || p.offsetWidth || 0;
      var w = Math.max(p.clientWidth||0, p.offsetWidth||0);
      if (p.scrollWidth > w) {
        layout.x -= p.scrollLeft;
        var col = (layout.x-p.offsetLeft);
        var cor = ((p.offsetLeft+w)-(layout.x+layout.width));
        if (col < cutOffLeft) {
          cutOffLeft = col;
        }
        if (cor < cutOffRight) {
          cutOffRight = cor;
        }
        // TODO this.addScrollListener(p);
      }
      
      //var h = p.clientHeight || p.offsetHeight || 0;
      var h = Math.max(p.clientHeight||0, p.offsetHeight||0);
      if (p.scrollHeight > h) {
        layout.y -= p.scrollTop;
        var cot = (layout.y-p.offsetTop);
        var cob = ((p.offsetTop+h)-(layout.y+layout.height));
        if (cot < cutOffTop) {
          cutOffTop = cot;
        }
        if (cob < cutOffBottom) {
          cutOffBottom = cob;
        }
        // TODO this.addScrollListener(p);
      }
      
      if (s) { // overflow !== "visible"
        layout.x += (parseInt(s.borderLeftWidth, 10) || 0);
        layout.y += (parseInt(s.borderTopWidth, 10) || 0);
      }
    
    }

    p = p.parentNode;
  }
  
  // When the body element has a max-width. Like on twitxr.com.
  if (polarrose.isIE && /^body|html$/i.test(p.nodeName) && imgs && (imgs.position==="static")) {
    layout.x += (p.offsetLeft || 0);
    layout.y += (p.offsetTop || 0);
  }
  
  layout.innerX = layout.x - cutOffLeft;
  layout.innerY = layout.y - cutOffTop;
  layout.innerWidth = layout.width + cutOffLeft + cutOffRight;
  layout.innerHeight = layout.height + cutOffTop + cutOffBottom;
  
  if (layout.innerWidth <= 0) {
    layout.innerWidth = 0;
    layout.visible = false;
  }
  if (layout.innerHeight <= 0) {
    layout.innerHeight = 0;
    layout.visible = false;
  }
  
  return layout;
}

//****************************************************************************************************

PolarRoseFrontendWidget.prototype.isImageLayoutsEqual = function(layout1,layout2) {
  if (!layout1 || !layout2) return false;
  try {
    for (var i in layout1) {
      if (layout1[i] !== layout2[i]) return false;
    }
  } catch(e) {
    return false;
  }
  return true;
}

//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

function PolarRoseBackend() {
  this.dashboard = new PolarRoseBackendDashboard();
  this.widget = new PolarRoseBackendWidget();
  this.callbacks = {};
  this.callbackscounter = 0;
}

PolarRoseBackend.prototype.encodeUrl = function(url) {
  if (!url) var url = "";
  url = (""+url);
  return (encodeURI(decodeURIComponent(url)).replace(/\?/g,"%3F").replace(/=/g,"%3D").replace(/&/g,"%26").replace(/#/g,"%23").replace(/'/g,"%27").replace(/\+/g,"%2B"));
}

PolarRoseBackend.prototype.cleaneUrl = function(url) {
  try {
    if (url && polarrose.config.urlcleaner && eval("typeof("+polarrose.config.urlcleaner+")")==="function") {
      url = eval(polarrose.config.urlcleaner+"('"+decodeURIComponent(url)+"')").toString() || url;
    }
  } catch(e){};
  return url;
}

PolarRoseBackend.prototype.getRequestId = function() {
  return ((++this.callbackscounter).toString() + "0" + (Math.floor(Math.random()*100000000)));
}

PolarRoseBackend.prototype.addScript = function(requestId, scriptSrc) {
  if (requestId && scriptSrc) {
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.setAttribute('type','text/javascript');
    script.setAttribute('id',('polarrosewidgetrequest'+requestId));
    script.setAttribute('src',scriptSrc);
    polarrose.debug("GET script request ("+requestId+"): \n"+scriptSrc);
    head.appendChild(script);
  }
}

PolarRoseBackend.prototype.removeScript = function(requestId) {
  var script = document.getElementById("polarrosewidgetrequest"+requestId);
  if (script && script.parentNode) {
    script.parentNode.removeChild(script);
  }
}

PolarRoseBackend.prototype.addCallback = function(requestId, callbackfunction) {
  this.callbacks["jsonp"+requestId] = callbackfunction;
  window.polarrosewidget["callback"+requestId] = function(requestIdRef) {
    return function(json) {
      polarrose.backend.callbacks["jsonp"+requestIdRef](json);
    };
  } (requestId);
}

PolarRoseBackend.prototype.removeCallback = function(requestId) {
  window.polarrosewidget["callback"+requestId] = function(){};
  this.callbacks["jsonp"+requestId] = function(){};
}

//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

function PolarRoseBackendDashboard() {
  this.url = "";
}

PolarRoseBackendDashboard.prototype.submitPage = function(doc) {
  if (this.validatePage(doc)) {
    this.getRssFeed(doc.location.href);
  }
}

PolarRoseBackendDashboard.prototype.validatePage = function(doc) {
  if (!doc) return false;
  if (doc.nodeName !== "#document") return false;
  if (doc.location.href.indexOf("http://") !== 0) return false;
  if (doc.location.href.match(/(.+)polarrose\.(net|com|org)/)) return false;
  return true;
}

PolarRoseBackendDashboard.prototype.getRssFeed = function(docUrl) {
  if (polarrose.config.rss) {
    this.createRequest(docUrl,polarrose.config.rss);
  }
}

PolarRoseBackendDashboard.prototype.createRequest = function(docUrl, rssFeedUrl) {
  var request = {
    "Version":"2008-09-11",
    "Action":"SubmitRssFeed",
    "Partner":polarrose.backend.encodeUrl(polarrose.config.partner),
    "JsonCallback":"polarrosewidget.callback",
    "Webpage":polarrose.backend.encodeUrl(polarrose.backend.cleaneUrl(docUrl)),
    "RssFeed":polarrose.backend.encodeUrl(rssFeedUrl),
    "ClientVersion":("db"+polarrose.version)
  };
  if (!request.Partner || !request.Webpage || !request.RssFeed) {
    polarrose.debug("ERROR in request: \n"+polarrose.format(request));
    return;
  }
  this.sendRequest(request);
}

PolarRoseBackendDashboard.prototype.sendRequest = function(request) {
  var requestId = polarrose.backend.getRequestId();
  polarrose.debug("Request ("+requestId+"): \n"+polarrose.format(request));
  var jsonpcallback = function(requestIdRef, requestRef) {
    return function(json) {
      polarrose.debug("Response ("+requestIdRef+"): \n"+polarrose.format(json));
      if (json && json.response && (json.response.constructor === Object)) {
        polarrose.frontend.dashboard.validateDashboard(json.response);
      } else if (json && json.errors && (json.errors.constructor === Array)) {
        for (var i=0; i<json.errors.length; i++) {
          polarrose.debug("- error("+requestIdRef+","+i+") code: "+json.errors[i].code);
          polarrose.debug("- error("+requestIdRef+","+i+") description: "+json.errors[i].description);
        }
      }
      polarrose.backend.removeScript(requestIdRef);
      polarrose.backend.removeCallback(requestIdRef);
    };
  } (requestId, request);
  polarrose.backend.addCallback(requestId, jsonpcallback);
  var scriptSrc = (this.url + "?");
  scriptSrc += ("Version=" + request.Version);
  scriptSrc += ("&Action=" + request.Action);
  scriptSrc += ("&Partner=" + request.Partner);
  scriptSrc += ("&JsonCallback=" + request.JsonCallback + requestId);
  scriptSrc += ("&Webpage=" + request.Webpage);
  scriptSrc += ("&RssFeed=" + request.RssFeed);
  scriptSrc += ("&ClientVersion=" + request.ClientVersion);
  polarrose.backend.addScript(requestId, scriptSrc);
}

//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

function PolarRoseBackendWidget() {
  this.url = "";
}

PolarRoseBackendWidget.prototype.submitPage = function(doc) {
  if (this.validatePage(doc)) {
    this.submitImages(doc);
  }
}

PolarRoseBackendWidget.prototype.validatePage = function(doc) {
  if (!doc) return false;
  if (doc.nodeName !== "#document") return false;
  if (doc.location.href.indexOf("http://") !== 0) return false;
  if (doc.location.href.match(/(.+)polarrose\.(net|com|org)/)) return false;
  return true;
}

PolarRoseBackendWidget.prototype.submitImages = function(doc, img) {
  if (img) {
    if (this.validateImage(img)) {
      this.getImageSize(doc.location.href, img);
    }
  } else {
    for (var i=0, leni=doc.images.length; i<leni; i++) {
      if (this.validateImage(doc.images[i])) {
        this.getImageSize(doc.location.href, doc.images[i]);
      }
    }
  }
}

PolarRoseBackendWidget.prototype.validateImage = function(img) {
  if (!img.complete) return false;
  if (!img.src) return false;
  if (img.src.indexOf("http://") !== 0) return false;
  if (img.src.match(/(.+)polarrose\.(net|com|org)/)) return false;
  if (polarrose.config.optin) {
    if (img.className.indexOf(polarrose.config.optin) >= 0) {
      if (img.className === polarrose.config.optin) {
        return true;
      }
      var classes = img.className.split(" ");
      for (var i in classes){
        if (classes[i] === polarrose.config.optin) {
          return true;
        }
      }
    }
    return false;
  }
  return true;
}

PolarRoseBackendWidget.prototype.getImageSize = function(docurl, img) {
  if (img.naturalWidth && img.naturalHeight) {
    if (this.validateImageSize(img.naturalWidth, img.naturalHeight)) {
      this.getImageETag(docurl, img, img.naturalWidth, img.naturalHeight);
    }
  } else {
    var tempImage = new Image();
    var onTempImageLoad = function(thisRef, docurlRef, imgRef, tempImageRef) {
      return function(e) {
        if (!imgRef.naturalWidth && tempImageRef.width) imgRef.naturalWidth = tempImageRef.width;
        if (!imgRef.naturalHeight && tempImageRef.height) imgRef.naturalHeight = tempImageRef.height;
        if (thisRef.validateImageSize(tempImageRef.width, tempImageRef.height)) {
          thisRef.getImageETag(docurlRef, imgRef, tempImageRef.width, tempImageRef.height);
        }
      };
    } (this, docurl, img, tempImage);
    if (document.addEventListener) {
      tempImage.addEventListener('load', onTempImageLoad, false);
    } else if (document.attachEvent) {
      tempImage.attachEvent('onload', onTempImageLoad, false);
    }
    tempImage.src = img.src;
  }
}

PolarRoseBackendWidget.prototype.validateImageSize = function(width, height) {
  if (!width || !height || width <= 32 || height <= 32
    || (width===392 && height===72) 
    || (width===468 && height===60) 
    || (width===234 && height===60) 
    || (width===728 && height===90)) {
    return false;
  }
  return true;
}

PolarRoseBackendWidget.prototype.getImageETag = function(docurl, img, width, height) {
  if (false/* TODO img.etag*/) {
    this.createRequest(docurl,img,width,height,img.etag);
  } else if (false/* TODO this.isDomainsTheSame(docurl,img.src)*/) {
    try {
      var req = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
      req.onreadystatechange = function(reqRef,thisRef,docurlRef,imgRef,widthRef,heightRef) {
        return function() {
          try {
            if (reqRef.readyState === 4) {
              var etag = null;
              if (reqRef.status === 200 && reqRef.getResponseHeader("etag")) {
                etag = reqRef.getResponseHeader("etag");
                imgRef.etag = etag;
              }
              thisRef.createRequest(docurlRef,imgRef,widthRef,heightRef,etag);
            }
          } catch(err) {
            thisRef.createRequest(docurlRef,imgRef,widthRef,heightRef,null);
          }
        };
      } (req,this,docurl,img,width,height);
      req.open("HEAD", img.src, true);
      req.send(null);
    } catch(err) {
      this.createRequest(docurl,img,width,height,null);
    }
  } else {
    this.createRequest(docurl,img,width,height,null);
  }
}

/*PolarRoseBackendWidget.prototype.isDomainsTheSame = function(url1, url2) {
  if (!url1 || !url2) return false;
  var domain1 = url1.substring(0,url1.indexOf("/",url1.indexOf("://")+3));
  var domain2 = url2.substring(0,url2.indexOf("/",url2.indexOf("://")+3));
  if (domain1 && domain2 && (domain1===domain2)) return true;
  else return false;
}*/

PolarRoseBackendWidget.prototype.createRequest = function(docurl, img, width, height, etag) {
  var request = {
    "Version":"2008-03-14",
    "Action":"SubmitImages",
    "Partner":polarrose.backend.encodeUrl(polarrose.config.partner),
    "Page":polarrose.backend.encodeUrl(polarrose.backend.cleaneUrl(docurl)),
    "JsonCallback":"polarrosewidget.callback",
    "Images":[{
      "Url":polarrose.backend.encodeUrl(polarrose.backend.cleaneUrl(img.src)),
      "ETag":(etag?polarrose.backend.encodeUrl(etag):null),
      "Width":(width?polarrose.backend.encodeUrl(width):null),
      "Height":(height?polarrose.backend.encodeUrl(height):null)
    }],
    "clientpluginversion":("wi"+polarrose.version)
  };
  this.sendRequest(request, img);
}

PolarRoseBackendWidget.prototype.sendRequest = function(request, img) {
  var requestId = polarrose.backend.getRequestId();
  polarrose.debug("Request ("+requestId+"): \n"+polarrose.format(request));
  var jsonpcallback = function(requestIdRef, /*requestRef,*/ imgRef) {
    return function(json) {
      polarrose.debug("Response ("+requestIdRef+"): \n"+polarrose.format(json));
      if (imgRef && json && json.response && (json.response.constructor === Array)) {
        for (var i=0; i<json.response.length; i++) {
          if (json.response[i]) {
            polarrose.frontend.widget.addFaces(imgRef, json.response[i].faces);
          } else {
            // TODO: reload?
          }
        }
      } else if (json && json.errors && (json.errors.constructor === Array)) {
        for (var i=0; i<json.errors.length; i++) {
          polarrose.debug("- error("+requestIdRef+","+i+") code: "+json.errors[i].code);
          polarrose.debug("- error("+requestIdRef+","+i+") description: "+json.errors[i].description);
        }
      }
      polarrose.backend.removeScript(requestIdRef);
      polarrose.backend.removeCallback(requestIdRef);
    };
  } (requestId, /*request,*/ img);
  polarrose.backend.addCallback(requestId, jsonpcallback);
  var scriptSrc = (this.url + "?");
  scriptSrc += ("Version=" + request.Version);
  scriptSrc += ("&Action=" + request.Action);
  if (request.Reload) {
    scriptSrc += ("&Reload=" + request.Reload);
  }
  if (request.Partner) {
    scriptSrc += ("&Partner=" + request.Partner);
  }
  scriptSrc += ("&Page=" + request.Page);
  scriptSrc += ("&JsonCallback=" + request.JsonCallback + requestId);
  for (var i=0; i<request.Images.length; i++) {
    var scriptSrcImage = ("&ImageUrl."+i+"=" + request.Images[i].Url);
    if (request.Images[i].ETag) {
      scriptSrcImage += ("&ImageETag."+i+"=" + request.Images[i].ETag);
    }    
    if (request.Images[i].Width && request.Images[i].Height) {
      scriptSrcImage += ("&ImageWidth."+i+"=" + request.Images[i].Width);
      scriptSrcImage += ("&ImageHeight."+i+"=" + request.Images[i].Height);
    }
    scriptSrc += scriptSrcImage;
  }
  scriptSrc += ("&clientpluginversion=" + request.clientpluginversion);
  polarrose.backend.addScript(requestId, scriptSrc);
}

//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

var polarrose = {
  version: "0.10.0",
  loaded: false,
  initialized: false,
  config: {
    partner:"",
    optin:"",
    hover:true,
    urlcleaner:"",
    widgetvisibility:true, // TODO
    debug:false,
    rss:"",
    owner:true,
    theme:"", // dark, light
    css:true,
    insert:"",
    layout:"horizontal", // horizontal, vertical
    progress:false, // true, false
    toppeoplesize:0, // 3,4,5 (default:5)
    dashboardvisibility:true // TODO
  },
  
  debuglog: new Array((new Date()).toUTCString()),
  debugprint: 0,
  debug: function(message) {
    this.debuglog.push(""+message);
    if (this.config.debug && window.console && window.console.debug) {
      for (var i=this.debugprint, leni=this.debuglog.length; i<leni; i++) {
        window.console.debug(""+this.debuglog[i]);
      }
      this.debugprint = this.debuglog.length;
    }
  },
  format: function(o, indent) {
    if (!o) return "null";
    if (!indent) var indent = "";
    if (o.constructor===Object || o.constructor===Array) {
      var temp = new Array();
      for (var i in o) {
        var a = ((o.constructor===Object)?(i+": "):(""));
        switch (typeof o[i]) {
        case 'object':
          temp.push(a+arguments.callee(o[i], indent+"   "));
          break;
        case 'boolean':
        case 'number':
          temp.push(a+o[i]);
          break;
        case 'string':
          temp.push(a+"\""+decodeURIComponent(o[i])+"\"");
          break;
        }
      }
      return (((o.constructor===Object)?"{":"[")+"\n   "+indent + temp.join(",\n   "+indent) + "\n"+indent+((o.constructor===Object)?"}":"]"));
    }
    return "";
  },

  getBrowser: function() {
    // from DOJO, http://www.dojotoolkit.org
    var n = navigator;
		var dua = n.userAgent;
		var dav = n.appVersion;
		var tv = parseFloat(dav);
		this.isOpera = (dua.indexOf("Opera") >= 0) ? tv : 0;
		this.isSafari = 0;
		var idx = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0);
		if (idx) {
			this.isSafari = parseFloat(dav.split("Version/")[1]) || ( ( parseFloat(dav.substr(idx+7)) >= 419.3 ) ? 3 : 2 ) || 2;
		}
		this.isAIR = (dua.indexOf("AdobeAIR") >= 0) ? 1 : 0;
		this.isKhtml = (dav.indexOf("Konqueror") >= 0 || this.isSafari) ? tv : 0;
		this.isMozilla = this.isMoz = (dua.indexOf("Gecko") >= 0 && !this.isKhtml) ? tv : 0;
		this.isFF = this.isIE = 0;
		if (this.isMoz) {
			this.isFF = parseFloat(dua.split("Firefox/")[1]) || 0;
		}
		if (document.all && !this.isOpera) {
			this.isIE = parseFloat(dav.split("MSIE ")[1]) || 0;
		}
  },
  isBrowserOk: function() {
    if ((this.isSafari>=2) || (this.isFF>=2) || (this.isIE>=7)) {
      return true;
    } else {
      return false;
    }
  },

  getConfigAttributes: function() {
    var scripts = document.getElementsByTagName("script");
    for (var i=0; i<scripts.length; i++) {
      if (/polarrosewidget[0-9]*\.js/i.test(scripts[i].getAttribute("src"))) {
        this.updateConfig(this.getConfigObject(decodeURIComponent((scripts[i].src.split("?")[1]||'').replace(/=/g,":").split("&"))));
        this.updateConfig(this.getConfigObject(scripts[i].getAttribute("config")));
        break;
      }
    }
    this.updateConfig(window.polarroseconfig || window.PolarRoseConfig);
    if (this.config.partner && !/^[a-zA-Z0-9_\-]{1,25}$/.test(this.config.partner)) {
      if (window.console && window.console.error) {
        window.console.error("Polar Rose Widget config error: partner attribute '"+this.config.partner+"' doesn't follow the mask ^[a-zA-Z0-9_\-]{1,25}$, and will be ignored.");
      }
      this.config.partner = "";
    }
  },
  getConfigObject: function(cfg) {
    if (cfg) {
      try {
        return eval("({ "+cfg+" })");
      } catch(err) {
        if (window.console && window.console.error) {
          window.console.error("Polar Rose Widget config error (when evaluating config attributes).");
        }
      };
    }
    return null;
  },
  updateConfig: function(cfgo) {
    if (cfgo) {
      for (var c in this.config) {
        if ((typeof cfgo[c]) === (typeof this.config[c])) {
          this.config[c] = cfgo[c];
        } else if (typeof cfgo[c] !== "undefined") {
          if (window.console && window.console.error) {
            window.console.error("Polar Rose Widget config error: '"+c+"' is not a "+(typeof this.config[c])+".");
          }
        }
      }
    }
  },
  
  load: function() {
    this.debug("widget load");
    if (this.loaded) return;
    this.loaded = true;
    
    this.getBrowser();
    this.debug("Browser: FF "+this.isFF+", IE "+this.isIE+", Safari "+this.isSafari+", Opera "+this.isOpera
      +", Mozilla "+this.isMozilla+", Khtml "+this.isKhtml+", AIR "+this.isAIR);
    if (!this.isBrowserOk()) {
      return;
    }
    this.getConfigAttributes();
    this.debug("Config: \n"+this.format(this.config));
    
    this.backend = new PolarRoseBackend();
    this.backend.dashboard.url = "http://dashboard.polarrose.com/DashboardService/public/api";
    this.backend.widget.url = "http://widgetservice.polarrose.com/RoseletService/api";
    
    this.frontend = new PolarRoseFrontend();
    this.frontend.dashboard.url = "http://www.polarrose.com";
    this.frontend.dashboard.batchurl = "http://www.polarrose.com/signin/partner?collectionName=";
    this.frontend.dashboard.thumburl = "http://images.polarrose.com/face/50";
    this.frontend.dashboard.imageurl = "http://static.polarrose.com/widget";
    this.frontend.widget.url = "http://www.polarrose.com";
    this.frontend.widget.imageUrl = "http://static.polarrose.com/widget";
    
    this.initialized = true;
    this.run();
  },

  run: function() {
    if (this.initialized) {
      this.debug("widget run");
      if (polarrose.config.progress || (window.turnOffListeners && window.turnOnListeners)) {
        this.frontend.dashboard.buildDashboard(null,"Processing\u2026","Please note processing may take up to 1 hour.");
      }
      this.backend.dashboard.submitPage(document);
    }
  },
  
  place: function() {
    if (this.initialized) {
      this.debug("widget place");
      this.frontend.widget.publish({"what":"roseplace"});
    }
  },
  
  clear: function() {
    if (this.initialized) {
      this.debug("widget clear");
      this.frontend.widget.publish({"what":"roseremove"});
      this.frontend.dashboard.clearCatfish();
      this.frontend.dashboard.clearStyleSheet();
    }
  },
  
  show: function() {
    if (this.initialized) {
      this.debug("widget show");
      polarrose.config.dashboardvisibility = true;
      this.frontend.dashboard.setDashboardVisibility(true);
      polarrose.config.widgetvisibility = true;
      this.frontend.widget.publish({"what":"rosevisibility"});
    }
  }, 
  
  hide: function() {
    if (this.initialized) {
      this.debug("widget hide");
      polarrose.config.dashboardvisibility = false;
      this.frontend.dashboard.setDashboardVisibility(false);
      polarrose.config.widgetvisibility = false;
      this.frontend.widget.publish({"what":"rosevisibility"});
    }
  }

};

polarrose.debug("Polar Rose Widget, version: "+polarrose.version);
polarrose.debug("Page: "+document.location.href);

window.polarrosewidget.version = polarrose.version;
window.polarrosewidget.place = function(){polarrose.place();};
window.polarrosewidget.clear = function(){polarrose.clear();};
window.polarrosewidget.show = function(){polarrose.show();};
window.polarrosewidget.hide = function(){polarrose.hide();};
window.polarrosewidget.debug = function(){return polarrose.debuglog;};

//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

var isPageLoadedLoop = function() {
  if (!polarrose.loaded) {
    if (isPageLoaded()) {
      setTimeout(function(){polarrose.load();}, 100);
    } else {
      setTimeout(function(){isPageLoadedLoop();}, 1000);
    }
  }
};
var isPageLoaded = function() {
  if (document.images && document.images.length > 0) {
    for (var i=0, leni=document.images.length; i<leni; i++) {
      if (!document.images[i].complete) return false;
    }
    return true;
  }
  return false;
};
isPageLoadedLoop();

if (window.addEventListener) {
  /*document.addEventListener('DOMContentLoaded', function(e){
    //
  }, false);*/
  window.addEventListener('load', function(e){
    setTimeout(function(){polarrose.load();}, 100);
  }, false);
} else if (window.attachEvent) {
  /*document.attachEvent('onreadystatechange', function(e){
    if (/loaded|complete/.test(document.readyState)) {
      //
    }
  }, false);*/
  window.attachEvent('onload', function(e){
    setTimeout(function(){polarrose.load();}, 100);
  }, false);
};

//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

})();
}
